[PATCH 1/3] kvm-unit-test: nSVM: Add alternative (v2) test format for nested guests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



  ..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@xxxxxxxxxx>
---
 x86/svm.c       | 75 ++++++++++++++++++++++++++++++++++++++++++---------------
 x86/svm.h       |  6 +++++
 x86/svm_tests.c |  2 ++
 3 files changed, 63 insertions(+), 20 deletions(-)

diff --git a/x86/svm.c b/x86/svm.c
index 07571e9..7ce33a6 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -110,9 +110,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();
 }
 
@@ -191,14 +198,49 @@ 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->vmcb = vmcb;
 	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;
@@ -210,19 +252,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:
@@ -303,7 +333,6 @@ extern struct svm_test svm_tests[];
 int main(int ac, char **av)
 {
 	int i = 0;
-	struct vmcb *vmcb;
 
 	setup_vm();
 	smp_init();
@@ -318,9 +347,15 @@ int main(int ac, char **av)
 	vmcb = alloc_page();
 
 	for (; svm_tests[i].name != NULL; i++) {
-		if (!svm_tests[i].supported())
-			continue;
-		test_run(&svm_tests[i], vmcb);
+		if (svm_tests[i].v2 == NULL) {
+			if (!svm_tests[i].supported())
+				continue;
+			test_run(&svm_tests[i]);
+		} else {
+			vmcb_ident(vmcb);
+			v2_test = &(svm_tests[i]);
+			svm_tests[i].v2();
+		}
 	}
 
 	return report_summary();
diff --git a/x86/svm.h b/x86/svm.h
index ccc5172..25514de 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -337,6 +337,8 @@ struct svm_test {
 	struct vmcb *vmcb;
 	int exits;
 	ulong scratch;
+	/* Alternative test interface. */
+	void (*v2)(void);
 };
 
 struct regs {
@@ -359,6 +361,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);
@@ -374,5 +378,7 @@ 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);
 
 #endif
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 264f8de..580bce6 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1195,6 +1195,8 @@ static bool pending_event_check_vmask(struct svm_test *test)
     return get_test_stage(test) == 2;
 }
 
+#define TEST(name) { #name, .v2 = name }
+
 struct svm_test svm_tests[] = {
     { "null", default_supported, default_prepare,
       default_prepare_gif_clear, null_test,
-- 
1.8.3.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux