[PATCH 6/7] x86: nVMX: Verify pass-through LAPIC & IO-APIC to guest

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

 



From: Elazar Leibovich <elazar.leibovich@xxxxxxxxxx>

Test configures VMCS to run guest with LAPIC & IO-APIC pass-through:
* MSR-bitmap is empty (no intercept on access to x2APIC MSRs).
* No exit on external-interrupts
* No tpr-shadow, virtualize-apic-access and virtualize-x2apic-mode.

To verify pass-through works correctly, guest asserts irq-line to trigger
a level-triggered interrupt that should be injected directly to guest.
In guest interrupt-handler, a vmcall will verify remote_irr=1 before
EOI. Then, guest issues EOI and another vmcall to verify remote_irr
was cleared.

Signed-off-by: Elazar Leibovich <elazar.leibovich@xxxxxxxxxx>
Co-authored-by: Liran Alon <liran.alon@xxxxxxxxxx>
Signed-off-by: Liran Alon <liran.alon@xxxxxxxxxx>
Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx>
---
 x86/unittests.cfg |  7 +++++++
 x86/vmx_tests.c   | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 639e487cd777..b6ad1b57e34e 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -551,6 +551,13 @@ extra_params = -cpu host,+vmx -m 2048 -append vmx_eoi_bitmap_ioapic_scan_test
 arch = x86_64
 groups = vmx
 
+[vmx_apic_passthrough]
+file = vmx.flat
+smp = 2
+extra_params = -cpu host,+vmx -m 2048 -append vmx_apic_passthrough_test
+arch = x86_64
+groups = vmx
+
 [debug]
 file = debug.flat
 arch = x86_64
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 0bf081846533..fe48981ead50 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -4018,6 +4018,57 @@ static void vmx_eoi_bitmap_ioapic_scan_test(void)
 	report(__func__, 1);
 }
 
+static void irq_78_handler_guest(isr_regs_t *regs)
+{
+	set_irq_line(0xf, 0);
+	vmcall();
+	eoi();
+	vmcall();
+}
+
+static void vmx_apic_passthrough_guest(void)
+{
+	handle_irq(0x78, irq_78_handler_guest);
+	irq_enable();
+
+	set_irq_line(0xf, 1);
+}
+
+static void vmx_apic_passthrough_test(void)
+{
+	void *msr_bitmap = alloc_page();
+
+	u64 cpu_ctrl_0 = CPU_SECONDARY | CPU_MSR_BITMAP;
+	u64 cpu_ctrl_1 = 0;
+
+	memset(msr_bitmap, 0x0, PAGE_SIZE);
+	vmcs_write(MSR_BITMAP, (u64)msr_bitmap);
+
+	vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) & ~PIN_EXTINT);
+
+	vmcs_write(CPU_EXEC_CTRL0, vmcs_read(CPU_EXEC_CTRL0) | cpu_ctrl_0);
+	vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | cpu_ctrl_1);
+
+	ioapic_set_redir(0xf, 0x78, TRIGGER_LEVEL);
+	test_set_guest(vmx_apic_passthrough_guest);
+
+	/* Before EOI remote_irr should still be set */
+	enter_guest();
+	skip_exit_vmcall();
+	TEST_ASSERT_EQ_MSG(1, (int)ioapic_read_redir(0xf).remote_irr,
+		"IOAPIC pass-through: remote_irr=1 before EOI");
+
+	/* After EOI remote_irr should be cleared */
+	enter_guest();
+	skip_exit_vmcall();
+	TEST_ASSERT_EQ_MSG(0, (int)ioapic_read_redir(0xf).remote_irr,
+		"IOAPIC pass-through: remote_irr=0 after EOI");
+
+	/* Let L2 finish */
+	enter_guest();
+	report(__func__, 1);
+}
+
 #define TEST(name) { #name, .v2 = name }
 
 /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */
@@ -4086,6 +4137,8 @@ struct vmx_test vmx_tests[] = {
 	TEST(vmentry_movss_shadow_test),
 	/* APICv tests */
 	TEST(vmx_eoi_bitmap_ioapic_scan_test),
+	/* APIC pass-through tests */
+	TEST(vmx_apic_passthrough_test),
 	/* Regression tests */
 	TEST(vmx_cr_load_test),
 	{ NULL, NULL, NULL, NULL, NULL, {0} },
-- 
1.9.1




[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