Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2480

kernel-2.6.18-128.1.10.el5.src.rpm

From: Aristeu Rozanski <aris@redhat.com>
Date: Wed, 20 Aug 2008 13:17:03 -0400
Subject: [x86] nmi: update nmi_watchdog_tick
Message-id: 20080820171650.552580000@redhat.com
O-Subject: [RHEL5.3 PATCH 17/25] nmi: update nmi_watchdog_tick() on i386
Bugzilla: 447618

https://bugzilla.redhat.com/show_bug.cgi?id=447618

Change nmi_watchdog_tick() to detect if the NMI was generated by the perf
counter (local APIC case).

upstream: 751521149a05e308d863d01ced61080ce1a2ec99 (and others)

diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 956ac01..8b66535 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -24,6 +24,7 @@
 #include <asm/smp.h>
 #include <asm/nmi.h>
 #include <asm/intel_arch_perfmon.h>
+#include <asm/kdebug.h>
 
 #include "mach_traps.h"
 
@@ -425,7 +426,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
 
 extern void die_nmi(struct pt_regs *, const char *msg);
 
-void nmi_watchdog_tick (struct pt_regs * regs)
+int nmi_watchdog_tick (struct pt_regs * regs)
 {
 
 	/*
@@ -433,7 +434,7 @@ void nmi_watchdog_tick (struct pt_regs * regs)
 	 * always switch the stack NMI-atomically, it's safe to use
 	 * smp_processor_id().
 	 */
-	unsigned int sum;
+	unsigned int sum, rc = 0;
 	int cpu = smp_processor_id();
 
 	sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
@@ -453,30 +454,24 @@ void nmi_watchdog_tick (struct pt_regs * regs)
 		last_irq_sums[cpu] = sum;
 		alert_counter[cpu] = 0;
 	}
-	if (nmi_perfctr_msr) {
-		if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
-			/*
-			 * P4 quirks:
-			 * - An overflown perfctr will assert its interrupt
-			 *   until the OVF flag in its CCCR is cleared.
-			 * - LVTPC is masked on interrupt and must be
-			 *   unmasked by the LVTPC handler.
-			 */
-			wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
-			apic_write(APIC_LVTPC, APIC_DM_NMI);
-			write_watchdog_counter(NULL);
-		}
-		else if (nmi_perfctr_msr == MSR_P6_PERFCTR0 ||
-		         nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-			/* Only P6 based Pentium M need to re-unmask
-			 * the apic vector but it doesn't hurt
-			 * other P6 variant */
-			apic_write(APIC_LVTPC, APIC_DM_NMI);
-			write_watchdog_counter32(NULL);
-		} else {
-			write_watchdog_counter(NULL);
-		}
-	}
+
+	/* see if the nmi watchdog went off */
+	if (!__get_cpu_var(wd_enabled))
+		return rc;
+	switch (nmi_watchdog) {
+	case NMI_LOCAL_APIC:
+		rc |= lapic_wd_event(nmi_hz);
+		break;
+	case NMI_IO_APIC:
+		/* don't know how to accurately check for this.
+		 * just assume it was a watchdog timer interrupt
+		 * This matches the old behaviour.
+		 */
+		rc = 1;
+		break;
+ 	}
+
+	return rc;
 }
 
 static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 10fa3ea..e0ab3a1 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -821,16 +821,14 @@ static void default_do_nmi(struct pt_regs * regs)
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
 							== NOTIFY_STOP)
 			return;
-#ifdef CONFIG_X86_LOCAL_APIC
+
 		/*
 		 * Ok, so this is none of the documented NMI sources,
 		 * so it must be the NMI watchdog.
 		 */
-		if (nmi_watchdog) {
-			nmi_watchdog_tick(regs);
+		if (nmi_watchdog_tick(regs))
 			return;
-		}
-#endif
+
 		if (!do_nmi_callback(regs, cpu))
 			unknown_nmi_error(reason, regs);
 		return;
diff --git a/include/asm-i386/nmi.h b/include/asm-i386/nmi.h
index 4ff5761..48edc43 100644
--- a/include/asm-i386/nmi.h
+++ b/include/asm-i386/nmi.h
@@ -53,7 +53,7 @@ extern int reserve_lapic_nmi(void);
 extern void release_lapic_nmi(void);
 extern void disable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct pt_regs * regs);
+extern int nmi_watchdog_tick (struct pt_regs * regs);
 
 extern unsigned int nmi_watchdog;
 #define NMI_DEFAULT     -1