aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDongdong Deng <dongdong.deng@windriver.com>2011-01-04 22:38:08 -0500
committerIngo Molnar <mingo@elte.hu>2011-01-05 08:22:57 -0500
commit554ec063982752e9a569ab9189eeffa3d96731b2 (patch)
tree1f27aba0e34881c1d8b428d18e1c1fbaa866c612 /arch
parent9ab181fa9ff73a38fccd0a4f1c40a38dfe62b535 (diff)
x86: Avoid calling arch_trigger_all_cpu_backtrace() at the same time
The spin_lock_debug/rcu_cpu_stall detector uses trigger_all_cpu_backtrace() to dump cpu backtrace. Therefore it is possible that trigger_all_cpu_backtrace() could be called at the same time on different CPUs, which triggers and 'unknown reason NMI' warning. The following case illustrates the problem: CPU1 CPU2 ... CPU N trigger_all_cpu_backtrace() set "backtrace_mask" to cpu mask | generate NMI interrupts generate NMI interrupts ... \ | / \ | / The "backtrace_mask" will be cleaned by the first NMI interrupt at nmi_watchdog_tick(), then the following NMI interrupts generated by other cpus's arch_trigger_all_cpu_backtrace() will be taken as unknown reason NMI interrupts. This patch uses a test_and_set to avoid the problem, and stop the arch_trigger_all_cpu_backtrace() from calling to avoid dumping a double cpu backtrace info when there is already a trigger_all_cpu_backtrace() in progress. Signed-off-by: Dongdong Deng <dongdong.deng@windriver.com> Reviewed-by: Bruce Ashfield <bruce.ashfield@windriver.com> Cc: fweisbec@gmail.com LKML-Reference: <1294198689-15447-2-git-send-email-dzickus@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Don Zickus <dzickus@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/apic/hw_nmi.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c
index 2b40a6045da..72ec29e1ae0 100644
--- a/arch/x86/kernel/apic/hw_nmi.c
+++ b/arch/x86/kernel/apic/hw_nmi.c
@@ -28,10 +28,20 @@ u64 hw_nmi_get_sample_period(void)
28/* For reliability, we're prepared to waste bits here. */ 28/* For reliability, we're prepared to waste bits here. */
29static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; 29static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
30 30
31/* "in progress" flag of arch_trigger_all_cpu_backtrace */
32static unsigned long backtrace_flag;
33
31void arch_trigger_all_cpu_backtrace(void) 34void arch_trigger_all_cpu_backtrace(void)
32{ 35{
33 int i; 36 int i;
34 37
38 if (test_and_set_bit(0, &backtrace_flag))
39 /*
40 * If there is already a trigger_all_cpu_backtrace() in progress
41 * (backtrace_flag == 1), don't output double cpu dump infos.
42 */
43 return;
44
35 cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask); 45 cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask);
36 46
37 printk(KERN_INFO "sending NMI to all CPUs:\n"); 47 printk(KERN_INFO "sending NMI to all CPUs:\n");
@@ -43,6 +53,9 @@ void arch_trigger_all_cpu_backtrace(void)
43 break; 53 break;
44 mdelay(1); 54 mdelay(1);
45 } 55 }
56
57 clear_bit(0, &backtrace_flag);
58 smp_mb__after_clear_bit();
46} 59}
47 60
48static int __kprobes 61static int __kprobes