[PATCH 2/2] [kvm-unit-test] nVMX x86: check posted-interrupt control on vmentry of L2

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

 



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 “process posted interrupts” VM-execution control is 1, the
    following must be true:

      - The “virtual-interrupt delivery” VM-execution control is 1.
      - The “acknowledge interrupt on exit” VM-exit control is 1.
      - The posted-interrupt notification vector has a value in the
      - range 0–255 (bits 15:8 are all 0).
      - Bits 5:0 of the posted-interrupt descriptor address are all 0.
      - The posted-interrupt descriptor address does not set any bits
        beyond the processor's physical-address width.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx>
Reviewed-by: Darren Kenny <darren.kenny@xxxxxxxxxx>
Reviewed-by: Karl Heubaum <karl.heubaum@xxxxxxxxxx>
---
 x86/vmx.h       |   1 +
 x86/vmx_tests.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+)

diff --git a/x86/vmx.h b/x86/vmx.h
index 54646f5..22b2892 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -144,6 +144,7 @@ enum Encoding {
 	TSC_OFFSET_HI		= 0x2011ul,
 	APIC_VIRT_ADDR		= 0x2012ul,
 	APIC_ACCS_ADDR		= 0x2014ul,
+	POSTED_INTR_DESC_ADDR	= 0x2016ul,
 	EPTP			= 0x201aul,
 	EPTP_HI			= 0x201bul,
 	VMREAD_BITMAP           = 0x2026ul,
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index caa1834..8b2efd8 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -3912,12 +3912,140 @@ static void test_virtual_intr_ctls(void)
 	vmcs_write(PIN_CONTROLS, pin_saved);
 }
 
+static void test_pi_desc_addr(u64 addr, bool ctrl)
+{
+	vmcs_write(POSTED_INTR_DESC_ADDR, addr);
+	report_prefix_pushf("Process-posted-interrupts enabled; posted-interrupt-descriptor-address 0x%lx", addr);
+	test_vmx_controls(ctrl, false);
+	report_prefix_pop();
+}
+
+/*
+ * If the “process posted interrupts” VM-execution control is 1, the
+ * following must be true:
+ *
+ *	- The “virtual-interrupt delivery” VM-execution control is 1.
+ *	- The “acknowledge interrupt on exit” VM-exit control is 1.
+ *	- The posted-interrupt notification vector has a value in the
+ *	- range 0–255 (bits 15:8 are all 0).
+ *	- Bits 5:0 of the posted-interrupt descriptor address are all 0.
+ *	- The posted-interrupt descriptor address does not set any bits
+ *	  beyond the processor's physical-address width.
+ * [Intel SDM]
+ */
+static void test_posted_intr(void)
+{
+	u32 saved_primary = vmcs_read(CPU_EXEC_CTRL0);
+	u32 saved_secondary = vmcs_read(CPU_EXEC_CTRL1);
+	u32 saved_pin = vmcs_read(PIN_CONTROLS);
+	u32 exit_ctl_saved = vmcs_read(EXI_CONTROLS);
+	u32 primary = saved_primary;
+	u32 secondary = saved_secondary;
+	u32 pin = saved_pin;
+	u32 exit_ctl = exit_ctl_saved;
+	u16 vec;
+	int i;
+
+	if (!((ctrl_pin_rev.clr & PIN_POST_INTR) &&
+	    (ctrl_cpu_rev[1].clr & CPU_VINTD) &&
+	    (ctrl_exit_rev.clr & EXI_INTA)))
+		return;
+
+	vmcs_write(CPU_EXEC_CTRL0, primary | CPU_SECONDARY | CPU_TPR_SHADOW);
+
+	/*
+	 * Test virtual-interrupt-delivery and acknowledge-interrupt-on-exit
+	 */
+	pin |= PIN_POST_INTR;
+	vmcs_write(PIN_CONTROLS, pin);
+	secondary &= ~CPU_VINTD;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery disabled");
+	test_vmx_controls(false, false);
+	report_prefix_pop();
+
+	secondary |= CPU_VINTD;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery enabled");
+	test_vmx_controls(false, false);
+	report_prefix_pop();
+
+	exit_ctl &= ~EXI_INTA;
+	vmcs_write(EXI_CONTROLS, exit_ctl);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery enabled; acknowledge-interrupt-on-exit disabled");
+	test_vmx_controls(false, false);
+	report_prefix_pop();
+
+	exit_ctl |= EXI_INTA;
+	vmcs_write(EXI_CONTROLS, exit_ctl);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery enabled; acknowledge-interrupt-on-exit enabled");
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	secondary &= ~CPU_VINTD;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery disabled; acknowledge-interrupt-on-exit enabled");
+	test_vmx_controls(false, false);
+	report_prefix_pop();
+
+	secondary |= CPU_VINTD;
+	vmcs_write(CPU_EXEC_CTRL1, secondary);
+	report_prefix_pushf("Process-posted-interrupts enabled; virtual-interrupt-delivery enabled; acknowledge-interrupt-on-exit enabled");
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	/*
+	 * Test posted-interrupt notification vector
+	 */
+	for (i = 0; i < 8; i++) {
+		vec = (1ul << i);
+		vmcs_write(PINV, vec);
+		report_prefix_pushf("Process-posted-interrupts enabled; posted-interrupt-notification-vector %u", vec);
+		test_vmx_controls(true, false);
+		report_prefix_pop();
+	}
+	for (i = 8; i < 16; i++) {
+		vec = (1ul << i);
+		vmcs_write(PINV, vec);
+		report_prefix_pushf("Process-posted-interrupts enabled; posted-interrupt-notification-vector %u", vec);
+		test_vmx_controls(false, false);
+		report_prefix_pop();
+	}
+
+	vec &= ~(0xff << 8);
+	vmcs_write(PINV, vec);
+	report_prefix_pushf("Process-posted-interrupts enabled; posted-interrupt-notification-vector %u", vec);
+	test_vmx_controls(true, false);
+	report_prefix_pop();
+
+	/*
+	 * Test posted-interrupt descriptor addresss
+	 */
+	for (i = 0; i < 6; i++) {
+		test_pi_desc_addr(1ul << i, false);
+	}
+
+	test_pi_desc_addr(0xf0, false);
+	test_pi_desc_addr(0xff, false);
+	test_pi_desc_addr(0x0f, false);
+	test_pi_desc_addr(0x8000, true);
+	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);
+
+	vmcs_write(CPU_EXEC_CTRL0, saved_primary);
+	vmcs_write(CPU_EXEC_CTRL1, saved_secondary);
+	vmcs_write(PIN_CONTROLS, saved_pin);
+}
+
 static void test_apic_ctls(void)
 {
 	test_apic_virt_addr();
 	test_apic_access_addr();
 	test_apic_virtual_ctls();
 	test_virtual_intr_ctls();
+	test_posted_intr();
 }
 
 static void set_vtpr(unsigned vtpr)
-- 
2.9.5




[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