aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2011-05-10 15:28:44 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-19 00:30:44 -0400
commit7c82733744a74f45e86125f369e876b896765038 (patch)
treefef00d30aeef96b8497b6ac01f7720c13f4f1cde /arch/powerpc/platforms
parentbd9e5eefecb3d69018bb95796298019d309cbec8 (diff)
powerpc/iseries: Cleanup and fix secondary startup
9cb82f2f4692293a27c578c3038518ce4477de72 (Make iSeries spin on __secondary_hold_spinloop, like pSeries) added a load of current_set but this load was repeated later and we don't even have the paca yet. It also checked __secondary_hold_spinloop with a 32 bit compare instead of a 64 bit compare. b6f6b98a4e91fcf31db7de54c3aa86252fc6fb5f (Don't spin on sync instruction at boot time) missed the copy of the startup code in iseries. 1426d5a3bd07589534286375998c0c8c6fdc5260 (Dynamically allocate pacas) doesn't allow for pacas to be less than lppacas and recalculated the paca location from the cpu id in r0 every time through the secondary loop. Various revisions over time made the comments on conditional branches confusing with respect to being a hold loop or forward progress Mostly in-order description of the changes: Replicate the few lines of code saved by the ugly scoped ifdef CONFIG_SMP in the secondary loop between yielding on UP and marking time with the hypervisor on SMP. Always compile the iseries_secondary_yield loop and use it if the cpu id is above nr_cpu_ids. Change all forward progress paths to be forward branches to the next numerical label. Assign a label to all loops. Move all sync instructions from the loops to the forward progress path. Wait to load current_set until paca is set to go. Move the iseries_secondary_smp_loop label to cover the whole spin loop. Add HMT_MEDIUM when we make forward progress. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/iseries/exception.S59
1 files changed, 35 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
index a67984c04954..29c02f36b32f 100644
--- a/arch/powerpc/platforms/iseries/exception.S
+++ b/arch/powerpc/platforms/iseries/exception.S
@@ -61,29 +61,31 @@ system_reset_iSeries:
61/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */ 61/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
62/* In the UP case we'll yield() later, and we will not access the paca anyway */ 62/* In the UP case we'll yield() later, and we will not access the paca anyway */
63#ifdef CONFIG_SMP 63#ifdef CONFIG_SMP
641: 64iSeries_secondary_wait_paca:
65 HMT_LOW 65 HMT_LOW
66 LOAD_REG_ADDR(r23, __secondary_hold_spinloop) 66 LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
67 ld r23,0(r23) 67 ld r23,0(r23)
68 sync
69 LOAD_REG_ADDR(r3,current_set)
70 sldi r28,r24,3 /* get current_set[cpu#] */
71 ldx r3,r3,r28
72 addi r1,r3,THREAD_SIZE
73 subi r1,r1,STACK_FRAME_OVERHEAD
74 68
75 cmpwi 0,r23,0 /* Keep poking the Hypervisor until */ 69 cmpdi 0,r23,0
76 bne 2f /* we're released */ 70 bne 2f /* go on when the master is ready */
77 /* Let the Hypervisor know we are alive */ 71
72 /* Keep poking the Hypervisor until we're released */
78 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ 73 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
79 lis r3,0x8002 74 lis r3,0x8002
80 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ 75 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
81 li r0,-1 /* r0=-1 indicates a Hypervisor call */ 76 li r0,-1 /* r0=-1 indicates a Hypervisor call */
82 sc /* Invoke the hypervisor via a system call */ 77 sc /* Invoke the hypervisor via a system call */
83 b 1b 78 b iSeries_secondary_wait_paca
84#endif
85 79
862: 802:
81 HMT_MEDIUM
82 sync
83
84 LOAD_REG_ADDR(r3, nr_cpu_ids) /* get number of pacas allocated */
85 lwz r3,0(r3) /* nr_cpus= or NR_CPUS can limit */
86 cmpld 0,r24,r3 /* is our cpu number allocated? */
87 bge iSeries_secondary_yield /* no, yield forever */
88
87 /* Load our paca now that it's been allocated */ 89 /* Load our paca now that it's been allocated */
88 LOAD_REG_ADDR(r13, paca) 90 LOAD_REG_ADDR(r13, paca)
89 ld r13,0(r13) 91 ld r13,0(r13)
@@ -94,10 +96,24 @@ system_reset_iSeries:
94 ori r23,r23,MSR_RI 96 ori r23,r23,MSR_RI
95 mtmsrd r23 /* RI on */ 97 mtmsrd r23 /* RI on */
96 98
97 HMT_LOW 99iSeries_secondary_smp_loop:
98#ifdef CONFIG_SMP
99 lbz r23,PACAPROCSTART(r13) /* Test if this processor 100 lbz r23,PACAPROCSTART(r13) /* Test if this processor
100 * should start */ 101 * should start */
102 cmpwi 0,r23,0
103 bne 3f /* go on when we are told */
104
105 HMT_LOW
106 /* Let the Hypervisor know we are alive */
107 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
108 lis r3,0x8002
109 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
110 li r0,-1 /* r0=-1 indicates a Hypervisor call */
111 sc /* Invoke the hypervisor via a system call */
112 mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
113 b iSeries_secondary_smp_loop /* wait for signal to start */
114
1153:
116 HMT_MEDIUM
101 sync 117 sync
102 LOAD_REG_ADDR(r3,current_set) 118 LOAD_REG_ADDR(r3,current_set)
103 sldi r28,r24,3 /* get current_set[cpu#] */ 119 sldi r28,r24,3 /* get current_set[cpu#] */
@@ -105,27 +121,22 @@ system_reset_iSeries:
105 addi r1,r3,THREAD_SIZE 121 addi r1,r3,THREAD_SIZE
106 subi r1,r1,STACK_FRAME_OVERHEAD 122 subi r1,r1,STACK_FRAME_OVERHEAD
107 123
108 cmpwi 0,r23,0
109 beq iSeries_secondary_smp_loop /* Loop until told to go */
110 b __secondary_start /* Loop until told to go */ 124 b __secondary_start /* Loop until told to go */
111iSeries_secondary_smp_loop: 125#endif /* CONFIG_SMP */
112 /* Let the Hypervisor know we are alive */ 126
113 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ 127iSeries_secondary_yield:
114 lis r3,0x8002
115 rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */
116#else /* CONFIG_SMP */
117 /* Yield the processor. This is required for non-SMP kernels 128 /* Yield the processor. This is required for non-SMP kernels
118 which are running on multi-threaded machines. */ 129 which are running on multi-threaded machines. */
130 HMT_LOW
119 lis r3,0x8000 131 lis r3,0x8000
120 rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ 132 rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */
121 addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ 133 addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */
122 li r4,0 /* "yield timed" */ 134 li r4,0 /* "yield timed" */
123 li r5,-1 /* "yield forever" */ 135 li r5,-1 /* "yield forever" */
124#endif /* CONFIG_SMP */
125 li r0,-1 /* r0=-1 indicates a Hypervisor call */ 136 li r0,-1 /* r0=-1 indicates a Hypervisor call */
126 sc /* Invoke the hypervisor via a system call */ 137 sc /* Invoke the hypervisor via a system call */
127 mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */ 138 mfspr r13,SPRN_SPRG_PACA /* Put r13 back ???? */
128 b 2b /* If SMP not configured, secondaries 139 b iSeries_secondary_yield /* If SMP not configured, secondaries
129 * loop forever */ 140 * loop forever */
130 141
131/*** ISeries-LPAR interrupt handlers ***/ 142/*** ISeries-LPAR interrupt handlers ***/