aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrish Sadhukhan <krish.sadhukhan@oracle.com>2020-03-17 13:05:35 -0700
committerPaolo Bonzini <pbonzini@redhat.com>2020-03-18 13:17:40 +0100
commit8660d1b52c940db56261422350ba356e1cc32951 (patch)
tree44bc13489b3bd72a41669bde4d988f8e51e49eb8
parent096cf7fec5cab2c1e337816e7e22bc576a9434c1 (diff)
downloadkvm-unit-tests-8660d1b52c940db56261422350ba356e1cc32951.tar.gz
kvm-unit-test: nSVM: Add alternative (v2) test format for nested guests
..so that we can add tests such as VMCB consistency tests, that require the tests to only proceed up to the execution of the first guest (nested) instruction and do not require us to define all the functions that the current format dictates. Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--x86/svm.c74
-rw-r--r--x86/svm.h6
-rw-r--r--x86/svm_tests.c2
3 files changed, 64 insertions, 18 deletions
diff --git a/x86/svm.c b/x86/svm.c
index a014adb..41685bf 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -112,9 +112,16 @@ inline void vmmcall(void)
asm volatile ("vmmcall" : : : "memory");
}
+static test_guest_func guest_main;
+
+void test_set_guest(test_guest_func func)
+{
+ guest_main = func;
+}
+
static void test_thunk(struct svm_test *test)
{
- test->guest_func(test);
+ guest_main(test);
vmmcall();
}
@@ -193,13 +200,48 @@ struct regs get_regs(void)
#define LOAD_GPR_C SAVE_GPR_C
-static void test_run(struct svm_test *test, struct vmcb *vmcb)
+struct svm_test *v2_test;
+struct vmcb *vmcb;
+
+#define ASM_VMRUN_CMD \
+ "vmload %%rax\n\t" \
+ "mov regs+0x80, %%r15\n\t" \
+ "mov %%r15, 0x170(%%rax)\n\t" \
+ "mov regs, %%r15\n\t" \
+ "mov %%r15, 0x1f8(%%rax)\n\t" \
+ LOAD_GPR_C \
+ "vmrun %%rax\n\t" \
+ SAVE_GPR_C \
+ "mov 0x170(%%rax), %%r15\n\t" \
+ "mov %%r15, regs+0x80\n\t" \
+ "mov 0x1f8(%%rax), %%r15\n\t" \
+ "mov %%r15, regs\n\t" \
+ "vmsave %%rax\n\t" \
+
+u64 guest_stack[10000];
+
+int svm_vmrun(void)
+{
+ vmcb->save.rip = (ulong)test_thunk;
+ vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
+ regs.rdi = (ulong)v2_test;
+
+ asm volatile (
+ ASM_VMRUN_CMD
+ :
+ : "a" (virt_to_phys(vmcb))
+ : "memory");
+
+ return (vmcb->control.exit_code);
+}
+
+static void test_run(struct svm_test *test)
{
u64 vmcb_phys = virt_to_phys(vmcb);
- u64 guest_stack[10000];
irq_disable();
test->prepare(test);
+ guest_main = test->guest_func;
vmcb->save.rip = (ulong)test_thunk;
vmcb->save.rsp = (ulong)(guest_stack + ARRAY_SIZE(guest_stack));
regs.rdi = (ulong)test;
@@ -211,19 +253,7 @@ static void test_run(struct svm_test *test, struct vmcb *vmcb)
"sti \n\t"
"call *%c[PREPARE_GIF_CLEAR](%[test]) \n \t"
"mov %[vmcb_phys], %%rax \n\t"
- "vmload %%rax\n\t"
- "mov regs+0x80, %%r15\n\t" // rflags
- "mov %%r15, 0x170(%%rax)\n\t"
- "mov regs, %%r15\n\t" // rax
- "mov %%r15, 0x1f8(%%rax)\n\t"
- LOAD_GPR_C
- "vmrun %%rax\n\t"
- SAVE_GPR_C
- "mov 0x170(%%rax), %%r15\n\t" // rflags
- "mov %%r15, regs+0x80\n\t"
- "mov 0x1f8(%%rax), %%r15\n\t" // rax
- "mov %%r15, regs\n\t"
- "vmsave %%rax\n\t"
+ ASM_VMRUN_CMD
"cli \n\t"
"stgi"
: // inputs clobbered by the guest:
@@ -357,9 +387,17 @@ int main(int ac, char **av)
vmcb = alloc_page();
for (; svm_tests[i].name != NULL; i++) {
- if (!test_wanted(svm_tests[i].name, av, ac) || !svm_tests[i].supported())
+ if (!test_wanted(svm_tests[i].name, av, ac))
+ continue;
+ if (svm_tests[i].supported && !svm_tests[i].supported())
continue;
- test_run(&svm_tests[i], vmcb);
+ if (svm_tests[i].v2 == NULL) {
+ test_run(&svm_tests[i]);
+ } else {
+ vmcb_ident(vmcb);
+ v2_test = &(svm_tests[i]);
+ svm_tests[i].v2();
+ }
}
if (!matched)
diff --git a/x86/svm.h b/x86/svm.h
index 599050e..645deb7 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -336,6 +336,8 @@ struct svm_test {
bool (*succeeded)(struct svm_test *test);
int exits;
ulong scratch;
+ /* Alternative test interface. */
+ void (*v2)(void);
};
struct regs {
@@ -358,6 +360,8 @@ struct regs {
u64 rflags;
};
+typedef void (*test_guest_func)(struct svm_test *);
+
u64 *npt_get_pte(u64 address);
u64 *npt_get_pde(u64 address);
u64 *npt_get_pdpe(void);
@@ -373,6 +377,8 @@ void inc_test_stage(struct svm_test *test);
void vmcb_ident(struct vmcb *vmcb);
struct regs get_regs(void);
void vmmcall(void);
+int svm_vmrun(void);
+void test_set_guest(test_guest_func func);
extern struct vmcb *vmcb;
extern struct svm_test svm_tests[];
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 3eef913..f1945ee 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1340,6 +1340,8 @@ static bool interrupt_check(struct svm_test *test)
return get_test_stage(test) == 5;
}
+#define TEST(name) { #name, .v2 = name }
+
struct svm_test svm_tests[] = {
{ "null", default_supported, default_prepare,
default_prepare_gif_clear, null_test,