1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/kernel.h>
14#include <linux/smp.h>
15#include <linux/reboot.h>
16#include <linux/kexec.h>
17#include <linux/export.h>
18#include <linux/crash_dump.h>
19#include <linux/delay.h>
20#include <linux/init.h>
21#include <linux/irq.h>
22#include <linux/types.h>
23
24#include <asm/processor.h>
25#include <asm/machdep.h>
26#include <asm/kexec.h>
27#include <asm/kdump.h>
28#include <asm/prom.h>
29#include <asm/smp.h>
30#include <asm/setjmp.h>
31#include <asm/debug.h>
32
33
34
35
36
37
38
39
40
41#define PRIMARY_TIMEOUT 500
42#define SECONDARY_TIMEOUT 1000
43
44#define IPI_TIMEOUT 10000
45#define REAL_MODE_TIMEOUT 10000
46
47
48int crashing_cpu = -1;
49static int time_to_dump;
50
51#define CRASH_HANDLER_MAX 3
52
53static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
54static DEFINE_SPINLOCK(crash_handlers_lock);
55
56static unsigned long crash_shutdown_buf[JMP_BUF_LEN];
57static int crash_shutdown_cpu = -1;
58
59static int handle_fault(struct pt_regs *regs)
60{
61 if (crash_shutdown_cpu == smp_processor_id())
62 longjmp(crash_shutdown_buf, 1);
63 return 0;
64}
65
66#ifdef CONFIG_SMP
67
68static atomic_t cpus_in_crash;
69void crash_ipi_callback(struct pt_regs *regs)
70{
71 static cpumask_t cpus_state_saved = CPU_MASK_NONE;
72
73 int cpu = smp_processor_id();
74
75 if (!cpu_online(cpu))
76 return;
77
78 hard_irq_disable();
79 if (!cpumask_test_cpu(cpu, &cpus_state_saved)) {
80 crash_save_cpu(regs, cpu);
81 cpumask_set_cpu(cpu, &cpus_state_saved);
82 }
83
84 atomic_inc(&cpus_in_crash);
85 smp_mb__after_atomic_inc();
86
87
88
89
90
91 while (!time_to_dump)
92 cpu_relax();
93
94 if (ppc_md.kexec_cpu_down)
95 ppc_md.kexec_cpu_down(1, 1);
96
97#ifdef CONFIG_PPC64
98 kexec_smp_wait();
99#else
100 for (;;);
101#endif
102
103
104}
105
106static void crash_kexec_prepare_cpus(int cpu)
107{
108 unsigned int msecs;
109 unsigned int ncpus = num_online_cpus() - 1;
110 int tries = 0;
111 int (*old_handler)(struct pt_regs *regs);
112
113 printk(KERN_EMERG "Sending IPI to other CPUs\n");
114
115 crash_send_ipi(crash_ipi_callback);
116 smp_wmb();
117
118again:
119
120
121
122
123
124 msecs = IPI_TIMEOUT;
125 while ((atomic_read(&cpus_in_crash) < ncpus) && (--msecs > 0))
126 mdelay(1);
127
128
129
130 if (atomic_read(&cpus_in_crash) >= ncpus) {
131 printk(KERN_EMERG "IPI complete\n");
132 return;
133 }
134
135 printk(KERN_EMERG "ERROR: %d cpu(s) not responding\n",
136 ncpus - atomic_read(&cpus_in_crash));
137
138
139
140
141
142
143 if ((panic_timeout > 0) || (tries > 0))
144 return;
145
146
147
148
149
150
151 old_handler = __debugger;
152 __debugger = handle_fault;
153 crash_shutdown_cpu = smp_processor_id();
154
155 if (setjmp(crash_shutdown_buf) == 0) {
156 printk(KERN_EMERG "Activate system reset (dumprestart) "
157 "to stop other cpu(s)\n");
158
159
160
161
162
163
164 atomic_set(&cpus_in_crash, 0);
165 smp_mb();
166
167 while (atomic_read(&cpus_in_crash) < ncpus)
168 cpu_relax();
169 }
170
171 crash_shutdown_cpu = -1;
172 __debugger = old_handler;
173
174 tries++;
175 goto again;
176}
177
178
179
180
181void crash_kexec_secondary(struct pt_regs *regs)
182{
183 unsigned long flags;
184 int msecs = SECONDARY_TIMEOUT;
185
186 local_irq_save(flags);
187
188
189 while (crashing_cpu < 0) {
190 if (--msecs < 0) {
191
192 local_irq_restore(flags);
193 return;
194 }
195
196 mdelay(1);
197 }
198
199 crash_ipi_callback(regs);
200}
201
202#else
203
204static void crash_kexec_prepare_cpus(int cpu)
205{
206
207
208
209
210
211
212#ifdef CONFIG_PPC64
213 smp_release_cpus();
214#else
215
216#endif
217}
218
219void crash_kexec_secondary(struct pt_regs *regs)
220{
221}
222#endif
223
224
225#if defined(CONFIG_SMP) && defined(CONFIG_PPC_STD_MMU_64)
226static void crash_kexec_wait_realmode(int cpu)
227{
228 unsigned int msecs;
229 int i;
230
231 msecs = REAL_MODE_TIMEOUT;
232 for (i=0; i < nr_cpu_ids && msecs > 0; i++) {
233 if (i == cpu)
234 continue;
235
236 while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
237 barrier();
238 if (!cpu_possible(i) || !cpu_online(i) || (msecs <= 0))
239 break;
240 msecs--;
241 mdelay(1);
242 }
243 }
244 mb();
245}
246#else
247static inline void crash_kexec_wait_realmode(int cpu) {}
248#endif
249
250
251
252
253
254int crash_shutdown_register(crash_shutdown_t handler)
255{
256 unsigned int i, rc;
257
258 spin_lock(&crash_handlers_lock);
259 for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
260 if (!crash_shutdown_handles[i]) {
261
262 crash_shutdown_handles[i] = handler;
263 rc = 0;
264 break;
265 }
266
267 if (i == CRASH_HANDLER_MAX) {
268 printk(KERN_ERR "Crash shutdown handles full, "
269 "not registered.\n");
270 rc = 1;
271 }
272
273 spin_unlock(&crash_handlers_lock);
274 return rc;
275}
276EXPORT_SYMBOL(crash_shutdown_register);
277
278int crash_shutdown_unregister(crash_shutdown_t handler)
279{
280 unsigned int i, rc;
281
282 spin_lock(&crash_handlers_lock);
283 for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
284 if (crash_shutdown_handles[i] == handler)
285 break;
286
287 if (i == CRASH_HANDLER_MAX) {
288 printk(KERN_ERR "Crash shutdown handle not found\n");
289 rc = 1;
290 } else {
291
292 for (; crash_shutdown_handles[i]; i++)
293 crash_shutdown_handles[i] =
294 crash_shutdown_handles[i+1];
295 rc = 0;
296 }
297
298 spin_unlock(&crash_handlers_lock);
299 return rc;
300}
301EXPORT_SYMBOL(crash_shutdown_unregister);
302
303void default_machine_crash_shutdown(struct pt_regs *regs)
304{
305 unsigned int i;
306 int (*old_handler)(struct pt_regs *regs);
307
308
309
310
311
312
313
314
315
316
317
318 hard_irq_disable();
319
320
321
322
323
324 crashing_cpu = smp_processor_id();
325
326
327
328
329
330 if (TRAP(regs) == 0x100)
331 mdelay(PRIMARY_TIMEOUT);
332
333 crash_kexec_prepare_cpus(crashing_cpu);
334
335 crash_save_cpu(regs, crashing_cpu);
336
337 time_to_dump = 1;
338
339 crash_kexec_wait_realmode(crashing_cpu);
340
341 machine_kexec_mask_interrupts();
342
343
344
345
346
347 old_handler = __debugger_fault_handler;
348 __debugger_fault_handler = handle_fault;
349 crash_shutdown_cpu = smp_processor_id();
350 for (i = 0; crash_shutdown_handles[i]; i++) {
351 if (setjmp(crash_shutdown_buf) == 0) {
352
353
354
355
356
357 asm volatile("sync; isync");
358
359 crash_shutdown_handles[i]();
360 asm volatile("sync; isync");
361 }
362 }
363 crash_shutdown_cpu = -1;
364 __debugger_fault_handler = old_handler;
365
366 if (ppc_md.kexec_cpu_down)
367 ppc_md.kexec_cpu_down(1, 0);
368}
369