[PATCH] kvm-unit-tests: VMX: Test MSR load/store feature

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

 



This checks some usage cases of VMX MSR load/store feature:
1) VM-entry MSR-load area is correctly filled
2) VM-exit MSR-store area is correctly filled
3) VM-exit MSR-load area is correctly filled
4) Attempt to load MSR_FS_BASE on VM entry (must generate
VM-entry failure due to MSR loading)

Signed-off-by: Eugene Korenevsky <ekorenevsky@xxxxxxxxx>
---
 x86/vmx_tests.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 184fafc..913904a 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -1525,6 +1525,80 @@ static int dbgctls_exit_handler(void)
 	return VMX_TEST_VMEXIT;
 }
 
+struct vmx_msr_entry {
+	u32 index;
+	u32 reserved;
+	u64 value;
+} __attribute__((packed));
+
+#define MSR_MAGIC 0x31415926
+struct vmx_msr_entry *exit_msr_store, *entry_msr_load, *exit_msr_load;
+
+static int msr_switch_init(struct vmcs *vmcs)
+{
+	msr_bmp_init();
+	exit_msr_store = alloc_page();
+	exit_msr_load = alloc_page();
+	entry_msr_load = alloc_page();
+	memset(exit_msr_store, 0, PAGE_SIZE);
+	memset(exit_msr_load, 0, PAGE_SIZE);
+	memset(entry_msr_load, 0, PAGE_SIZE);
+	entry_msr_load[0].index = MSR_KERNEL_GS_BASE;
+	entry_msr_load[0].value = MSR_MAGIC;
+
+	vmx_set_test_stage(1);
+	vmcs_write(ENT_MSR_LD_CNT, 1);
+	vmcs_write(ENTER_MSR_LD_ADDR, (u64)entry_msr_load);
+	vmcs_write(EXI_MSR_ST_CNT, 1);
+	vmcs_write(EXIT_MSR_ST_ADDR, (u64)exit_msr_store);
+	vmcs_write(EXI_MSR_LD_CNT, 1);
+	vmcs_write(EXIT_MSR_LD_ADDR, (u64)exit_msr_load);
+	return VMX_TEST_START;
+}
+
+static void msr_switch_main()
+{
+	if (vmx_get_test_stage() == 1) {
+		report("VM entry MSR load",
+			rdmsr(MSR_KERNEL_GS_BASE) == MSR_MAGIC);
+		vmx_set_test_stage(2);
+		wrmsr(MSR_KERNEL_GS_BASE, MSR_MAGIC + 1);
+		exit_msr_store[0].index = MSR_KERNEL_GS_BASE;
+		exit_msr_load[0].index = MSR_KERNEL_GS_BASE;
+		exit_msr_load[0].value = MSR_MAGIC + 2;
+	}
+	vmcall();
+}
+
+static int msr_switch_exit_handler()
+{
+	ulong reason;
+
+	reason = vmcs_read(EXI_REASON);
+	switch (reason) {
+	case 0x80000000 | VMX_FAIL_MSR:
+		if (vmx_get_test_stage() == 3) {
+			report("VM entry MSR load: try to load FS_BASE",
+				vmcs_read(EXI_QUALIFICATION) == 1);
+			return VMX_TEST_VMEXIT;
+		}
+		break;
+	case VMX_VMCALL:
+		if (vmx_get_test_stage() == 2) {
+			report("VM exit MSR store",
+				exit_msr_store[0].value == MSR_MAGIC + 1);
+			report("VM exit MSR load",
+				rdmsr(MSR_KERNEL_GS_BASE) == MSR_MAGIC + 2);
+			vmx_set_test_stage(3);
+			entry_msr_load[0].index = MSR_FS_BASE;
+			return VMX_TEST_RESUME;
+		}
+	}
+	printf("ERROR %s: unexpected stage=%u or reason=%lu\n",
+		__func__, vmx_get_test_stage(), reason);
+	return VMX_TEST_EXIT;
+}
+
 /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */
 struct vmx_test vmx_tests[] = {
 	{ "null", NULL, basic_guest_main, basic_exit_handler, NULL, {0} },
@@ -1546,5 +1620,7 @@ struct vmx_test vmx_tests[] = {
 		interrupt_exit_handler, NULL, {0} },
 	{ "debug controls", dbgctls_init, dbgctls_main, dbgctls_exit_handler,
 		NULL, {0} },
+	{ "MSR switch", msr_switch_init, msr_switch_main,
+		msr_switch_exit_handler, NULL, {0} },
 	{ NULL, NULL, NULL, NULL, NULL, {0} },
 };
-- 
2.0.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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