diff options
Diffstat (limited to 'arch/x86/kernel/apic/hw_nmi.c')
-rw-r--r-- | arch/x86/kernel/apic/hw_nmi.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index cefd6942f0e9..72ec29e1ae06 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c | |||
@@ -17,19 +17,31 @@ | |||
17 | #include <linux/nmi.h> | 17 | #include <linux/nmi.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | 19 | ||
20 | /* For reliability, we're prepared to waste bits here. */ | 20 | #ifdef CONFIG_HARDLOCKUP_DETECTOR |
21 | static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; | ||
22 | |||
23 | u64 hw_nmi_get_sample_period(void) | 21 | u64 hw_nmi_get_sample_period(void) |
24 | { | 22 | { |
25 | return (u64)(cpu_khz) * 1000 * 60; | 23 | return (u64)(cpu_khz) * 1000 * 60; |
26 | } | 24 | } |
25 | #endif | ||
26 | |||
27 | #ifdef arch_trigger_all_cpu_backtrace | ||
28 | /* For reliability, we're prepared to waste bits here. */ | ||
29 | static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; | ||
30 | |||
31 | /* "in progress" flag of arch_trigger_all_cpu_backtrace */ | ||
32 | static unsigned long backtrace_flag; | ||
27 | 33 | ||
28 | #ifdef ARCH_HAS_NMI_WATCHDOG | ||
29 | void arch_trigger_all_cpu_backtrace(void) | 34 | void arch_trigger_all_cpu_backtrace(void) |
30 | { | 35 | { |
31 | int i; | 36 | int i; |
32 | 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 | |||
33 | cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask); | 45 | cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask); |
34 | 46 | ||
35 | printk(KERN_INFO "sending NMI to all CPUs:\n"); | 47 | printk(KERN_INFO "sending NMI to all CPUs:\n"); |
@@ -41,6 +53,9 @@ void arch_trigger_all_cpu_backtrace(void) | |||
41 | break; | 53 | break; |
42 | mdelay(1); | 54 | mdelay(1); |
43 | } | 55 | } |
56 | |||
57 | clear_bit(0, &backtrace_flag); | ||
58 | smp_mb__after_clear_bit(); | ||
44 | } | 59 | } |
45 | 60 | ||
46 | static int __kprobes | 61 | static int __kprobes |
@@ -49,7 +64,7 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self, | |||
49 | { | 64 | { |
50 | struct die_args *args = __args; | 65 | struct die_args *args = __args; |
51 | struct pt_regs *regs; | 66 | struct pt_regs *regs; |
52 | int cpu = smp_processor_id(); | 67 | int cpu; |
53 | 68 | ||
54 | switch (cmd) { | 69 | switch (cmd) { |
55 | case DIE_NMI: | 70 | case DIE_NMI: |
@@ -61,6 +76,7 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self, | |||
61 | } | 76 | } |
62 | 77 | ||
63 | regs = args->regs; | 78 | regs = args->regs; |
79 | cpu = smp_processor_id(); | ||
64 | 80 | ||
65 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { | 81 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { |
66 | static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED; | 82 | static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED; |
@@ -90,18 +106,3 @@ static int __init register_trigger_all_cpu_backtrace(void) | |||
90 | } | 106 | } |
91 | early_initcall(register_trigger_all_cpu_backtrace); | 107 | early_initcall(register_trigger_all_cpu_backtrace); |
92 | #endif | 108 | #endif |
93 | |||
94 | /* STUB calls to mimic old nmi_watchdog behaviour */ | ||
95 | #if defined(CONFIG_X86_LOCAL_APIC) | ||
96 | unsigned int nmi_watchdog = NMI_NONE; | ||
97 | EXPORT_SYMBOL(nmi_watchdog); | ||
98 | void acpi_nmi_enable(void) { return; } | ||
99 | void acpi_nmi_disable(void) { return; } | ||
100 | #endif | ||
101 | atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */ | ||
102 | EXPORT_SYMBOL(nmi_active); | ||
103 | int unknown_nmi_panic; | ||
104 | void cpu_nmi_set_wd_enabled(void) { return; } | ||
105 | void stop_apic_nmi_watchdog(void *unused) { return; } | ||
106 | void setup_apic_nmi_watchdog(void *unused) { return; } | ||
107 | int __init check_nmi_watchdog(void) { return 0; } | ||