aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2011-11-29 19:23:17 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-12-07 22:02:24 -0500
commit2440c01e10f07adcbc2094ba12ae4ad6094bd2b6 (patch)
tree5e14335ea80cf627a3037f348d4675d2ffa980ba /arch/powerpc/kernel
parent549e88a134b3b393a4312e8d76628b9260eee57f (diff)
powerpc/kdump: Only save CPU state first time through the secondary CPU capture code
We might enter the secondary CPU capture code twice, eg if we have to unstick some CPUs with a system reset. In this case we don't want to overwrite the state on CPUs that had made it into the capture code OK, so use the cpus_state_saved cpumask for that and make it local to crash_ipi_callback. For controlling progress now use atomic_t cpus_in_crash to count how many CPUs have made it into the kdump code, and time_to_dump to tell everyone it's time to dump. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/crash.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index b942980e9650..28be3452e67a 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -46,7 +46,8 @@
46 46
47/* This keeps a track of which one is the crashing cpu. */ 47/* This keeps a track of which one is the crashing cpu. */
48int crashing_cpu = -1; 48int crashing_cpu = -1;
49static cpumask_t cpus_in_crash = CPU_MASK_NONE; 49static atomic_t cpus_in_crash;
50static int time_to_dump;
50 51
51#define CRASH_HANDLER_MAX 3 52#define CRASH_HANDLER_MAX 3
52/* NULL terminated list of shutdown handles */ 53/* NULL terminated list of shutdown handles */
@@ -67,21 +68,27 @@ static int handle_fault(struct pt_regs *regs)
67 68
68void crash_ipi_callback(struct pt_regs *regs) 69void crash_ipi_callback(struct pt_regs *regs)
69{ 70{
71 static cpumask_t cpus_state_saved = CPU_MASK_NONE;
72
70 int cpu = smp_processor_id(); 73 int cpu = smp_processor_id();
71 74
72 if (!cpu_online(cpu)) 75 if (!cpu_online(cpu))
73 return; 76 return;
74 77
75 hard_irq_disable(); 78 hard_irq_disable();
76 if (!cpumask_test_cpu(cpu, &cpus_in_crash)) 79 if (!cpumask_test_cpu(cpu, &cpus_state_saved)) {
77 crash_save_cpu(regs, cpu); 80 crash_save_cpu(regs, cpu);
78 cpumask_set_cpu(cpu, &cpus_in_crash); 81 cpumask_set_cpu(cpu, &cpus_state_saved);
82 }
83
84 atomic_inc(&cpus_in_crash);
85 smp_mb__after_atomic_inc();
79 86
80 /* 87 /*
81 * Starting the kdump boot. 88 * Starting the kdump boot.
82 * This barrier is needed to make sure that all CPUs are stopped. 89 * This barrier is needed to make sure that all CPUs are stopped.
83 */ 90 */
84 while (!cpumask_test_cpu(crashing_cpu, &cpus_in_crash)) 91 while (!time_to_dump)
85 cpu_relax(); 92 cpu_relax();
86 93
87 if (ppc_md.kexec_cpu_down) 94 if (ppc_md.kexec_cpu_down)
@@ -115,19 +122,18 @@ again:
115 * respond. 122 * respond.
116 */ 123 */
117 msecs = IPI_TIMEOUT; 124 msecs = IPI_TIMEOUT;
118 while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) { 125 while ((atomic_read(&cpus_in_crash) < ncpus) && (--msecs > 0))
119 mdelay(1); 126 mdelay(1);
120 }
121 127
122 /* Would it be better to replace the trap vector here? */ 128 /* Would it be better to replace the trap vector here? */
123 129
124 if (cpumask_weight(&cpus_in_crash) >= ncpus) { 130 if (atomic_read(&cpus_in_crash) >= ncpus) {
125 printk(KERN_EMERG "IPI complete\n"); 131 printk(KERN_EMERG "IPI complete\n");
126 return; 132 return;
127 } 133 }
128 134
129 printk(KERN_EMERG "ERROR: %d cpu(s) not responding\n", 135 printk(KERN_EMERG "ERROR: %d cpu(s) not responding\n",
130 ncpus - cpumask_weight(&cpus_in_crash)); 136 ncpus - atomic_read(&cpus_in_crash));
131 137
132 /* 138 /*
133 * If we have a panic timeout set then we can't wait indefinitely 139 * If we have a panic timeout set then we can't wait indefinitely
@@ -155,10 +161,10 @@ again:
155 * crash code again. We need to reset cpus_in_crash so we 161 * crash code again. We need to reset cpus_in_crash so we
156 * wait for everyone to do this. 162 * wait for everyone to do this.
157 */ 163 */
158 cpus_in_crash = CPU_MASK_NONE; 164 atomic_set(&cpus_in_crash, 0);
159 smp_mb(); 165 smp_mb();
160 166
161 while (cpumask_weight(&cpus_in_crash) < ncpus) 167 while (atomic_read(&cpus_in_crash) < ncpus)
162 cpu_relax(); 168 cpu_relax();
163 } 169 }
164 170
@@ -316,7 +322,6 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
316 * such that another IPI will not be sent. 322 * such that another IPI will not be sent.
317 */ 323 */
318 crashing_cpu = smp_processor_id(); 324 crashing_cpu = smp_processor_id();
319 crash_save_cpu(regs, crashing_cpu);
320 325
321 /* 326 /*
322 * If we came in via system reset, wait a while for the secondary 327 * If we came in via system reset, wait a while for the secondary
@@ -326,7 +331,11 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
326 mdelay(PRIMARY_TIMEOUT); 331 mdelay(PRIMARY_TIMEOUT);
327 332
328 crash_kexec_prepare_cpus(crashing_cpu); 333 crash_kexec_prepare_cpus(crashing_cpu);
329 cpumask_set_cpu(crashing_cpu, &cpus_in_crash); 334
335 crash_save_cpu(regs, crashing_cpu);
336
337 time_to_dump = 1;
338
330 crash_kexec_wait_realmode(crashing_cpu); 339 crash_kexec_wait_realmode(crashing_cpu);
331 340
332 machine_kexec_mask_interrupts(); 341 machine_kexec_mask_interrupts();