diff options
Diffstat (limited to 'arch/x86_64/kernel/crash.c')
-rw-r--r-- | arch/x86_64/kernel/crash.c | 26 |
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. */ |
28 | static int crashing_cpu; | 29 | static 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 |
96 | static atomic_t waiting_for_crash_ipi; | 97 | static atomic_t waiting_for_crash_ipi; |
97 | 98 | ||
98 | static int crash_nmi_callback(struct pt_regs *regs, int cpu) | 99 | static 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 | ||
141 | static struct notifier_block crash_nmi_nb = { | ||
142 | .notifier_call = crash_nmi_callback, | ||
143 | }; | ||
144 | |||
130 | static void nmi_shootdown_cpus(void) | 145 | static 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 | } |