aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-02-10 02:45:24 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-01 00:37:09 -0400
commitfa3f82c8bb7acbe049ea71f258b3ae0a33d9d40b (patch)
tree9c5e71195c7948c139ea37d8d0e0287f062910f9 /arch
parent963e5d3b76d657f1ebcf3561446d2ba1872bbfa2 (diff)
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/smp.h1
-rw-r--r--arch/powerpc/kernel/head_32.S9
-rw-r--r--arch/powerpc/kernel/smp.c9
-rw-r--r--arch/powerpc/platforms/pseries/offline_states.h2
4 files changed, 17 insertions, 4 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 66e237bbe15f..1de0e97a394f 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -36,6 +36,7 @@ extern void cpu_die(void);
36 36
37extern void smp_send_debugger_break(int cpu); 37extern void smp_send_debugger_break(int cpu);
38extern void smp_message_recv(int); 38extern void smp_message_recv(int);
39extern void start_secondary_resume(void);
39 40
40DECLARE_PER_CPU(unsigned int, cpu_pvr); 41DECLARE_PER_CPU(unsigned int, cpu_pvr);
41 42
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 98c4b29a56f4..c5c24beb8387 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -890,6 +890,15 @@ __secondary_start:
890 mtspr SPRN_SRR1,r4 890 mtspr SPRN_SRR1,r4
891 SYNC 891 SYNC
892 RFI 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#endif /* CONFIG_SMP */ 902#endif /* CONFIG_SMP */
894 903
895#ifdef CONFIG_KVM_BOOK3S_HANDLER 904#ifdef CONFIG_KVM_BOOK3S_HANDLER
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 981360509172..1c9956c43801 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -502,7 +502,7 @@ static struct device_node *cpu_to_l2cache(int cpu)
502} 502}
503 503
504/* Activate a secondary processor. */ 504/* Activate a secondary processor. */
505int __devinit start_secondary(void *unused) 505void __devinit start_secondary(void *unused)
506{ 506{
507 unsigned int cpu = smp_processor_id(); 507 unsigned int cpu = smp_processor_id();
508 struct device_node *l2_cache; 508 struct device_node *l2_cache;
@@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused)
558 local_irq_enable(); 558 local_irq_enable();
559 559
560 cpu_idle(); 560 cpu_idle();
561 return 0; 561
562 BUG();
562} 563}
563 564
564int setup_profiling_timer(unsigned int multiplier) 565int setup_profiling_timer(unsigned int multiplier)
@@ -660,5 +661,9 @@ void cpu_die(void)
660{ 661{
661 if (ppc_md.cpu_die) 662 if (ppc_md.cpu_die)
662 ppc_md.cpu_die(); 663 ppc_md.cpu_die();
664
665 /* If we return, we re-enter start_secondary */
666 start_secondary_resume();
663} 667}
668
664#endif 669#endif
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h
index 75a6f480d931..08672d9136ab 100644
--- a/arch/powerpc/platforms/pseries/offline_states.h
+++ b/arch/powerpc/platforms/pseries/offline_states.h
@@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu)
34#endif 34#endif
35 35
36extern enum cpu_state_vals get_preferred_offline_state(int cpu); 36extern enum cpu_state_vals get_preferred_offline_state(int cpu);
37extern int start_secondary(void);
38extern void start_secondary_resume(void);
39#endif 37#endif