[PATCH kvm-unit-tests] ioapic: poll for completion of other CPUs in level-triggered SMP tests

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

 



The IOAPIC does not do anything if a level-triggered interrupt is asserted
while its REMOTE_IRR bit is set in the redirection table, and this can
cause a race condition between test_ioapic_physical_destination_mode
and test_ioapic_logical_destination_mode.  If CPU 1 is still running in
ioapic_isr_85 and has not sent the EOI, while CPU 0 has already reached
the set_irq_line(0x0e, 1) line of test_ioapic_logical_destination_mode,
the interrupt is dropped and the test hangs.

For some reason, this has started to occur about 20-30% of the time with
a 5.20-rc0 debug kernel.  With this patch, the ioapic test has survived
100 iterations without failing.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 x86/ioapic.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/x86/ioapic.c b/x86/ioapic.c
index 7cbccd7..4f578ce 100644
--- a/x86/ioapic.c
+++ b/x86/ioapic.c
@@ -6,6 +6,12 @@
 #include "isr.h"
 #include "delay.h"
 
+static void poll_remote_irr(unsigned line)
+{
+	while (ioapic_read_redir(line).remote_irr)
+		cpu_relax();
+}
+
 static void toggle_irq_line(unsigned line)
 {
 	set_irq_line(line, 1);
@@ -214,6 +220,7 @@ static void test_ioapic_level_tmr_smp(bool expected_tmr_before)
 	report(tmr_before == expected_tmr_before && g_tmr_79,
 	       "TMR for ioapic level interrupts (expected %s)",
 	       expected_tmr_before ? "true" : "false");
+	poll_remote_irr(0xe);
 }
 
 static int g_isr_98;
@@ -402,6 +409,7 @@ static void test_ioapic_self_reconfigure(void)
 	set_irq_line(0x0e, 1);
 	e = ioapic_read_redir(0xe);
 	report(g_isr_84 == 1 && e.remote_irr == 0, "Reconfigure self");
+	poll_remote_irr(0xe);
 }
 
 static volatile int g_isr_85;
@@ -429,6 +437,7 @@ static void test_ioapic_physical_destination_mode(void)
 		pause();
 	} while(g_isr_85 != 1);
 	report(g_isr_85 == 1, "ioapic physical destination mode");
+	poll_remote_irr(0xe);
 }
 
 static volatile int g_isr_86;
@@ -461,6 +470,7 @@ static void test_ioapic_logical_destination_mode(void)
 		pause();
 	} while(g_isr_86 < nr_vcpus);
 	report(g_isr_86 == nr_vcpus, "ioapic logical destination mode");
+	poll_remote_irr(0xe);
 }
 
 int main(void)
-- 
2.31.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