Expand the testcase that verifies KVM intercepts EOI for in-flight level- triggered interrupts across routing changes to test multiple interrupts, e.g. to ensure KVM isn't processing only the highest priority interrupt, and to test both in-service (ISR) and pending interrupts (IRR). Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- x86/ioapic.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/x86/ioapic.c b/x86/ioapic.c index 7d3e37cc..e46eae2f 100644 --- a/x86/ioapic.c +++ b/x86/ioapic.c @@ -373,28 +373,58 @@ static void test_ioapic_level_retrigger_mask(void) set_mask(0x0e, false); } -static volatile int g_isr_84; +static volatile int g_isr_64, g_isr_84; -static void ioapic_isr_84(isr_regs_t *regs) +static void ioapic_reconfigure_dest(int line) { - int line = 0xe; ioapic_redir_entry_t e; - ++g_isr_84; set_irq_line(line, 0); e = ioapic_read_redir(line); + report(e.remote_irr == 1, "Reconfigure Remote IRR set"); + e.dest_id = 1; // Update only upper part of the register because we only change the // destination, which resides in the upper part ioapic_write_reg(0x10 + line * 2 + 1, ((u32 *)&e)[1]); +} +static void ioapic_isr_64(isr_regs_t *regs) +{ + /* + * Raise the IRQ line for the higher priority interrupt, *before* + * reconfiguring the I/O APIC routing. KVM should intercept EOI for + * both the in-service vector (line 0xd, vector 0x64) and the requested + * vector (line 0xe, vector 0x84). + */ + set_irq_line(0x0e, 1); + + ioapic_reconfigure_dest(0xe); + ioapic_reconfigure_dest(0xd); + eoi(); + + ++g_isr_64; +} + +static void ioapic_isr_84(isr_regs_t *regs) +{ + report(g_isr_64, "Higher priority IRQ should be blocked until IRET restores RFLAGS.IF"); + + ++g_isr_84; eoi(); } static void test_ioapic_self_reconfigure(void) { + ioapic_redir_entry_t d = { + .vector = 0x64, + .delivery_mode = 0, + .dest_mode = 0, + .dest_id = 0, + .trig_mode = TRIGGER_LEVEL, + }; ioapic_redir_entry_t e = { .vector = 0x84, .delivery_mode = 0, @@ -403,11 +433,21 @@ static void test_ioapic_self_reconfigure(void) .trig_mode = TRIGGER_LEVEL, }; + handle_irq(0x64, ioapic_isr_64); + ioapic_write_redir(0xd, d); + handle_irq(0x84, ioapic_isr_84); ioapic_write_redir(0xe, e); - set_irq_line(0x0e, 1); + + set_irq_line(0x0d, 1); + e = ioapic_read_redir(0xe); - report(g_isr_84 == 1 && e.remote_irr == 0, "Reconfigure self"); + report(g_isr_84 == 1 && e.remote_irr == 0, "Reconfigure self highest priority"); + + d = ioapic_read_redir(0xd); + report(g_isr_64 == 1 && d.remote_irr == 0, "Reconfigure self lower priority"); + + poll_remote_irr(0xd); poll_remote_irr(0xe); } base-commit: 68fee697b589b7eb7b82e8dd60155c5ccf054275 -- 2.48.1.711.g2feabab25a-goog