Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa3f82c8 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 963e5d3b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ extern void cpu_die(void);


extern void smp_send_debugger_break(int cpu);
extern void smp_send_debugger_break(int cpu);
extern void smp_message_recv(int);
extern void smp_message_recv(int);
extern void start_secondary_resume(void);


DECLARE_PER_CPU(unsigned int, cpu_pvr);
DECLARE_PER_CPU(unsigned int, cpu_pvr);


+9 −0
Original line number Original line Diff line number Diff line
@@ -890,6 +890,15 @@ __secondary_start:
	mtspr	SPRN_SRR1,r4
	mtspr	SPRN_SRR1,r4
	SYNC
	SYNC
	RFI
	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 */
#endif /* CONFIG_SMP */


#ifdef CONFIG_KVM_BOOK3S_HANDLER
#ifdef CONFIG_KVM_BOOK3S_HANDLER
+7 −2
Original line number Original line Diff line number Diff line
@@ -502,7 +502,7 @@ static struct device_node *cpu_to_l2cache(int cpu)
}
}


/* Activate a secondary processor. */
/* Activate a secondary processor. */
int __devinit start_secondary(void *unused)
void __devinit start_secondary(void *unused)
{
{
	unsigned int cpu = smp_processor_id();
	unsigned int cpu = smp_processor_id();
	struct device_node *l2_cache;
	struct device_node *l2_cache;
@@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused)
	local_irq_enable();
	local_irq_enable();


	cpu_idle();
	cpu_idle();
	return 0;

	BUG();
}
}


int setup_profiling_timer(unsigned int multiplier)
int setup_profiling_timer(unsigned int multiplier)
@@ -660,5 +661,9 @@ void cpu_die(void)
{
{
	if (ppc_md.cpu_die)
	if (ppc_md.cpu_die)
		ppc_md.cpu_die();
		ppc_md.cpu_die();

	/* If we return, we re-enter start_secondary */
	start_secondary_resume();
}
}

#endif
#endif
+0 −2
Original line number Original line Diff line number Diff line
@@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu)
#endif
#endif


extern enum cpu_state_vals get_preferred_offline_state(int cpu);
extern enum cpu_state_vals get_preferred_offline_state(int cpu);
extern int start_secondary(void);
extern void start_secondary_resume(void);
#endif
#endif