aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/machine_kexec_64.c
diff options
context:
space:
mode:
authorMatt Evans <matt@ozlabs.org>2010-07-29 14:49:08 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-31 01:05:22 -0400
commite8e5c2155b0035b6e04f29be67f6444bc914005b (patch)
tree053dc35d425029ea221abc32c0ac81f3512cd2b0 /arch/powerpc/kernel/machine_kexec_64.c
parente2f7f73717c0a2927bbe7551d90b1ec47a094361 (diff)
powerpc/kexec: Fix orphaned offline CPUs across kexec
When CPU hotplug is used, some CPUs may be offline at the time a kexec is performed. The subsequent kernel may expect these CPUs to be already running, and will declare them stuck. On pseries, there's also a soft-offline (cede) state that CPUs may be in; this can also cause problems as the kexeced kernel may ask RTAS if they're online -- and RTAS would say they are. The CPU will either appear stuck, or will cause a crash as we replace its cede loop beneath it. This patch kicks each present offline CPU awake before the kexec, so that none are forever lost to these assumptions in the subsequent kernel. Now, the behaviour is that all available CPUs that were offlined are now online & usable after the kexec. This mimics the behaviour of a full reboot (on which all CPUs will be restarted). Signed-off-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/machine_kexec_64.c')
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index a0bcec3614e1..583af70c4b14 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -16,6 +16,7 @@
16#include <linux/init_task.h> 16#include <linux/init_task.h>
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/cpu.h>
19 20
20#include <asm/page.h> 21#include <asm/page.h>
21#include <asm/current.h> 22#include <asm/current.h>
@@ -216,9 +217,32 @@ static void kexec_prepare_cpus_wait(int wait_state)
216 mb(); 217 mb();
217} 218}
218 219
219static void kexec_prepare_cpus(void) 220/*
221 * We need to make sure each present CPU is online. The next kernel will scan
222 * the device tree and assume primary threads are online and query secondary
223 * threads via RTAS to online them if required. If we don't online primary
224 * threads, they will be stuck. However, we also online secondary threads as we
225 * may be using 'cede offline'. In this case RTAS doesn't see the secondary
226 * threads as offline -- and again, these CPUs will be stuck.
227 *
228 * So, we online all CPUs that should be running, including secondary threads.
229 */
230static void wake_offline_cpus(void)
220{ 231{
232 int cpu = 0;
233
234 for_each_present_cpu(cpu) {
235 if (!cpu_online(cpu)) {
236 printk(KERN_INFO "kexec: Waking offline cpu %d.\n",
237 cpu);
238 cpu_up(cpu);
239 }
240 }
241}
221 242
243static void kexec_prepare_cpus(void)
244{
245 wake_offline_cpus();
222 smp_call_function(kexec_smp_down, NULL, /* wait */0); 246 smp_call_function(kexec_smp_down, NULL, /* wait */0);
223 local_irq_disable(); 247 local_irq_disable();
224 mb(); /* make sure IRQs are disabled before we say they are */ 248 mb(); /* make sure IRQs are disabled before we say they are */