All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nVMX: Test 'Type' and 'S' portions of Access Rights field in guest segment registers
@ 2020-11-10  1:45 Krish Sadhukhan
  0 siblings, 0 replies; only message in thread
From: Krish Sadhukhan @ 2020-11-10  1:45 UTC (permalink / raw)
  To: kvm; +Cc: jmattson, sean.j.christopherson, pbonzini

According to section "Checks on Guest Segment Registers" in Intel SDM vol 3C,
the following checks are performed on the Guest Segment Registers on vmentry
of nested guests:

    Access-rights field:
	— Bits 3:0 (Type):
	    - CS: The values allowed depend on the setting of the “unrestricted
	          guest” VM-execution control:
		    - If the control is 0, the Type must be 9, 11, 13, or 15
		      (accessed code segment).
		    - If the control is 1, the Type must be either 3 (read/write
		      accessed expand-up data segment) or one of 9, 11, 13, and
		      15 (accessed code segment).
	    - SS: If SS is usable, the Type must be 3 or 7 (read/write,
		  accessed data segment).
	    - DS, ES, FS, GS: The following checks apply if the register is
	      		      usable:
			- Bit 0 of the Type must be 1 (accessed).
			- If bit 3 of the Type is 1 (code segment), then bit 1
		  	  of the Type must be 1 (readable).
	— Bit 4 (S): If the register is CS or if the register is usable, S must
	  be 1.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
---
 x86/vmx_tests.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 165 insertions(+)

diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index d2084ae..e7481bf 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -8177,6 +8177,170 @@ static void test_guest_segment_base_addr_fields(void)
 	vmcs_write(GUEST_AR_ES, ar_saved);
 }
 
+#define TEST_SEGMENT_AR(seg, name, saved_val, mask, test_val, xfail, msg)\
+{									\
+	u32 val = (saved_val & mask) | test_val;			\
+	vmcs_write(seg, val);						\
+	test_guest_state(msg, xfail, val, name);			\
+}
+
+#define TEST_SEGMENT_AR_TYPE_HELPER(seg, name)				\
+{									\
+	u32 ar_saved = vmcs_read(seg);					\
+									\
+	TEST_SEGMENT_AR(seg, name, (ar_saved | GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK1, 0x1, false, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved | GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK1, 0x0, false, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved & ~GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK1, 0x1, false, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved & ~GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK1, 0x0, true, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved | GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK2, 0x8, false, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved | GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK2, 0x2, false, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved & ~GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK2, 0x9, true, msg);				\
+	TEST_SEGMENT_AR(seg, name, (ar_saved & ~GUEST_SEG_UNUSABLE_MASK),\
+	    AR_TYPE_MASK2, 0x3, false, msg);				\
+									\
+	vmcs_write(seg, ar_saved);					\
+}
+
+#define TEST_SEGMENT_AR_S_HELPER(seg, name)				\
+{									\
+	u32 ar_saved = vmcs_read(seg);					\
+	char msg[] = "Access_Rights[4]";				\
+									\
+	if (seg == GUEST_AR_CS) {					\
+		TEST_SEGMENT_AR(seg, name, ar_saved, AR_S_MASK, 0x10,	\
+		    false, msg);					\
+		TEST_SEGMENT_AR(seg, name, ar_saved, AR_S_MASK, ~0x10,	\
+		    true, msg);						\
+	} else {							\
+		TEST_SEGMENT_AR(seg, name, (ar_saved |			\
+		    GUEST_SEG_UNUSABLE_MASK), AR_S_MASK, 0x10, false, msg);\
+		TEST_SEGMENT_AR(seg, name, (ar_saved |			\
+		    GUEST_SEG_UNUSABLE_MASK), AR_S_MASK, 0x0, false, msg);\
+		TEST_SEGMENT_AR(seg, name, (ar_saved &			\
+		    ~GUEST_SEG_UNUSABLE_MASK), AR_S_MASK, 0x10, false, msg);\
+		TEST_SEGMENT_AR(seg, name, (ar_saved &			\
+		    ~GUEST_SEG_UNUSABLE_MASK), AR_S_MASK, 0x0, true, msg);\
+	}								\
+	vmcs_write(seg, ar_saved);					\
+}
+
+/*
+ * The following checks are done on the Access Rights field of the Guest
+ * Segment Registers:
+ *
+ * Bits 3:0 (Type):
+ *   CS:
+ *     - If the “unrestricted guest" VM-execution control is 0, value must be
+ *       9, 11, 13, or 15.
+ *     - If the “unrestricted guest" VM-execution control is 1, value must be
+ *       either 3 or one of 9, 11, 13, and 15.
+ *   SS:
+ *     - If SS is usable, the Type must be 3 or 7.
+ *   DS, ES, FS, GS:
+ *     - If the register is usable, bit 0 of the Type must be 1 and if bit 3
+ *	 of the Type is 1, then bit 1 of the Type must be 1.
+ *
+ * Bit 4 (S): If the register is CS or if the register is usable, S must be 1.
+ *
+ *  [Intel SDM]
+ */
+static void test_guest_segment_ar_fields(void)
+{
+	/*
+	 * Type [3:0] of CS
+	 */
+	u32 ar_saved = vmcs_read(GUEST_AR_CS);
+	char msg[] = "Access_Rights[3:0]";
+
+#define	AR_TYPE_MASK	~0xf
+#define	AR_TYPE_MASK1	~0x1
+#define	AR_TYPE_MASK2	~0xa
+
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0x9, false, msg);
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0xb, false, msg);
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0xd, false, msg);
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0xf, false, msg);
+
+	/* Turn off "unrestricted guest" vm-execution control */
+	u32 cpu_ctrl0_saved = vmcs_read(CPU_EXEC_CTRL0);
+	u32 cpu_ctrl1_saved = vmcs_read(CPU_EXEC_CTRL1);
+	if (cpu_ctrl1_saved | CPU_URG)
+		vmcs_write(CPU_EXEC_CTRL1, cpu_ctrl1_saved & ~CPU_URG);
+
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0x3, false, msg);
+
+	/* Turn on "unrestricted guest" vm-execution control */
+	vmcs_write(CPU_EXEC_CTRL0, cpu_ctrl0_saved | CPU_SECONDARY);
+	vmcs_write(CPU_EXEC_CTRL1, cpu_ctrl1_saved | CPU_URG);
+	/* EPT and EPTP must be setup when "unrestricted guest" is on */
+	setup_ept(false);
+
+	TEST_SEGMENT_AR(GUEST_AR_CS, "GUEST_AR_CS", ar_saved,
+	    AR_TYPE_MASK, 0x3, false, msg);
+
+	vmcs_write(GUEST_AR_CS, ar_saved);
+	vmcs_write(CPU_EXEC_CTRL0, cpu_ctrl0_saved);
+	vmcs_write(CPU_EXEC_CTRL1, cpu_ctrl1_saved);
+
+	/*
+	 * Type [3:0] of SS
+	 */
+	ar_saved = vmcs_read(GUEST_AR_SS);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved |
+	    GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x3, false, msg);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved |
+	    GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x7, false, msg);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved |
+	    GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x0, false, msg);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved &
+	    ~GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x3, false, msg);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved &
+	    ~GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x7, false, msg);
+
+	TEST_SEGMENT_AR(GUEST_AR_SS, "GUEST_AR_SS", (ar_saved &
+	    ~GUEST_SEG_UNUSABLE_MASK), AR_TYPE_MASK, 0x0, true, msg);
+
+	vmcs_write(GUEST_AR_SS, ar_saved);
+
+	/*
+	 * Type [3:0] of DS, ES, FS and GS
+	 */
+	TEST_SEGMENT_AR_TYPE_HELPER(GUEST_AR_DS, "GUEST_AR_DS");
+	TEST_SEGMENT_AR_TYPE_HELPER(GUEST_AR_ES, "GUEST_AR_ES");
+	TEST_SEGMENT_AR_TYPE_HELPER(GUEST_AR_FS, "GUEST_AR_FS");
+	TEST_SEGMENT_AR_TYPE_HELPER(GUEST_AR_GS, "GUEST_AR_GS");
+
+	/*
+	 * S [4] of CS, SS, DS, ES, FS and GS
+	 */
+#define	AR_S_MASK	~0x10
+
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_CS, "GUEST_AR_CS");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_CS, "GUEST_AR_CS");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_SS, "GUEST_AR_SS");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_DS, "GUEST_AR_DS");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_ES, "GUEST_AR_ES");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_FS, "GUEST_AR_FS");
+	TEST_SEGMENT_AR_S_HELPER(GUEST_AR_GS, "GUEST_AR_GS");
+}
+
 /*
  * Check that the virtual CPU checks the VMX Guest State Area as
  * documented in the Intel SDM.
@@ -8201,6 +8365,7 @@ static void vmx_guest_state_area_test(void)
 
 	test_guest_segment_sel_fields();
 	test_guest_segment_base_addr_fields();
+	test_guest_segment_ar_fields();
 
 	test_canonical(GUEST_BASE_GDTR, "GUEST_BASE_GDTR", false);
 	test_canonical(GUEST_BASE_IDTR, "GUEST_BASE_IDTR", false);
-- 
2.18.4


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-10  1:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-10  1:45 [PATCH] nVMX: Test 'Type' and 'S' portions of Access Rights field in guest segment registers Krish Sadhukhan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.