When running tests that can result in a vcpu being left in an indeterminate state it is useful to be able to run the test on a vcpu other than 0. This patch allows test_run to be executed on any vcpu indicated by the on_vcpu member of the svm_test struct. The initialized state of the vcpu0 registers used to populate the vmcb is carried forward to the other vcpus. Signed-off-by: Cathy Avery <cavery@xxxxxxxxxx> --- x86/svm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- x86/svm.h | 13 +++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/x86/svm.c b/x86/svm.c index 41685bf..9f7ae7e 100644 --- a/x86/svm.c +++ b/x86/svm.c @@ -367,6 +367,45 @@ test_wanted(const char *name, char *filters[], int filter_count) } } +static void set_additional_vpcu_regs(struct extra_vcpu_info *info) +{ + wrmsr(MSR_VM_HSAVE_PA, info->hsave); + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_SVME); + wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX); + write_cr3(info->cr3); + write_cr4(info->cr4); + write_cr0(info->cr0); + write_dr6(info->dr6); + write_dr7(info->dr7); + write_cr2(info->cr2); + wrmsr(MSR_IA32_CR_PAT, info->g_pat); + wrmsr(MSR_IA32_DEBUGCTLMSR, info->dbgctl); +} + +static void get_additional_vcpu_regs(struct extra_vcpu_info *info) +{ + info->hsave = rdmsr(MSR_VM_HSAVE_PA); + info->cr3 = read_cr3(); + info->cr4 = read_cr4(); + info->cr0 = read_cr0(); + info->dr7 = read_dr7(); + info->dr6 = read_dr6(); + info->cr2 = read_cr2(); + info->g_pat = rdmsr(MSR_IA32_CR_PAT); + info->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR); +} + +static void init_additional_vcpu_regs(void) +{ + int i; + struct extra_vcpu_info info; + + get_additional_vcpu_regs(&info); + + for (i = 1; i < cpu_count(); i++) + on_cpu(i, (void *)set_additional_vpcu_regs, &info); +} + int main(int ac, char **av) { int i = 0; @@ -384,6 +423,8 @@ int main(int ac, char **av) setup_svm(); + init_additional_vcpu_regs(); + vmcb = alloc_page(); for (; svm_tests[i].name != NULL; i++) { @@ -392,7 +433,13 @@ int main(int ac, char **av) if (svm_tests[i].supported && !svm_tests[i].supported()) continue; if (svm_tests[i].v2 == NULL) { - test_run(&svm_tests[i]); + if (svm_tests[i].on_vcpu) { + if (cpu_count() <= svm_tests[i].on_vcpu) + continue; + on_cpu(svm_tests[i].on_vcpu, (void *)test_run, &svm_tests[i]); + } + else + test_run(&svm_tests[i]); } else { vmcb_ident(vmcb); v2_test = &(svm_tests[i]); diff --git a/x86/svm.h b/x86/svm.h index 645deb7..d023a32 100644 --- a/x86/svm.h +++ b/x86/svm.h @@ -338,6 +338,7 @@ struct svm_test { ulong scratch; /* Alternative test interface. */ void (*v2)(void); + int on_vcpu; }; struct regs { @@ -360,6 +361,18 @@ struct regs { u64 rflags; }; +struct extra_vcpu_info { + u64 hsave; + u64 cr3; + u64 cr4; + u64 cr0; + u64 dr7; + u64 dr6; + u64 cr2; + u64 g_pat; + u64 dbgctl; +}; + typedef void (*test_guest_func)(struct svm_test *); u64 *npt_get_pte(u64 address); -- 2.20.1