diff options
author | Milton Miller <miltonm@bga.com> | 2011-05-10 15:28:33 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-05-19 00:30:43 -0400 |
commit | 3d2cea732d68aa270c360f55d8669820ebce188a (patch) | |
tree | 2f43b11f58c81aa6891dae39f91f674842bb7e7e | |
parent | f0e939ae373836400b38e090d78fba6a183976f0 (diff) |
powerpc/kexec: Fix memory corruption from unallocated slaves
Commit 1fc711f7ffb01089efc58042cfdbac8573d1b59a (powerpc/kexec: Fix race
in kexec shutdown) moved the write to signal the cpu had exited the kernel
from before the transition to real mode in kexec_smp_wait to kexec_wait.
Unfornately it missed that kexec_wait is used both by cpus leaving the
kernel and by secondary slave cpus that were not allocated a paca for
what ever reason -- they could be beyond nr_cpus or not described in
the current device tree for whatever reason (for example, kexec-load
was not refreshed after a cpu hotplug operation). Cpus coming through
that path they will write to paca[NR_CPUS] which is beyond the space
allocated for the paca data and overwrite memory not allocated to pacas
but very likely still real mode accessable).
Move the write back to kexec_smp_wait, which is used only by cpus that
found their paca, but after the transition to real mode.
Signed-off-by: Milton Miller <miltonm@bga.com>
Cc: <stable@kernel.org> # (1fc711f was backported to 2.6.32)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/misc_64.S | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 206a321a71d3..e89df59cdc5a 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -462,7 +462,8 @@ _GLOBAL(disable_kernel_fp) | |||
462 | * wait for the flag to change, indicating this kernel is going away but | 462 | * wait for the flag to change, indicating this kernel is going away but |
463 | * the slave code for the next one is at addresses 0 to 100. | 463 | * the slave code for the next one is at addresses 0 to 100. |
464 | * | 464 | * |
465 | * This is used by all slaves. | 465 | * This is used by all slaves, even those that did not find a matching |
466 | * paca in the secondary startup code. | ||
466 | * | 467 | * |
467 | * Physical (hardware) cpu id should be in r3. | 468 | * Physical (hardware) cpu id should be in r3. |
468 | */ | 469 | */ |
@@ -471,10 +472,6 @@ _GLOBAL(kexec_wait) | |||
471 | 1: mflr r5 | 472 | 1: mflr r5 |
472 | addi r5,r5,kexec_flag-1b | 473 | addi r5,r5,kexec_flag-1b |
473 | 474 | ||
474 | li r4,KEXEC_STATE_REAL_MODE | ||
475 | stb r4,PACAKEXECSTATE(r13) | ||
476 | SYNC | ||
477 | |||
478 | 99: HMT_LOW | 475 | 99: HMT_LOW |
479 | #ifdef CONFIG_KEXEC /* use no memory without kexec */ | 476 | #ifdef CONFIG_KEXEC /* use no memory without kexec */ |
480 | lwz r4,0(r5) | 477 | lwz r4,0(r5) |
@@ -499,11 +496,17 @@ kexec_flag: | |||
499 | * | 496 | * |
500 | * get phys id from paca | 497 | * get phys id from paca |
501 | * switch to real mode | 498 | * switch to real mode |
499 | * mark the paca as no longer used | ||
502 | * join other cpus in kexec_wait(phys_id) | 500 | * join other cpus in kexec_wait(phys_id) |
503 | */ | 501 | */ |
504 | _GLOBAL(kexec_smp_wait) | 502 | _GLOBAL(kexec_smp_wait) |
505 | lhz r3,PACAHWCPUID(r13) | 503 | lhz r3,PACAHWCPUID(r13) |
506 | bl real_mode | 504 | bl real_mode |
505 | |||
506 | li r4,KEXEC_STATE_REAL_MODE | ||
507 | stb r4,PACAKEXECSTATE(r13) | ||
508 | SYNC | ||
509 | |||
507 | b .kexec_wait | 510 | b .kexec_wait |
508 | 511 | ||
509 | /* | 512 | /* |