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 | |
| 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>
| -rw-r--r-- | arch/powerpc/include/asm/paca.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 20 | ||||
| -rw-r--r-- | arch/powerpc/kernel/paca.c | 10 | ||||
| -rw-r--r-- | arch/powerpc/kernel/setup_64.c | 10 |
4 files changed, 31 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 8ce7963ad41d..1ff6662f7faf 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -146,7 +146,7 @@ struct paca_struct { | |||
| 146 | extern struct paca_struct *paca; | 146 | extern struct paca_struct *paca; |
| 147 | extern __initdata struct paca_struct boot_paca; | 147 | extern __initdata struct paca_struct boot_paca; |
| 148 | extern void initialise_paca(struct paca_struct *new_paca, int cpu); | 148 | extern void initialise_paca(struct paca_struct *new_paca, int cpu); |
| 149 | 149 | extern void setup_paca(struct paca_struct *new_paca); | |
| 150 | extern void allocate_pacas(void); | 150 | extern void allocate_pacas(void); |
| 151 | extern void free_unused_pacas(void); | 151 | extern void free_unused_pacas(void); |
| 152 | 152 | ||
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 | */ |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index f88acf0218db..3db8d64f40e1 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -105,6 +105,16 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
| 105 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 105 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* Put the paca pointer into r13 and SPRG_PACA */ | ||
| 109 | void setup_paca(struct paca_struct *new_paca) | ||
| 110 | { | ||
| 111 | local_paca = new_paca; | ||
| 112 | mtspr(SPRN_SPRG_PACA, local_paca); | ||
| 113 | #ifdef CONFIG_PPC_BOOK3E | ||
| 114 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
| 115 | #endif | ||
| 116 | } | ||
| 117 | |||
| 108 | static int __initdata paca_size; | 118 | static int __initdata paca_size; |
| 109 | 119 | ||
| 110 | void __init allocate_pacas(void) | 120 | void __init allocate_pacas(void) |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index c352f322dbdd..96e662c1d46b 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -142,16 +142,6 @@ early_param("smt-enabled", early_smt_enabled); | |||
| 142 | #define check_smt_enabled() | 142 | #define check_smt_enabled() |
| 143 | #endif /* CONFIG_SMP */ | 143 | #endif /* CONFIG_SMP */ |
| 144 | 144 | ||
| 145 | /* Put the paca pointer into r13 and SPRG_PACA */ | ||
| 146 | static void __init setup_paca(struct paca_struct *new_paca) | ||
| 147 | { | ||
| 148 | local_paca = new_paca; | ||
| 149 | mtspr(SPRN_SPRG_PACA, local_paca); | ||
| 150 | #ifdef CONFIG_PPC_BOOK3E | ||
| 151 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
| 152 | #endif | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | 145 | /* |
| 156 | * Early initialization entry point. This is called by head.S | 146 | * Early initialization entry point. This is called by head.S |
| 157 | * with MMU translation disabled. We rely on the "feature" of | 147 | * with MMU translation disabled. We rely on the "feature" of |
