aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/nmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/nmi.c')
-rw-r--r--arch/i386/kernel/nmi.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index eaafe233a5da..a5e34d655965 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -22,6 +22,7 @@
22#include <linux/percpu.h> 22#include <linux/percpu.h>
23#include <linux/dmi.h> 23#include <linux/dmi.h>
24#include <linux/kprobes.h> 24#include <linux/kprobes.h>
25#include <linux/cpumask.h>
25 26
26#include <asm/smp.h> 27#include <asm/smp.h>
27#include <asm/nmi.h> 28#include <asm/nmi.h>
@@ -42,6 +43,8 @@ int nmi_watchdog_enabled;
42static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner); 43static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner);
43static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]); 44static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]);
44 45
46static cpumask_t backtrace_mask = CPU_MASK_NONE;
47
45/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's 48/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
46 * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) 49 * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now)
47 */ 50 */
@@ -192,6 +195,8 @@ static __cpuinit inline int nmi_known_cpu(void)
192 return 0; 195 return 0;
193} 196}
194 197
198static int endflag __initdata = 0;
199
195#ifdef CONFIG_SMP 200#ifdef CONFIG_SMP
196/* The performance counters used by NMI_LOCAL_APIC don't trigger when 201/* The performance counters used by NMI_LOCAL_APIC don't trigger when
197 * the CPU is idle. To make sure the NMI watchdog really ticks on all 202 * the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -199,7 +204,6 @@ static __cpuinit inline int nmi_known_cpu(void)
199 */ 204 */
200static __init void nmi_cpu_busy(void *data) 205static __init void nmi_cpu_busy(void *data)
201{ 206{
202 volatile int *endflag = data;
203 local_irq_enable_in_hardirq(); 207 local_irq_enable_in_hardirq();
204 /* Intentionally don't use cpu_relax here. This is 208 /* Intentionally don't use cpu_relax here. This is
205 to make sure that the performance counter really ticks, 209 to make sure that the performance counter really ticks,
@@ -207,14 +211,13 @@ static __init void nmi_cpu_busy(void *data)
207 pause instruction. On a real HT machine this is fine because 211 pause instruction. On a real HT machine this is fine because
208 all other CPUs are busy with "useless" delay loops and don't 212 all other CPUs are busy with "useless" delay loops and don't
209 care if they get somewhat less cycles. */ 213 care if they get somewhat less cycles. */
210 while (*endflag == 0) 214 while (endflag == 0)
211 barrier(); 215 mb();
212} 216}
213#endif 217#endif
214 218
215static int __init check_nmi_watchdog(void) 219static int __init check_nmi_watchdog(void)
216{ 220{
217 volatile int endflag = 0;
218 unsigned int *prev_nmi_count; 221 unsigned int *prev_nmi_count;
219 int cpu; 222 int cpu;
220 223
@@ -867,14 +870,16 @@ static unsigned int
867 870
868void touch_nmi_watchdog (void) 871void touch_nmi_watchdog (void)
869{ 872{
870 int i; 873 if (nmi_watchdog > 0) {
874 unsigned cpu;
871 875
872 /* 876 /*
873 * Just reset the alert counters, (other CPUs might be 877 * Just reset the alert counters, (other CPUs might be
874 * spinning on locks we hold): 878 * spinning on locks we hold):
875 */ 879 */
876 for_each_possible_cpu(i) 880 for_each_present_cpu (cpu)
877 alert_counter[i] = 0; 881 alert_counter[cpu] = 0;
882 }
878 883
879 /* 884 /*
880 * Tickle the softlockup detector too: 885 * Tickle the softlockup detector too:
@@ -907,6 +912,16 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
907 touched = 1; 912 touched = 1;
908 } 913 }
909 914
915 if (cpu_isset(cpu, backtrace_mask)) {
916 static DEFINE_SPINLOCK(lock); /* Serialise the printks */
917
918 spin_lock(&lock);
919 printk("NMI backtrace for cpu %d\n", cpu);
920 dump_stack();
921 spin_unlock(&lock);
922 cpu_clear(cpu, backtrace_mask);
923 }
924
910 sum = per_cpu(irq_stat, cpu).apic_timer_irqs; 925 sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
911 926
912 /* if the apic timer isn't firing, this cpu isn't doing much */ 927 /* if the apic timer isn't firing, this cpu isn't doing much */
@@ -1033,6 +1048,19 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
1033 1048
1034#endif 1049#endif
1035 1050
1051void __trigger_all_cpu_backtrace(void)
1052{
1053 int i;
1054
1055 backtrace_mask = cpu_online_map;
1056 /* Wait for up to 10 seconds for all CPUs to do the backtrace */
1057 for (i = 0; i < 10 * 1000; i++) {
1058 if (cpus_empty(backtrace_mask))
1059 break;
1060 mdelay(1);
1061 }
1062}
1063
1036EXPORT_SYMBOL(nmi_active); 1064EXPORT_SYMBOL(nmi_active);
1037EXPORT_SYMBOL(nmi_watchdog); 1065EXPORT_SYMBOL(nmi_watchdog);
1038EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi); 1066EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);