[2/2,v2,kvm-unit-test] nVMX x86: Check PML and EPT on vmentry of L2 guests
diff mbox series

Message ID 20180927183328.9945-3-krish.sadhukhan@oracle.com
State New
Headers show
Series
  • [1/2,v2] nVMX x86: Make nested_vmx_check_pml_controls() concise
Related show

Commit Message

Krish Sadhukhan Sept. 27, 2018, 6:33 p.m. UTC
According to section "Checks on VMX Controls" in Intel SDM vol 3C, the
following check needs to be enforced on vmentry of L2 guests:

    If the "enable PML" VM-execution control is 1, the "enable EPT"
    VM-execution control must also be 1. In addition, the PML address
    must satisfy the following checks:

      — Bits 11:0 of the address must be 0.
      — The address should not set any bits beyond the processor’s
	physical-address width.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
Reviewed-by: Mark Kanda <mark.kanda@oracle.com>
---
 x86/vmx_tests.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 0e9d900..3b7406a 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -3869,7 +3869,8 @@  static void test_posted_intr(void)
 	test_pi_desc_addr(0x00, true);
 	test_pi_desc_addr(0xc000, true);
 
-	test_vmcs_page_values("process-posted interrupts", POSTED_INTR_DESC_ADDR, false, false);
+	test_vmcs_page_values("process-posted interrupts",
+	    POSTED_INTR_DESC_ADDR, false, false);
 
 	vmcs_write(CPU_EXEC_CTRL0, saved_primary);
 	vmcs_write(CPU_EXEC_CTRL1, saved_secondary);
@@ -4408,6 +4409,62 @@  done:
 	vmcs_write(PIN_CONTROLS, pin_ctrls);
 }
 
+/*
+ * If the “enable PML” VM-execution control is 1, the “enable EPT”
+ * VM-execution control must also be 1. In addition, the PML address
+ * must satisfy the following checks:
+ *
+ *    — Bits 11:0 of the address must be 0.
+ *    — The address should not set any bits beyond the processor’s
+ *	physical-address width.
+ *
+ *  [Intel SDM]
+ */
+static void test_pml(void)
+{
+	u32 primary_saved = vmcs_read(CPU_EXEC_CTRL0);
+	u32 secondary_saved = vmcs_read(CPU_EXEC_CTRL1);
+	u32 primary = primary_saved;
+	u32 secondary = secondary_saved;
+
+	if (!((ctrl_cpu_rev[0].clr & CPU_SECONDARY) &&
+	    (ctrl_cpu_rev[1].clr & CPU_EPT) && (ctrl_cpu_rev[1].clr & CPU_PML))) {
+		test_skip("\"Secondary execution\" control or \"enable EPT\" control or \"enable PML\" control is not supported !");
+		return;
+	}
+
+	primary |= CPU_SECONDARY;
+	vmcs_write(CPU_EXEC_CTRL0, primary);
+	secondary &= ~(CPU_PML | CPU_EPT);
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("enable-PML disabled, enable-EPT disabled");
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	secondary |= CPU_PML;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("enable-PML enabled, enable-EPT disabled");
+	test_vmx_controls(false, false);
+	report_prefix_pop();
+
+	secondary |= CPU_EPT;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("enable-PML enabled, enable-EPT enabled");
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	secondary &= ~CPU_PML;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("enable-PML disabled, enable EPT enabled");
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	test_vmcs_page_reference(CPU_PML, PMLADDR, "PML address",
+	    "PML", false, false);
+
+	vmcs_write(CPU_EXEC_CTRL0, primary_saved);
+	vmcs_write(CPU_EXEC_CTRL1, secondary_saved);
+}
 
 /*
  * Check that the virtual CPU checks all of the VMX controls as
@@ -4431,6 +4488,7 @@  static void vmx_controls_test(void)
 	test_apic_ctls();
 	test_tpr_threshold();
 	test_nmi_ctrls();
+	test_pml();
 	test_invalid_event_injection();
 }