From: "Maciej W. Rozycki" Fix up the 8259 ack handling for buggy SMM firmware. See http://www.ussg.iu.edu/hypermail/linux/kernel/0203.2/0956.html Apparently the embedded 8259A-compatible core is not fully functional. This patch lets the I/O APIC-driven NMI watchdog to function correctly. Credit to Ross Dickson for discovering this. --- arch/i386/kernel/io_apic.c | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff -puN arch/i386/kernel/io_apic.c~8259-timer-ack-fix arch/i386/kernel/io_apic.c --- 25/arch/i386/kernel/io_apic.c~8259-timer-ack-fix 2004-02-06 18:03:45.000000000 -0800 +++ 25-akpm/arch/i386/kernel/io_apic.c 2004-02-06 18:06:00.000000000 -0800 @@ -2155,6 +2155,10 @@ static inline void check_timer(void) { int pin1, pin2; int vector; + unsigned int ver; + + ver = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(ver); /* * get/set the timer IRQ vector: @@ -2168,11 +2172,17 @@ static inline void check_timer(void) * mode for the 8259A whenever interrupts are routed * through I/O APICs. Also IRQ0 has to be enabled in * the 8259A which implies the virtual wire has to be - * disabled in the local APIC. + * disabled in the local APIC. Finally timer interrupts + * need to be acknowledged manually in the 8259A for + * do_slow_timeoffset() and for the i82489DX when using + * the NMI watchdog. */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = 1; + if (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)) + timer_ack = 1; + else + timer_ack = !cpu_has_tsc; enable_8259A_irq(0); pin1 = find_isa_irq_pin(0, mp_INT); @@ -2190,7 +2200,8 @@ static inline void check_timer(void) disable_8259A_irq(0); setup_nmi(); enable_8259A_irq(0); - check_nmi_watchdog(); + if (check_nmi_watchdog() < 0); + timer_ack = !cpu_has_tsc; } return; } @@ -2213,7 +2224,8 @@ static inline void check_timer(void) add_pin_to_irq(0, 0, pin2); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); - check_nmi_watchdog(); + if (check_nmi_watchdog() < 0); + timer_ack = !cpu_has_tsc; } return; } _