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

[Xen-changelog] [xen-unstable] x86: fix the potential of encountering panic "IO-APIC + timer doesn't work! ..."



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1228995610 0
# Node ID c15244125a693d2a1ae5e5745a649467394d8dac
# Parent  f4c1a347311bbdc7dbf3b1b213719929cf03ede3
x86: fix the potential of encountering panic "IO-APIC + timer doesn't work! ..."

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Linux commit:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=4aae07025265151e3f7041dfbf0f529e122de1d8

x86: fix "Kernel panic - not syncing: IO-APIC + timer doesn't work!"

Under rare circumstances we found we could have an IRQ0 entry while we
are in the middle of setting up the local APIC, the i8259A and the
PIT. That is certainly not how it's supposed to work! check_timer()
was supposed to be called with irqs turned off - but this eroded away
sometime in the past. This code would still work most of the time
because this code runs very quickly, but just the right timing
conditions are present and IRQ0 hits in this small, ~30 usecs window,
timer irqs stop and the system does not boot up. Also, given how early
this is during bootup, the hang is very deterministic - but it would
only occur on certain machines (and certain configs).

The fix was quite simple: disable/restore interrupts properly in this
function. With that in place the test-system now boots up just fine.

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
 xen/arch/x86/io_apic.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletion(-)

diff -r f4c1a347311b -r c15244125a69 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Thu Dec 11 11:36:00 2008 +0000
+++ b/xen/arch/x86/io_apic.c    Thu Dec 11 11:40:10 2008 +0000
@@ -1257,14 +1257,16 @@ static int __init timer_irq_works(void)
 static int __init timer_irq_works(void)
 {
     extern unsigned long pit0_ticks;
-    unsigned long t1;
+    unsigned long t1, flags;
 
     t1 = pit0_ticks;
     mb();
 
+    local_save_flags(flags);
     local_irq_enable();
     /* Let ten ticks pass... */
     mdelay((10 * 1000) / HZ);
+    local_irq_restore(flags);
 
     /*
      * Expect a few ticks at least, to be sure some possible
@@ -1707,6 +1709,9 @@ static inline void check_timer(void)
 {
     int apic1, pin1, apic2, pin2;
     int vector;
+    unsigned long flags;
+
+    local_irq_save(flags);
 
     /*
      * get/set the timer IRQ vector:
@@ -1748,6 +1753,7 @@ static inline void check_timer(void)
          */
         unmask_IO_APIC_irq(0);
         if (timer_irq_works()) {
+            local_irq_restore(flags);
             if (disable_timer_pin_1 > 0)
                 clear_IO_APIC_pin(apic1, pin1);
             return;
@@ -1765,6 +1771,7 @@ static inline void check_timer(void)
          */
         setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
         if (timer_irq_works()) {
+            local_irq_restore(flags);
             printk("works.\n");
             if (pin1 != -1)
                 replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
@@ -1792,6 +1799,7 @@ static inline void check_timer(void)
     enable_8259A_irq(0);
 
     if (timer_irq_works()) {
+        local_irq_restore(flags);
         printk(" works.\n");
         return;
     }
@@ -1806,6 +1814,8 @@ static inline void check_timer(void)
     apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
 
     unlock_ExtINT_logic();
+
+    local_irq_restore(flags);
 
     if (timer_irq_works()) {
         printk(" works.\n");

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.