diff mbox series

[kvm-unit-tests,1/2] x86: VMX: Verify do not lose pending interrupt queued before entering guest

Message ID 20180904093731.28473-2-liran.alon@oracle.com (mailing list archive)
State New, archived
Headers show
Series : x86: VMX: Verify do not lose pending interrupt queued before entering guest | expand

Commit Message

Liran Alon Sept. 4, 2018, 9:37 a.m. UTC
This patch test the issue fixed by KVM commit "KVM: nVMX: Fix loss of
pending event before entering L2". The test aim to verify that a pending
interrupt while interrupts are disabled is dispatched when we enter into
VMX guest instead of being lost.

The test configures VMCS to intercept external-interrupts and then
queue an interrupt by disabling interrupts and issue a self-IPI.
At this point, we enter guest and we expect CPU to immediately exit
guest on external-interrupt. To complete the test, we then re-enable
interrupts, verify interrupt is dispatched and re-enter guest to verify
it completes execution.

Reviewed-by: Nikita Leshchenko <nikita.leshchenko@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 x86/unittests.cfg |  6 ++++++
 x86/vmx_tests.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
diff mbox series

Patch

diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 9d3931921440..8d1c7db1cf6f 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -554,6 +554,12 @@  extra_params = -cpu host,+vmx -m 2560 -append vmx_cr_load_test
 arch = x86_64
 groups = vmx
 
+[vmx_pending_event_test]
+file = vmx.flat
+extra_params = -cpu host,+vmx -m 2560 -append vmx_pending_event_test
+arch = x86_64
+groups = vmx
+
 [vmx_eoi_bitmap_ioapic_scan]
 file = vmx.flat
 smp = 2
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 7a41732d058a..21b474db012b 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -4457,6 +4457,53 @@  static void vmx_cr_load_test(void)
 	TEST_ASSERT(!write_cr4_checking(cr4 & ~X86_CR4_PCIDE));
 }
 
+bool vmx_pending_event_ipi_fired;
+static void vmx_pending_event_ipi_isr(isr_regs_t *regs)
+{
+	vmx_pending_event_ipi_fired = true;
+	eoi();
+}
+
+bool vmx_pending_event_guest_run;
+static void vmx_pending_event_guest(void)
+{
+	vmx_pending_event_guest_run = true;
+}
+
+static void vmx_pending_event_test(void)
+{
+	int ipi_vector = 0xf1;
+
+	vmx_pending_event_ipi_fired = false;
+	handle_irq(ipi_vector, vmx_pending_event_ipi_isr);
+
+	vmx_pending_event_guest_run = false;
+	test_set_guest(vmx_pending_event_guest);
+
+	vmcs_set_bits(PIN_CONTROLS, PIN_EXTINT);
+
+	irq_disable();
+	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL |
+				   APIC_DM_FIXED | ipi_vector,
+				   0);
+
+	enter_guest();
+
+	assert_exit_reason(VMX_EXTINT);
+	report("Guest did not run before host received IPI",
+		   !vmx_pending_event_guest_run);
+
+	irq_enable();
+	asm volatile ("nop");
+	irq_disable();
+	report("Got pending interrupt after IRQ enabled",
+		   vmx_pending_event_ipi_fired);
+
+	enter_guest();
+	report("Guest finished running when no interrupt",
+		   vmx_pending_event_guest_run);
+}
+
 static bool cpu_has_apicv(void)
 {
 	return ((ctrl_cpu_rev[1].clr & CPU_APIC_REG_VIRT) &&
@@ -5016,6 +5063,7 @@  struct vmx_test vmx_tests[] = {
 	TEST(vmx_vmcs_shadow_test),
 	/* Regression tests */
 	TEST(vmx_cr_load_test),
+	TEST(vmx_pending_event_test),
 	/* EPT access tests. */
 	TEST(ept_access_test_not_present),
 	TEST(ept_access_test_read_only),