aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Evans <matt@ozlabs.org>2010-07-07 17:55:37 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-07-31 00:56:30 -0400
commitfc53b4202e61c7e9008c241933ae282aab8a6082 (patch)
treec279a5256ba18a27ca0b785ecf6819f592a23509
parent7e3f36c3e107bd76b6709e358b1e7c703fb6f81a (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.h2
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c20
-rw-r--r--arch/powerpc/kernel/paca.c10
-rw-r--r--arch/powerpc/kernel/setup_64.c10
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 {
146extern struct paca_struct *paca; 146extern struct paca_struct *paca;
147extern __initdata struct paca_struct boot_paca; 147extern __initdata struct paca_struct boot_paca;
148extern void initialise_paca(struct paca_struct *new_paca, int cpu); 148extern void initialise_paca(struct paca_struct *new_paca, int cpu);
149 149extern void setup_paca(struct paca_struct *new_paca);
150extern void allocate_pacas(void); 150extern void allocate_pacas(void);
151extern void free_unused_pacas(void); 151extern 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)
260static union thread_union kexec_stack __init_task_data = 260static 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 */
267struct paca_struct kexec_paca;
268
263/* Our assembly helper, in kexec_stub.S */ 269/* Our assembly helper, in kexec_stub.S */
264extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, 270extern 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 */
109void 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
108static int __initdata paca_size; 118static int __initdata paca_size;
109 119
110void __init allocate_pacas(void) 120void __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 */
146static 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