aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/nmi.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /arch/sparc/kernel/nmi.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/sparc/kernel/nmi.c')
-rw-r--r--arch/sparc/kernel/nmi.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index b129611590a4..a4bd7ba74c89 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -21,9 +21,10 @@
21 21
22#include <asm/perf_event.h> 22#include <asm/perf_event.h>
23#include <asm/ptrace.h> 23#include <asm/ptrace.h>
24#include <asm/local.h>
25#include <asm/pcr.h> 24#include <asm/pcr.h>
26 25
26#include "kstack.h"
27
27/* We don't have a real NMI on sparc64, but we can fake one 28/* We don't have a real NMI on sparc64, but we can fake one
28 * up using profiling counter overflow interrupts and interrupt 29 * up using profiling counter overflow interrupts and interrupt
29 * levels. 30 * levels.
@@ -47,7 +48,7 @@ static DEFINE_PER_CPU(short, wd_enabled);
47static int endflag __initdata; 48static int endflag __initdata;
48 49
49static DEFINE_PER_CPU(unsigned int, last_irq_sum); 50static DEFINE_PER_CPU(unsigned int, last_irq_sum);
50static DEFINE_PER_CPU(local_t, alert_counter); 51static DEFINE_PER_CPU(long, alert_counter);
51static DEFINE_PER_CPU(int, nmi_touch); 52static DEFINE_PER_CPU(int, nmi_touch);
52 53
53void touch_nmi_watchdog(void) 54void touch_nmi_watchdog(void)
@@ -93,38 +94,43 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
93notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) 94notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
94{ 95{
95 unsigned int sum, touched = 0; 96 unsigned int sum, touched = 0;
96 int cpu = smp_processor_id(); 97 void *orig_sp;
97 98
98 clear_softint(1 << irq); 99 clear_softint(1 << irq);
99 pcr_ops->write(PCR_PIC_PRIV);
100 100
101 local_cpu_data().__nmi_count++; 101 local_cpu_data().__nmi_count++;
102 102
103 nmi_enter(); 103 nmi_enter();
104 104
105 orig_sp = set_hardirq_stack();
106
105 if (notify_die(DIE_NMI, "nmi", regs, 0, 107 if (notify_die(DIE_NMI, "nmi", regs, 0,
106 pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) 108 pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
107 touched = 1; 109 touched = 1;
110 else
111 pcr_ops->write(PCR_PIC_PRIV);
108 112
109 sum = kstat_irqs_cpu(0, cpu); 113 sum = local_cpu_data().irq0_irqs;
110 if (__get_cpu_var(nmi_touch)) { 114 if (__get_cpu_var(nmi_touch)) {
111 __get_cpu_var(nmi_touch) = 0; 115 __get_cpu_var(nmi_touch) = 0;
112 touched = 1; 116 touched = 1;
113 } 117 }
114 if (!touched && __get_cpu_var(last_irq_sum) == sum) { 118 if (!touched && __get_cpu_var(last_irq_sum) == sum) {
115 local_inc(&__get_cpu_var(alert_counter)); 119 __this_cpu_inc(alert_counter);
116 if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz) 120 if (__this_cpu_read(alert_counter) == 30 * nmi_hz)
117 die_nmi("BUG: NMI Watchdog detected LOCKUP", 121 die_nmi("BUG: NMI Watchdog detected LOCKUP",
118 regs, panic_on_timeout); 122 regs, panic_on_timeout);
119 } else { 123 } else {
120 __get_cpu_var(last_irq_sum) = sum; 124 __get_cpu_var(last_irq_sum) = sum;
121 local_set(&__get_cpu_var(alert_counter), 0); 125 __this_cpu_write(alert_counter, 0);
122 } 126 }
123 if (__get_cpu_var(wd_enabled)) { 127 if (__get_cpu_var(wd_enabled)) {
124 write_pic(picl_value(nmi_hz)); 128 write_pic(picl_value(nmi_hz));
125 pcr_ops->write(pcr_enable); 129 pcr_ops->write(pcr_enable);
126 } 130 }
127 131
132 restore_hardirq_stack(orig_sp);
133
128 nmi_exit(); 134 nmi_exit();
129} 135}
130 136