Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+17 -4
+1
arch/powerpc/include/asm/smp.h
··· 36 36 37 37 extern void smp_send_debugger_break(int cpu); 38 38 extern void smp_message_recv(int); 39 + extern void start_secondary_resume(void); 39 40 40 41 DECLARE_PER_CPU(unsigned int, cpu_pvr); 41 42
+9
arch/powerpc/kernel/head_32.S
··· 890 890 mtspr SPRN_SRR1,r4 891 891 SYNC 892 892 RFI 893 + 894 + _GLOBAL(start_secondary_resume) 895 + /* Reset stack */ 896 + rlwinm r1,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ 897 + addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD 898 + li r3,0 899 + std r3,0(r1) /* Zero the stack frame pointer */ 900 + bl start_secondary 901 + b . 893 902 #endif /* CONFIG_SMP */ 894 903 895 904 #ifdef CONFIG_KVM_BOOK3S_HANDLER
+7 -2
arch/powerpc/kernel/smp.c
··· 502 502 } 503 503 504 504 /* Activate a secondary processor. */ 505 - int __devinit start_secondary(void *unused) 505 + void __devinit start_secondary(void *unused) 506 506 { 507 507 unsigned int cpu = smp_processor_id(); 508 508 struct device_node *l2_cache; ··· 558 558 local_irq_enable(); 559 559 560 560 cpu_idle(); 561 - return 0; 561 + 562 + BUG(); 562 563 } 563 564 564 565 int setup_profiling_timer(unsigned int multiplier) ··· 661 660 { 662 661 if (ppc_md.cpu_die) 663 662 ppc_md.cpu_die(); 663 + 664 + /* If we return, we re-enter start_secondary */ 665 + start_secondary_resume(); 664 666 } 667 + 665 668 #endif
-2
arch/powerpc/platforms/pseries/offline_states.h
··· 34 34 #endif 35 35 36 36 extern enum cpu_state_vals get_preferred_offline_state(int cpu); 37 - extern int start_secondary(void); 38 - extern void start_secondary_resume(void); 39 37 #endif