Skip to contentSkip to conversation

nVMX: 5-level nested EPT support

PATCH Applied Sean Christopherson 2 participants 7 messages Feb 7, 2020 – Jun 22, 2020 KVM

lore
Share & tools
lore
#0 lore raw

cover nVMX: 5-level nested EPT support

Add support for 5-level nested EPT and clean up the test for MSR_IA32_VMX_EPT_VPID_CAP in the process.

Sean Christopherson (4):
nVMX: Extend EPTP test to allow 5-level EPT
nVMX: Refactor the EPT/VPID MSR cap check to make it readable
nVMX: Mark bit 39 of MSR_IA32_VMX_EPT_VPID_CAP as reserved
nVMX: Extend EPT cap MSR test to allow 5-level EPT

 x86/vmx.c       | 21 ++++++++++++++++++++-
 x86/vmx.h       |  4 +++-
 x86/vmx_tests.c | 12 ++++++++----
 3 files changed, 31 insertions(+), 6 deletions(-)
Signature · 1 line
2.24.1
#1 lore raw

PATCH 1/4 nVMX: Extend EPTP test to allow 5-level EPT

Modify the EPTP test to expect success when the EPTP is configured for 5-level page walks and 5-level walks are enumerated as supported by the EPT capabilities MSR. KVM is in the process of gaining support for 5-level nested EPT[*].

[*] https://lkml.kernel.org/r/[email protected]

---
 x86/vmx.h       |  1 +
 x86/vmx_tests.c | 12 ++++++++----
 2 files changed, 9 insertions(+), 4 deletions(-)
x86/vmx.h +1 -0
index 6214400..e8035fc 100644
@@ -581,6 +581,7 @@ enum vm_instruction_error_number {
 
 #define EPT_CAP_WT		1ull
 #define EPT_CAP_PWL4		(1ull << 6)
+#define EPT_CAP_PWL5		(1ull << 7)
 #define EPT_CAP_UC		(1ull << 8)
 #define EPT_CAP_WB		(1ull << 14)
 #define EPT_CAP_2M_PAGE		(1ull << 16)
x86/vmx_tests.c +8 -4
index b31c360..bae1496 100644
@@ -4669,8 +4669,8 @@ static void test_eptp_ad_bit(u64 eptp, bool ctrl)
  *
  *     - The EPT memory type (bits 2:0) must be a value supported by the
  *	 processor as indicated in the IA32_VMX_EPT_VPID_CAP MSR.
- *     - Bits 5:3 (1 less than the EPT page-walk length) must be 3,
- *	 indicating an EPT page-walk length of 4.
+ *     - Bits 5:3 (1 less than the EPT page-walk length) must indicate a
+ *	 supported EPT page-walk length.
  *     - Bit 6 (enable bit for accessed and dirty flags for EPT) must be
  *	 0 if bit 21 of the IA32_VMX_EPT_VPID_CAP MSR is read as 0,
  *	 indicating that the processor does not support accessed and dirty
@@ -4710,6 +4710,9 @@ static void test_ept_eptp(void)
 	if (msr & EPT_CAP_WB)
 		wr_bk = true;
 
+	/* Support for 4-level EPT is mandatory. */
+	report(msr & EPT_CAP_PWL4, "4-level EPT support check");
+
 	primary |= CPU_SECONDARY;
 	vmcs_write(CPU_EXEC_CTRL0, primary);
 	secondary |= CPU_EPT;
@@ -4751,12 +4754,13 @@ static void test_ept_eptp(void)
 	eptp = (eptp & ~EPT_MEM_TYPE_MASK) | 6ul;
 
 	/*
-	 * Page walk length (bits 5:3)
+	 * Page walk length (bits 5:3).  Note, the value in VMCS.EPTP "is 1
+	 * less than the EPT page-walk length".
 	 */
 	for (i = 0; i < 8; i++) {
 		eptp = (eptp & ~EPTP_PG_WALK_LEN_MASK) |
 		    (i << EPTP_PG_WALK_LEN_SHIFT);
-		if (i == 3)
+		if (i == 3 || (i == 4 && (msr & EPT_CAP_PWL5)))
 			ctrl = true;
 		else
 			ctrl = false;
Signature · 1 line
2.24.1
#2 lore raw

PATCH 2/4 nVMX: Refactor the EPT/VPID MSR cap check to make it readable

In reply to Sean Christopherson

Use the EPT_CAP_* and VPID_CAP_* defines to declare which bits are reserved in MSR_IA32_VMX_EPT_VPID_CAP. Encoding the reserved bits in a 64-bit literal is difficult to read, even more difficult to update, and error prone, as evidenced by the check allowing bit 39 to be '1', despite it being reserved to zero in Intel's SDM.

No functional change intended.

---
 x86/vmx.c | 21 ++++++++++++++++++++-
 x86/vmx.h |  3 ++-
 2 files changed, 22 insertions(+), 2 deletions(-)
x86/vmx.c +20 -1
index 0f2521b..3a99d27 100644
@@ -1537,8 +1537,27 @@ static void test_vmx_caps(void)
 	       (val & 0xfffffffffffffc01Ull) == 0,
 	       "MSR_IA32_VMX_VMCS_ENUM");
 
+	fixed0 = -1ull;
+	fixed0 &= ~(EPT_CAP_WT |
+		    EPT_CAP_PWL4 |
+		    EPT_CAP_UC |
+		    EPT_CAP_WB |
+		    EPT_CAP_2M_PAGE |
+		    EPT_CAP_1G_PAGE |
+		    EPT_CAP_INVEPT |
+		    EPT_CAP_AD_FLAG |
+		    EPT_CAP_ADV_EPT_INFO |
+		    EPT_CAP_INVEPT_SINGLE |
+		    EPT_CAP_INVEPT_ALL |
+		    VPID_CAP_INVVPID |
+		    (1ull << 39) |
+		    VPID_CAP_INVVPID_ADDR |
+		    VPID_CAP_INVVPID_CXTGLB |
+		    VPID_CAP_INVVPID_ALL |
+		    VPID_CAP_INVVPID_CXTLOC);
+
 	val = rdmsr(MSR_IA32_VMX_EPT_VPID_CAP);
-	report((val & 0xfffff07ef98cbebeUll) == 0,
+	report((val & fixed0) == 0,
 	       "MSR_IA32_VMX_EPT_VPID_CAP");
 }
 
x86/vmx.h +2 -1
index e8035fc..44f0fdd 100644
@@ -587,9 +587,10 @@ enum vm_instruction_error_number {
 #define EPT_CAP_2M_PAGE		(1ull << 16)
 #define EPT_CAP_1G_PAGE		(1ull << 17)
 #define EPT_CAP_INVEPT		(1ull << 20)
+#define EPT_CAP_AD_FLAG		(1ull << 21)
+#define EPT_CAP_ADV_EPT_INFO	(1ull << 22)
 #define EPT_CAP_INVEPT_SINGLE	(1ull << 25)
 #define EPT_CAP_INVEPT_ALL	(1ull << 26)
-#define EPT_CAP_AD_FLAG		(1ull << 21)
 #define VPID_CAP_INVVPID	(1ull << 32)
 #define VPID_CAP_INVVPID_ADDR   (1ull << 40)
 #define VPID_CAP_INVVPID_CXTGLB (1ull << 41)
Signature · 1 line
2.24.1
#3 lore raw

PATCH 3/4 nVMX: Mark bit 39 of MSR_IA32_VMX_EPT_VPID_CAP as reserved

In reply to Sean Christopherson

Remove bit 39, which is defined as reserved in Intel's SDM, from the set of allowed-1 bits in MSR_IA32_VMX_EPT_VPID_CAP.

Fixes 69c8d31 ("VMX: Validate capability MSRs")
---
 x86/vmx.c | 1 -
 1 file changed, 1 deletion(-)
x86/vmx.c +0 -1
index 3a99d27..ac4aa56 100644
@@ -1550,7 +1550,6 @@ static void test_vmx_caps(void)
 		    EPT_CAP_INVEPT_SINGLE |
 		    EPT_CAP_INVEPT_ALL |
 		    VPID_CAP_INVVPID |
-		    (1ull << 39) |
 		    VPID_CAP_INVVPID_ADDR |
 		    VPID_CAP_INVVPID_CXTGLB |
 		    VPID_CAP_INVVPID_ALL |
Signature · 1 line
2.24.1
#4 lore raw

PATCH 4/4 nVMX: Extend EPT cap MSR test to allow 5-level EPT

In reply to Sean Christopherson

Modify the EMSR_IA32_VMX_EPT_VPID_CAP test to mark the 5-level EPT cap bit as allowed-1. KVM is in the process of gaining support for 5-level nested EPT[*].

[*] https://lkml.kernel.org/r/[email protected]

---
 x86/vmx.c | 1 +
 1 file changed, 1 insertion(+)
x86/vmx.c +1 -0
index ac4aa56..a15c2be 100644
@@ -1540,6 +1540,7 @@ static void test_vmx_caps(void)
 	fixed0 = -1ull;
 	fixed0 &= ~(EPT_CAP_WT |
 		    EPT_CAP_PWL4 |
+		    EPT_CAP_PWL5 |
 		    EPT_CAP_UC |
 		    EPT_CAP_WB |
 		    EPT_CAP_2M_PAGE |
Signature · 1 line
2.24.1
#5 lore raw
In reply to Sean Christopherson

Ping. These still apply cleanly on master and are required to get unit tests passing on systems with 5-level paging.

Quoted 17 lines · Sean Christopherson

Add support for 5-level nested EPT and clean up the test for MSR_IA32_VMX_EPT_VPID_CAP in the process.

Sean Christopherson (4):
nVMX: Extend EPTP test to allow 5-level EPT
nVMX: Refactor the EPT/VPID MSR cap check to make it readable
nVMX: Mark bit 39 of MSR_IA32_VMX_EPT_VPID_CAP as reserved
nVMX: Extend EPT cap MSR test to allow 5-level EPT

 x86/vmx.c       | 21 ++++++++++++++++++++-
 x86/vmx.h       |  4 +++-
 x86/vmx_tests.c | 12 ++++++++----
 3 files changed, 31 insertions(+), 6 deletions(-)
Signature · 1 line
2.24.1
maintainer Applied
#6 lore raw
Quoted 22 lines · Sean Christopherson

Ping. These still apply cleanly on master and are required to get unit tests passing on systems with 5-level paging.

Quoted 17 lines · Sean Christopherson

Add support for 5-level nested EPT and clean up the test for MSR_IA32_VMX_EPT_VPID_CAP in the process.

Sean Christopherson (4):
nVMX: Extend EPTP test to allow 5-level EPT
nVMX: Refactor the EPT/VPID MSR cap check to make it readable
nVMX: Mark bit 39 of MSR_IA32_VMX_EPT_VPID_CAP as reserved
nVMX: Extend EPT cap MSR test to allow 5-level EPT

 x86/vmx.c       | 21 ++++++++++++++++++++-
 x86/vmx.h       |  4 +++-
 x86/vmx_tests.c | 12 ++++++++----
 3 files changed, 31 insertions(+), 6 deletions(-)
Signature · 1 line
2.24.1

Applied, thanks.

Paolo