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>
This commit is contained in:
parent
7e3f36c3e1
commit
fc53b4202e
@ -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);
|
||||
|
||||
|
@ -260,6 +260,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,
|
||||
@ -287,6 +293,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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user