aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/crash.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/kernel/crash.c')
-rw-r--r--arch/x86_64/kernel/crash.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index d8d5750d6106..3525f884af82 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -23,6 +23,7 @@
23#include <asm/nmi.h> 23#include <asm/nmi.h>
24#include <asm/hw_irq.h> 24#include <asm/hw_irq.h>
25#include <asm/mach_apic.h> 25#include <asm/mach_apic.h>
26#include <asm/kdebug.h>
26 27
27/* This keeps a track of which one is crashing cpu. */ 28/* This keeps a track of which one is crashing cpu. */
28static int crashing_cpu; 29static int crashing_cpu;
@@ -68,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
68 * for the data I pass, and I need tags 69 * for the data I pass, and I need tags
69 * on the data to indicate what information I have 70 * on the data to indicate what information I have
70 * squirrelled away. ELF notes happen to provide 71 * squirrelled away. ELF notes happen to provide
71 * all of that that no need to invent something new. 72 * all of that, no need to invent something new.
72 */ 73 */
73 74
74 buf = (u32*)per_cpu_ptr(crash_notes, cpu); 75 buf = (u32*)per_cpu_ptr(crash_notes, cpu);
@@ -95,15 +96,25 @@ static void crash_save_self(struct pt_regs *regs)
95#ifdef CONFIG_SMP 96#ifdef CONFIG_SMP
96static atomic_t waiting_for_crash_ipi; 97static atomic_t waiting_for_crash_ipi;
97 98
98static int crash_nmi_callback(struct pt_regs *regs, int cpu) 99static int crash_nmi_callback(struct notifier_block *self,
100 unsigned long val, void *data)
99{ 101{
102 struct pt_regs *regs;
103 int cpu;
104
105 if (val != DIE_NMI_IPI)
106 return NOTIFY_OK;
107
108 regs = ((struct die_args *)data)->regs;
109 cpu = raw_smp_processor_id();
110
100 /* 111 /*
101 * Don't do anything if this handler is invoked on crashing cpu. 112 * Don't do anything if this handler is invoked on crashing cpu.
102 * Otherwise, system will completely hang. Crashing cpu can get 113 * Otherwise, system will completely hang. Crashing cpu can get
103 * an NMI if system was initially booted with nmi_watchdog parameter. 114 * an NMI if system was initially booted with nmi_watchdog parameter.
104 */ 115 */
105 if (cpu == crashing_cpu) 116 if (cpu == crashing_cpu)
106 return 1; 117 return NOTIFY_STOP;
107 local_irq_disable(); 118 local_irq_disable();
108 119
109 crash_save_this_cpu(regs, cpu); 120 crash_save_this_cpu(regs, cpu);
@@ -127,12 +138,17 @@ static void smp_send_nmi_allbutself(void)
127 * cpu hotplug shouldn't matter. 138 * cpu hotplug shouldn't matter.
128 */ 139 */
129 140
141static struct notifier_block crash_nmi_nb = {
142 .notifier_call = crash_nmi_callback,
143};
144
130static void nmi_shootdown_cpus(void) 145static void nmi_shootdown_cpus(void)
131{ 146{
132 unsigned long msecs; 147 unsigned long msecs;
133 148
134 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); 149 atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
135 set_nmi_callback(crash_nmi_callback); 150 if (register_die_notifier(&crash_nmi_nb))
151 return; /* return what? */
136 152
137 /* 153 /*
138 * Ensure the new callback function is set before sending 154 * Ensure the new callback function is set before sending
@@ -178,9 +194,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
178 if(cpu_has_apic) 194 if(cpu_has_apic)
179 disable_local_APIC(); 195 disable_local_APIC();
180 196
181#if defined(CONFIG_X86_IO_APIC)
182 disable_IO_APIC(); 197 disable_IO_APIC();
183#endif
184 198
185 crash_save_self(regs); 199 crash_save_self(regs);
186} 200}