Merge git://git.infradead.org/battery-2.6
[pandora-kernel.git] / arch / powerpc / kernel / crash.c
1 /*
2  * Architecture specific (PPC64) functions for kexec based crash dumps.
3  *
4  * Copyright (C) 2005, IBM Corp.
5  *
6  * Created by: Haren Myneni
7  *
8  * This source code is licensed under the GNU General Public License,
9  * Version 2.  See the file COPYING for more details.
10  *
11  */
12
13 #undef DEBUG
14
15 #include <linux/kernel.h>
16 #include <linux/smp.h>
17 #include <linux/reboot.h>
18 #include <linux/kexec.h>
19 #include <linux/bootmem.h>
20 #include <linux/crash_dump.h>
21 #include <linux/delay.h>
22 #include <linux/elf.h>
23 #include <linux/elfcore.h>
24 #include <linux/init.h>
25 #include <linux/irq.h>
26 #include <linux/types.h>
27
28 #include <asm/processor.h>
29 #include <asm/machdep.h>
30 #include <asm/kexec.h>
31 #include <asm/kdump.h>
32 #include <asm/lmb.h>
33 #include <asm/firmware.h>
34 #include <asm/smp.h>
35
36 #ifdef DEBUG
37 #include <asm/udbg.h>
38 #define DBG(fmt...) udbg_printf(fmt)
39 #else
40 #define DBG(fmt...)
41 #endif
42
43 /* This keeps a track of which one is crashing cpu. */
44 int crashing_cpu = -1;
45 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
46 cpumask_t cpus_in_sr = CPU_MASK_NONE;
47
48 #ifdef CONFIG_SMP
49 static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
50
51 void crash_ipi_callback(struct pt_regs *regs)
52 {
53         int cpu = smp_processor_id();
54
55         if (!cpu_online(cpu))
56                 return;
57
58         hard_irq_disable();
59         if (!cpu_isset(cpu, cpus_in_crash))
60                 crash_save_cpu(regs, cpu);
61         cpu_set(cpu, cpus_in_crash);
62
63         /*
64          * Entered via soft-reset - could be the kdump
65          * process is invoked using soft-reset or user activated
66          * it if some CPU did not respond to an IPI.
67          * For soft-reset, the secondary CPU can enter this func
68          * twice. 1 - using IPI, and 2. soft-reset.
69          * Tell the kexec CPU that entered via soft-reset and ready
70          * to go down.
71          */
72         if (cpu_isset(cpu, cpus_in_sr)) {
73                 cpu_clear(cpu, cpus_in_sr);
74                 atomic_inc(&enter_on_soft_reset);
75         }
76
77         /*
78          * Starting the kdump boot.
79          * This barrier is needed to make sure that all CPUs are stopped.
80          * If not, soft-reset will be invoked to bring other CPUs.
81          */
82         while (!cpu_isset(crashing_cpu, cpus_in_crash))
83                 cpu_relax();
84
85         if (ppc_md.kexec_cpu_down)
86                 ppc_md.kexec_cpu_down(1, 1);
87
88 #ifdef CONFIG_PPC64
89         kexec_smp_wait();
90 #else
91         for (;;);       /* FIXME */
92 #endif
93
94         /* NOTREACHED */
95 }
96
97 /*
98  * Wait until all CPUs are entered via soft-reset.
99  */
100 static void crash_soft_reset_check(int cpu)
101 {
102         unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
103
104         cpu_clear(cpu, cpus_in_sr);
105         while (atomic_read(&enter_on_soft_reset) != ncpus)
106                 cpu_relax();
107 }
108
109
110 static void crash_kexec_prepare_cpus(int cpu)
111 {
112         unsigned int msecs;
113
114         unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
115
116         crash_send_ipi(crash_ipi_callback);
117         smp_wmb();
118
119         /*
120          * FIXME: Until we will have the way to stop other CPUSs reliabally,
121          * the crash CPU will send an IPI and wait for other CPUs to
122          * respond.
123          * Delay of at least 10 seconds.
124          */
125         printk(KERN_EMERG "Sending IPI to other cpus...\n");
126         msecs = 10000;
127         while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
128                 cpu_relax();
129                 mdelay(1);
130         }
131
132         /* Would it be better to replace the trap vector here? */
133
134         /*
135          * FIXME: In case if we do not get all CPUs, one possibility: ask the
136          * user to do soft reset such that we get all.
137          * Soft-reset will be used until better mechanism is implemented.
138          */
139         if (cpus_weight(cpus_in_crash) < ncpus) {
140                 printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
141                         ncpus - cpus_weight(cpus_in_crash));
142                 printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
143                 cpus_in_sr = CPU_MASK_NONE;
144                 atomic_set(&enter_on_soft_reset, 0);
145                 while (cpus_weight(cpus_in_crash) < ncpus)
146                         cpu_relax();
147         }
148         /*
149          * Make sure all CPUs are entered via soft-reset if the kdump is
150          * invoked using soft-reset.
151          */
152         if (cpu_isset(cpu, cpus_in_sr))
153                 crash_soft_reset_check(cpu);
154         /* Leave the IPI callback set */
155 }
156
157 /*
158  * This function will be called by secondary cpus or by kexec cpu
159  * if soft-reset is activated to stop some CPUs.
160  */
161 void crash_kexec_secondary(struct pt_regs *regs)
162 {
163         int cpu = smp_processor_id();
164         unsigned long flags;
165         int msecs = 5;
166
167         local_irq_save(flags);
168         /* Wait 5ms if the kexec CPU is not entered yet. */
169         while (crashing_cpu < 0) {
170                 if (--msecs < 0) {
171                         /*
172                          * Either kdump image is not loaded or
173                          * kdump process is not started - Probably xmon
174                          * exited using 'x'(exit and recover) or
175                          * kexec_should_crash() failed for all running tasks.
176                          */
177                         cpu_clear(cpu, cpus_in_sr);
178                         local_irq_restore(flags);
179                         return;
180                 }
181                 mdelay(1);
182                 cpu_relax();
183         }
184         if (cpu == crashing_cpu) {
185                 /*
186                  * Panic CPU will enter this func only via soft-reset.
187                  * Wait until all secondary CPUs entered and
188                  * then start kexec boot.
189                  */
190                 crash_soft_reset_check(cpu);
191                 cpu_set(crashing_cpu, cpus_in_crash);
192                 if (ppc_md.kexec_cpu_down)
193                         ppc_md.kexec_cpu_down(1, 0);
194                 machine_kexec(kexec_crash_image);
195                 /* NOTREACHED */
196         }
197         crash_ipi_callback(regs);
198 }
199
200 #else
201 static void crash_kexec_prepare_cpus(int cpu)
202 {
203         /*
204          * move the secondarys to us so that we can copy
205          * the new kernel 0-0x100 safely
206          *
207          * do this if kexec in setup.c ?
208          */
209 #ifdef CONFIG_PPC64
210         smp_release_cpus();
211 #else
212         /* FIXME */
213 #endif
214 }
215
216 void crash_kexec_secondary(struct pt_regs *regs)
217 {
218         cpus_in_sr = CPU_MASK_NONE;
219 }
220 #endif
221 #ifdef CONFIG_SPU_BASE
222
223 #include <asm/spu.h>
224 #include <asm/spu_priv1.h>
225
226 struct crash_spu_info {
227         struct spu *spu;
228         u32 saved_spu_runcntl_RW;
229         u32 saved_spu_status_R;
230         u32 saved_spu_npc_RW;
231         u64 saved_mfc_sr1_RW;
232         u64 saved_mfc_dar;
233         u64 saved_mfc_dsisr;
234 };
235
236 #define CRASH_NUM_SPUS  16      /* Enough for current hardware */
237 static struct crash_spu_info crash_spu_info[CRASH_NUM_SPUS];
238
239 static void crash_kexec_stop_spus(void)
240 {
241         struct spu *spu;
242         int i;
243         u64 tmp;
244
245         for (i = 0; i < CRASH_NUM_SPUS; i++) {
246                 if (!crash_spu_info[i].spu)
247                         continue;
248
249                 spu = crash_spu_info[i].spu;
250
251                 crash_spu_info[i].saved_spu_runcntl_RW =
252                         in_be32(&spu->problem->spu_runcntl_RW);
253                 crash_spu_info[i].saved_spu_status_R =
254                         in_be32(&spu->problem->spu_status_R);
255                 crash_spu_info[i].saved_spu_npc_RW =
256                         in_be32(&spu->problem->spu_npc_RW);
257
258                 crash_spu_info[i].saved_mfc_dar    = spu_mfc_dar_get(spu);
259                 crash_spu_info[i].saved_mfc_dsisr  = spu_mfc_dsisr_get(spu);
260                 tmp = spu_mfc_sr1_get(spu);
261                 crash_spu_info[i].saved_mfc_sr1_RW = tmp;
262
263                 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
264                 spu_mfc_sr1_set(spu, tmp);
265
266                 __delay(200);
267         }
268 }
269
270 void crash_register_spus(struct list_head *list)
271 {
272         struct spu *spu;
273
274         list_for_each_entry(spu, list, full_list) {
275                 if (WARN_ON(spu->number >= CRASH_NUM_SPUS))
276                         continue;
277
278                 crash_spu_info[spu->number].spu = spu;
279         }
280 }
281
282 #else
283 static inline void crash_kexec_stop_spus(void)
284 {
285 }
286 #endif /* CONFIG_SPU_BASE */
287
288 void default_machine_crash_shutdown(struct pt_regs *regs)
289 {
290         unsigned int irq;
291
292         /*
293          * This function is only called after the system
294          * has panicked or is otherwise in a critical state.
295          * The minimum amount of code to allow a kexec'd kernel
296          * to run successfully needs to happen here.
297          *
298          * In practice this means stopping other cpus in
299          * an SMP system.
300          * The kernel is broken so disable interrupts.
301          */
302         hard_irq_disable();
303
304         for_each_irq(irq) {
305                 struct irq_desc *desc = irq_desc + irq;
306
307                 if (desc->status & IRQ_INPROGRESS)
308                         desc->chip->eoi(irq);
309
310                 if (!(desc->status & IRQ_DISABLED))
311                         desc->chip->disable(irq);
312         }
313
314         /*
315          * Make a note of crashing cpu. Will be used in machine_kexec
316          * such that another IPI will not be sent.
317          */
318         crashing_cpu = smp_processor_id();
319         crash_save_cpu(regs, crashing_cpu);
320         crash_kexec_prepare_cpus(crashing_cpu);
321         cpu_set(crashing_cpu, cpus_in_crash);
322         crash_kexec_stop_spus();
323         if (ppc_md.kexec_cpu_down)
324                 ppc_md.kexec_cpu_down(1, 0);
325 }