powerpc/smp: soft-replugged CPUs must go back to start_secondary
Various thing are torn down when a CPU is hot-unplugged. That CPU is expected to go back to start_secondary when re-plugged to re initialize everything, such as clock sources, maps, ... Some implementations just return from cpu_die() callback in the idle loop when the CPU is "re-plugged". This is not enough. We fix it using a little asm trampoline which resets the stack and calls back into start_secondary as if we were all fresh from boot. The trampoline already existed on ppc64, but we add it for ppc32 Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
		| @@ -36,6 +36,7 @@ extern void cpu_die(void); | ||||
|  | ||||
| extern void smp_send_debugger_break(int cpu); | ||||
| extern void smp_message_recv(int); | ||||
| extern void start_secondary_resume(void); | ||||
|  | ||||
| DECLARE_PER_CPU(unsigned int, cpu_pvr); | ||||
|  | ||||
|   | ||||
| @@ -890,6 +890,15 @@ __secondary_start: | ||||
| 	mtspr	SPRN_SRR1,r4 | ||||
| 	SYNC | ||||
| 	RFI | ||||
|  | ||||
| _GLOBAL(start_secondary_resume) | ||||
| 	/* Reset stack */ | ||||
| 	rlwinm	r1,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */ | ||||
| 	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | ||||
| 	li	r3,0 | ||||
| 	std	r3,0(r1)		/* Zero the stack frame pointer	*/ | ||||
| 	bl	start_secondary | ||||
| 	b	. | ||||
| #endif /* CONFIG_SMP */ | ||||
|  | ||||
| #ifdef CONFIG_KVM_BOOK3S_HANDLER | ||||
|   | ||||
| @@ -502,7 +502,7 @@ static struct device_node *cpu_to_l2cache(int cpu) | ||||
| } | ||||
|  | ||||
| /* Activate a secondary processor. */ | ||||
| int __devinit start_secondary(void *unused) | ||||
| void __devinit start_secondary(void *unused) | ||||
| { | ||||
| 	unsigned int cpu = smp_processor_id(); | ||||
| 	struct device_node *l2_cache; | ||||
| @@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused) | ||||
| 	local_irq_enable(); | ||||
|  | ||||
| 	cpu_idle(); | ||||
| 	return 0; | ||||
|  | ||||
| 	BUG(); | ||||
| } | ||||
|  | ||||
| int setup_profiling_timer(unsigned int multiplier) | ||||
| @@ -660,5 +661,9 @@ void cpu_die(void) | ||||
| { | ||||
| 	if (ppc_md.cpu_die) | ||||
| 		ppc_md.cpu_die(); | ||||
|  | ||||
| 	/* If we return, we re-enter start_secondary */ | ||||
| 	start_secondary_resume(); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu) | ||||
| #endif | ||||
|  | ||||
| extern enum cpu_state_vals get_preferred_offline_state(int cpu); | ||||
| extern int start_secondary(void); | ||||
| extern void start_secondary_resume(void); | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user