// SPDX-License-Identifier: GPL-2.0 /* * Check for KVM_GET_REG_LIST regressions. * * Copyright (C) 2020, Red Hat, Inc. * * When attempting to migrate from a host with an older kernel to a host * with a newer kernel we allow the newer kernel on the destination to * list new registers with get-reg-list. We assume they'll be unused, at * least until the guest reboots, and so they're relatively harmless. * However, if the destination host with the newer kernel is missing * registers which the source host with the older kernel has, then that's * a regression in get-reg-list. This test checks for that regression by * checking the current list against a blessed list. We should never have * missing registers, but if new ones appear then they can probably be * added to the blessed list. A completely new blessed list can be created * by running the test with the --list command line argument. * * The blessed list should be created from the oldest possible kernel.
*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include"kvm_util.h" #include"test_util.h" #include"processor.h"
n = 0;
for_each_sublist(c, s) { for (i = 0; i < s->regs_n; ++i)
blessed_reg[n++] = s->regs[i];
}
/* * We only test that we can get the register and then write back the * same value. Some registers may allow other values to be written * back, but others only allow some bits to be changed, and at least * for ID registers set will fail if the value does not exactly match * what was returned by get. If registers that allow other values to * be written need to have the other values tested, then we should * create a new set of tests for those in a new independent test * executable. * * Only do the get/set tests on present, blessed list registers, * since we don't know the capabilities of any new registers.
*/
for_each_present_blessed_reg(i) {
uint8_t addr[2048 / 8]; struct kvm_one_reg reg = {
.id = reg_list->reg[i],
.addr = (__u64)&addr,
}; bool reject_reg = false, skip_reg = false; int ret;
ret = __vcpu_get_reg(vcpu, reg_list->reg[i], &addr); if (ret) {
printf("%s: Failed to get ", config_name(c));
print_reg(config_name(c), reg.id);
putchar('\n');
++failed_get;
}
for_each_sublist(c, s) { /* rejects_set registers are rejected for set operation */ if (s->rejects_set && find_reg(s->rejects_set, s->rejects_set_n, reg.id)) {
reject_reg = true;
ret = __vcpu_ioctl(vcpu, KVM_SET_ONE_REG, ®); if (ret != -1 || !check_reject_set(errno)) {
printf("%s: Failed to reject (ret=%d, errno=%d) ", config_name(c), ret, errno);
print_reg(config_name(c), reg.id);
putchar('\n');
++failed_reject;
} break;
}
/* skips_set registers are skipped for set operation */ if (s->skips_set && find_reg(s->skips_set, s->skips_set_n, reg.id)) {
skip_reg = true;
++skipped_set; break;
}
}
if (!reject_reg && !skip_reg) {
ret = __vcpu_ioctl(vcpu, KVM_SET_ONE_REG, ®); if (ret) {
printf("%s: Failed to set ", config_name(c));
print_reg(config_name(c), reg.id);
putchar('\n');
++failed_set;
}
}
}
for_each_new_reg(i)
++new_regs;
for_each_missing_reg(i)
++missing_regs;
if (new_regs || missing_regs) {
n = 0;
for_each_reg_filtered(i)
++n;
if (new_regs) {
printf("\n%s: There are %d new registers.\n" "Consider adding them to the blessed reg " "list with the following lines:\n\n", config_name(c), new_regs);
for_each_new_reg(i)
print_reg(config_name(c), reg_list->reg[i]);
putchar('\n');
}
if (missing_regs) {
printf("\n%s: There are %d missing registers.\n" "The following lines are missing registers:\n\n", config_name(c), missing_regs);
for_each_missing_reg(i)
print_reg(config_name(c), blessed_reg[i]);
putchar('\n');
}
staticvoid help(void)
{ struct vcpu_reg_list *c; int i;
printf( "\n" "usage: get-reg-list [--config=] [--list] [--list-filtered]\n\n" " --config= Used to select a specific vcpu configuration for the test/listing\n" " '' may be\n");
for (i = 0; i < vcpu_configs_n; ++i) {
c = vcpu_configs[i];
printf( " '%s'\n", config_name(c));
}
printf( "\n" " --list Print the register list rather than test it (requires --config)\n" " --list-filtered Print registers that would normally be filtered out (requires --config)\n" "\n"
);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.