
From: "Maciej W. Rozycki" <macro@linux-mips.org>

 While discussing races in the NMI handler's trailer fiddling with RTC
registers, I've discovered we incorrectly attempt to handle NMIs coming
from the system (memory errors, IOCHK# assertions, etc.) with all
processors even though the interrupts are only routed to the bootstrap
processor.  If one of these events coincides with a NMI watchdog tick it
may even be handled multiple times in parallel.

Here is a fix that makes application processors ignore these events.  They
no longer access the NMI status bits at I/O port 0x61 which has also the
advantage of removing the contention on the port when the I/O APIC NMI
watchdog makes all processors arrive at the handler at the same time.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/i386/kernel/traps.c   |    6 +++++-
 25-akpm/arch/x86_64/kernel/traps.c |    8 ++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff -puN arch/i386/kernel/traps.c~x86-x86_64-only-handle-system-nmis-on-the-bsp arch/i386/kernel/traps.c
--- 25/arch/i386/kernel/traps.c~x86-x86_64-only-handle-system-nmis-on-the-bsp	Wed Nov  3 15:37:20 2004
+++ 25-akpm/arch/i386/kernel/traps.c	Wed Nov  3 15:37:20 2004
@@ -583,7 +583,11 @@ void die_nmi (struct pt_regs *regs, cons
 
 static void default_do_nmi(struct pt_regs * regs)
 {
-	unsigned char reason = get_nmi_reason();
+	unsigned char reason = 0;
+
+	/* Only the BSP gets external NMIs from the system.  */
+	if (!smp_processor_id())
+		reason = get_nmi_reason();
  
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
diff -puN arch/x86_64/kernel/traps.c~x86-x86_64-only-handle-system-nmis-on-the-bsp arch/x86_64/kernel/traps.c
--- 25/arch/x86_64/kernel/traps.c~x86-x86_64-only-handle-system-nmis-on-the-bsp	Wed Nov  3 15:37:20 2004
+++ 25-akpm/arch/x86_64/kernel/traps.c	Wed Nov  3 15:38:48 2004
@@ -580,9 +580,13 @@ static void unknown_nmi_error(unsigned c
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
-asmlinkage void default_do_nmi(struct pt_regs * regs)
+asmlinkage void default_do_nmi(struct pt_regs *regs)
 {
-	unsigned char reason = get_nmi_reason();
+	unsigned char reason;
+
+	/* Only the BSP gets external NMIs from the system.  */
+	if (!smp_processor_id())
+		reason = get_nmi_reason();
 
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
_
