[PATCH kvm-unit-tests 2/2] x86: vmx: test invalid type for INVVPID

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

 



Test that it does not cause an infinite stream of vmexits.
The test is not relying on INVVPID doing anything, so it is
not necessary to fall back from SINGLE to ALL like
vpid_sync does.  Therefore I am just changing the test
to try three INVVPID instructions.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 x86/vmx.h       | 10 ++++++++--
 x86/vmx_tests.c | 39 +++++++++++++++++++++++++++++++++------
 2 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/x86/vmx.h b/x86/vmx.h
index 146f082..d6bc217 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -495,6 +495,7 @@ enum Ctrl1 {
 #define INVEPT_SINGLE		1
 #define INVEPT_GLOBAL		2
 
+#define INVVPID_SINGLE_ADDRESS	0
 #define INVVPID_SINGLE		1
 #define INVVPID_ALL		2
 
@@ -562,14 +563,19 @@ static inline bool invept(unsigned long type, u64 eptp)
 	return ret;
 }
 
-static inline void invvpid(unsigned long type, u16 vpid, u64 gva)
+static inline bool invvpid(unsigned long type, u16 vpid, u64 gva)
 {
+	bool ret;
+	u64 rflags = read_rflags() | X86_EFLAGS_CF | X86_EFLAGS_ZF;
+
 	struct {
 		u64 vpid : 16;
 		u64 rsvd : 48;
 		u64 gva;
 	} operand = {vpid, 0, gva};
-	asm volatile("invvpid %0, %1\n" ::"m"(operand),"r"(type));
+	asm volatile("push %1; popf; invvpid %2, %3; setbe %0"
+		     : "=q" (ret) : "r" (rflags), "m"(operand),"r"(type) : "cc");
+	return ret;
 }
 
 void print_vmexit_info();
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index dd3af58..71c571c 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -1169,6 +1169,24 @@ static int ept_exit_handler()
 	return VMX_TEST_VMEXIT;
 }
 
+bool invvpid_test(int type, u16 vpid)
+{
+	bool ret, supported;
+
+	supported = ept_vpid.val & (VPID_CAP_INVVPID_SINGLE >> INVVPID_SINGLE << type);
+	ret = invvpid(type, vpid, 0);
+
+	if (ret == !supported)
+		return false;
+
+	if (!supported)
+		printf("WARNING: unsupported invvpid passed!\n");
+	else
+		printf("WARNING: invvpid failed!\n");
+
+	return true;
+}
+
 static int vpid_init()
 {
 	u32 ctrl_cpu1;
@@ -1189,10 +1207,13 @@ static void vpid_main()
 {
 	vmx_set_test_stage(0);
 	vmcall();
-	report("INVVPID SINGLE", vmx_get_test_stage() == 0);
-	vmx_set_test_stage(1);
+	report("INVVPID SINGLE ADDRESS", vmx_get_test_stage() == 1);
+	vmx_set_test_stage(2);
 	vmcall();
-	report("INVVPID ALL", vmx_get_test_stage() == 1);
+	report("INVVPID SINGLE", vmx_get_test_stage() == 3);
+	vmx_set_test_stage(4);
+	vmcall();
+	report("INVVPID ALL", vmx_get_test_stage() == 5);
 }
 
 static int vpid_exit_handler()
@@ -1209,10 +1230,16 @@ static int vpid_exit_handler()
 	case VMX_VMCALL:
 		switch(vmx_get_test_stage()) {
 		case 0:
-			vpid_sync(INVVPID_SINGLE, 1);
+			if (!invvpid_test(INVVPID_SINGLE_ADDRESS, 1))
+				vmx_inc_test_stage();
 			break;
-		case 1:
-			vpid_sync(INVVPID_ALL, 1);
+		case 2:
+			if (!invvpid_test(INVVPID_SINGLE, 1))
+				vmx_inc_test_stage();
+			break;
+		case 4:
+			if (!invvpid_test(INVVPID_ALL, 1))
+				vmx_inc_test_stage();
 			break;
 		default:
 			printf("ERROR: unexpected stage, %d\n",
-- 
2.5.0

--
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