Skip to contentSkip to conversation

powerpc/kexec: Switch to a static PACA on the way out

PATCH In review Matt Evans 2 participants 2 messages Jul 8, 2010 – Jul 23, 2010 PowerPC

lore
Share & tools
lore

Matt Evans

author
#0 lore raw

PATCH v2 1/1 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.

---
v2: Changes from Milton's review:
- Use setup_paca() and move from setup_64.c,
- SLB cache inval. not required,
- Adjust 'paca' (oops..), and
- Poison data_offset/per_cpu_offset

 arch/powerpc/include/asm/paca.h        |    2 +-
 arch/powerpc/kernel/machine_kexec_64.c |   20 ++++++++++++++++++++
 arch/powerpc/kernel/paca.c             |   10 ++++++++++
 arch/powerpc/kernel/setup_64.c         |   10 ----------
 4 files changed, 31 insertions(+), 11 deletions(-)
arch/powerpc/include/asm/paca.h +1 -1
index 8ce7963..1ff6662 100644
@@ -146,7 +146,7 @@ struct paca_struct {
 extern struct paca_struct *paca;
 extern __initdata struct paca_struct boot_paca;
 extern void initialise_paca(struct paca_struct *new_paca, int cpu);
-
+extern void setup_paca(struct paca_struct *new_paca);
 extern void allocate_pacas(void);
 extern void free_unused_pacas(void);
 
arch/powerpc/kernel/machine_kexec_64.c +20 -0
index 26f9900..c4d0123 100644
@@ -273,6 +273,12 @@ static void kexec_prepare_cpus(void)
 static union thread_union kexec_stack __init_task_data =
 	{ };
 
+/*
+ * For similar reasons to the stack above, the kexecing CPU needs to be on a
+ * static PACA; we switch to kexec_paca.
+ */
+struct paca_struct kexec_paca;
+
 /* Our assembly helper, in kexec_stub.S */
 extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
 					void *image, void *control,
@@ -300,6 +306,20 @@ void default_machine_kexec(struct kimage *image)
 	kexec_stack.thread_info.task = current_thread_info()->task;
 	kexec_stack.thread_info.flags = 0;
 
+	/* We need a static PACA, too; copy this CPU's PACA over and switch to
+	 * it.  Also poison per_cpu_offset to catch anyone using non-static
+	 * data.
+	 */
+	memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct));
+	kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL;
+	paca = (struct paca_struct *)RELOC_HIDE(&kexec_paca, 0) -
+		kexec_paca.paca_index;
+	setup_paca(&kexec_paca);
+
+	/* XXX: If anyone does 'dynamic lppacas' this will also need to be
+	 * switched to a static version!
+	 */
+
 	/* Some things are best done in assembly.  Finding globals with
 	 * a toc is easier in C, so pass in what we can.
 	 */
arch/powerpc/kernel/paca.c +10 -0
index f88acf0..3db8d64 100644
@@ -105,6 +105,16 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 #endif /* CONFIG_PPC_STD_MMU_64 */
 }
 
+/* Put the paca pointer into r13 and SPRG_PACA */
+void setup_paca(struct paca_struct *new_paca)
+{
+	local_paca = new_paca;
+	mtspr(SPRN_SPRG_PACA, local_paca);
+#ifdef CONFIG_PPC_BOOK3E
+	mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
+#endif
+}
+
 static int __initdata paca_size;
 
 void __init allocate_pacas(void)
arch/powerpc/kernel/setup_64.c +0 -10
index f3fb5a7..6efbed4 100644
@@ -142,16 +142,6 @@ early_param("smt-enabled", early_smt_enabled);
 #define check_smt_enabled()
 #endif /* CONFIG_SMP */
 
-/* Put the paca pointer into r13 and SPRG_PACA */
-static void __init setup_paca(struct paca_struct *new_paca)
-{
-	local_paca = new_paca;
-	mtspr(SPRN_SPRG_PACA, local_paca);
-#ifdef CONFIG_PPC_BOOK3E
-	mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
-#endif
-}
-
 /*
  * Early initialization entry point. This is called by head.S
  * with MMU translation disabled. We rely on the "feature" of
Signature · 1 line
1.6.3.3
#1 lore raw
Quoted 37 lines · Matt Evans

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.

---
v2: Changes from Milton's review:
- Use setup_paca() and move from setup_64.c,
- SLB cache inval. not required,
- Adjust 'paca' (oops..), and
- Poison data_offset/per_cpu_offset

 arch/powerpc/include/asm/paca.h        |    2 +-
 arch/powerpc/kernel/machine_kexec_64.c |   20 ++++++++++++++++++++
 arch/powerpc/kernel/paca.c             |   10 ++++++++++
 arch/powerpc/kernel/setup_64.c         |   10 ----------
 4 files changed, 31 insertions(+), 11 deletions(-)
arch/powerpc/include/asm/paca.h +1 -1
index 8ce7963..1ff6662 100644
@@ -146,7 +146,7 @@ struct paca_struct {
 extern struct paca_struct *paca;
 extern __initdata struct paca_struct boot_paca;
 extern void initialise_paca(struct paca_struct *new_paca, int cpu);
-
+extern void setup_paca(struct paca_struct *new_paca);
 extern void allocate_pacas(void);
 extern void free_unused_pacas(void);
 
arch/powerpc/kernel/machine_kexec_64.c +0 -0
index 26f9900..c4d0123 100644

arch/powerpc/kernel/machine_kexec_64.c static void kexec_prepare_cpus(void) · line 281

Quoted 9 lines
arch/powerpc/kernel/machine_kexec_64.c +6 -0
@@ -273,6 +273,12 @@ static void kexec_prepare_cpus(void)
 static union thread_union kexec_stack __init_task_data =
 	{ };
 
+/*
+ * For similar reasons to the stack above, the kexecing CPU needs to be on a
+ * static PACA; we switch to kexec_paca.
+ */
+struct paca_struct kexec_paca;
+

Hopelessly late probably but .. we could use boot_paca which already exists and is static.

cheers