diff options
author | Matt Evans <matt@ozlabs.org> | 2010-07-07 17:55:37 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-07-31 00:56:30 -0400 |
commit | fc53b4202e61c7e9008c241933ae282aab8a6082 (patch) | |
tree | c279a5256ba18a27ca0b785ecf6819f592a23509 /arch/powerpc/kernel/machine_kexec_64.c | |
parent | 7e3f36c3e107bd76b6709e358b1e7c703fb6f81a (diff) |
powerpc/kexec: Switch to a static PACA on the way out
With dynamic PACAs, the kexecing CPU's PACA won't lie within the kernel
static data and there is a chance that something may stomp it when preparing
to kexec. This patch switches this final CPU to a static PACA just before
we pull the switch.
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.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index de6b70eac51d..022d2f613b7b 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -260,6 +260,12 @@ static void kexec_prepare_cpus(void) | |||
260 | static union thread_union kexec_stack __init_task_data = | 260 | static union thread_union kexec_stack __init_task_data = |
261 | { }; | 261 | { }; |
262 | 262 | ||
263 | /* | ||
264 | * For similar reasons to the stack above, the kexecing CPU needs to be on a | ||
265 | * static PACA; we switch to kexec_paca. | ||
266 | */ | ||
267 | struct paca_struct kexec_paca; | ||
268 | |||
263 | /* Our assembly helper, in kexec_stub.S */ | 269 | /* Our assembly helper, in kexec_stub.S */ |
264 | extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, | 270 | extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, |
265 | void *image, void *control, | 271 | void *image, void *control, |
@@ -287,6 +293,20 @@ void default_machine_kexec(struct kimage *image) | |||
287 | kexec_stack.thread_info.task = current_thread_info()->task; | 293 | kexec_stack.thread_info.task = current_thread_info()->task; |
288 | kexec_stack.thread_info.flags = 0; | 294 | kexec_stack.thread_info.flags = 0; |
289 | 295 | ||
296 | /* We need a static PACA, too; copy this CPU's PACA over and switch to | ||
297 | * it. Also poison per_cpu_offset to catch anyone using non-static | ||
298 | * data. | ||
299 | */ | ||
300 | memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct)); | ||
301 | kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL; | ||
302 | paca = (struct paca_struct *)RELOC_HIDE(&kexec_paca, 0) - | ||
303 | kexec_paca.paca_index; | ||
304 | setup_paca(&kexec_paca); | ||
305 | |||
306 | /* XXX: If anyone does 'dynamic lppacas' this will also need to be | ||
307 | * switched to a static version! | ||
308 | */ | ||
309 | |||
290 | /* Some things are best done in assembly. Finding globals with | 310 | /* Some things are best done in assembly. Finding globals with |
291 | * a toc is easier in C, so pass in what we can. | 311 | * a toc is easier in C, so pass in what we can. |
292 | */ | 312 | */ |