aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-03-15 23:54:35 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-04-19 21:03:24 -0400
commit9d07bc841c9779b4d7902e417f4e509996ce805d (patch)
tree7a381096d3da7497aac58c4ec18c74299ee47fb4
parentad0693ee722b93b63a89c845e99513f242e43aa6 (diff)
powerpc: Properly handshake CPUs going out of boot spin loop
We need to wait a bit for them to have done their CPU setup or we might end up with translation and EE on with different LPCR values between threads Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/include/asm/smp.h1
-rw-r--r--arch/powerpc/kernel/head_64.S18
-rw-r--r--arch/powerpc/kernel/prom.c27
-rw-r--r--arch/powerpc/kernel/setup_32.c1
-rw-r--r--arch/powerpc/kernel/setup_64.c13
5 files changed, 37 insertions, 23 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index a902a0d3ae0d..bb4c033a8fb0 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -29,6 +29,7 @@
29#include <asm/percpu.h> 29#include <asm/percpu.h>
30 30
31extern int boot_cpuid; 31extern int boot_cpuid;
32extern int boot_cpu_count;
32 33
33extern void cpu_die(void); 34extern void cpu_die(void);
34 35
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 95944278380c..0700e1135c91 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -242,23 +242,31 @@ generic_secondary_common_init:
242 ld r23,0(r23) 242 ld r23,0(r23)
243 ld r23,CPU_SPEC_RESTORE(r23) 243 ld r23,CPU_SPEC_RESTORE(r23)
244 cmpdi 0,r23,0 244 cmpdi 0,r23,0
245 beq 4f 245 beq 3f
246 ld r23,0(r23) 246 ld r23,0(r23)
247 mtctr r23 247 mtctr r23
248 bctrl 248 bctrl
249 249
2503: HMT_LOW 2503: LOAD_REG_ADDR(r3, boot_cpu_count) /* Decrement boot_cpu_count */
251 lwarx r4,0,r3
252 subi r4,r4,1
253 stwcx. r4,0,r3
254 bne 3b
255 isync
256
2574: HMT_LOW
251 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ 258 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
252 /* start. */ 259 /* start. */
253#ifndef CONFIG_SMP 260#ifndef CONFIG_SMP
254 b 3b /* Never go on non-SMP */ 261 b 4b /* Never go on non-SMP */
255#else 262#else
256 cmpwi 0,r23,0 263 cmpwi 0,r23,0
257 beq 3b /* Loop until told to go */ 264 beq 4b /* Loop until told to go */
258 265
259 sync /* order paca.run and cur_cpu_spec */ 266 sync /* order paca.run and cur_cpu_spec */
267 isync /* In case code patching happened */
260 268
2614: /* Create a temp kernel stack for use before relocation is on. */ 269 /* Create a temp kernel stack for use before relocation is on. */
262 ld r1,PACAEMERGSP(r13) 270 ld r1,PACAEMERGSP(r13)
263 subi r1,r1,STACK_FRAME_OVERHEAD 271 subi r1,r1,STACK_FRAME_OVERHEAD
264 272
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index e74fa12afc82..c391dc4c8bad 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -268,13 +268,12 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
268 const char *uname, int depth, 268 const char *uname, int depth,
269 void *data) 269 void *data)
270{ 270{
271 static int logical_cpuid = 0;
272 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 271 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
273 const u32 *prop; 272 const u32 *prop;
274 const u32 *intserv; 273 const u32 *intserv;
275 int i, nthreads; 274 int i, nthreads;
276 unsigned long len; 275 unsigned long len;
277 int found = 0; 276 int found = -1;
278 277
279 /* We are scanning "cpu" nodes only */ 278 /* We are scanning "cpu" nodes only */
280 if (type == NULL || strcmp(type, "cpu") != 0) 279 if (type == NULL || strcmp(type, "cpu") != 0)
@@ -299,11 +298,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
299 * booted proc. 298 * booted proc.
300 */ 299 */
301 if (initial_boot_params && initial_boot_params->version >= 2) { 300 if (initial_boot_params && initial_boot_params->version >= 2) {
302 if (intserv[i] == 301 if (intserv[i] == initial_boot_params->boot_cpuid_phys)
303 initial_boot_params->boot_cpuid_phys) { 302 found = boot_cpu_count;
304 found = 1;
305 break;
306 }
307 } else { 303 } else {
308 /* 304 /*
309 * Check if it's the boot-cpu, set it's hw index now, 305 * Check if it's the boot-cpu, set it's hw index now,
@@ -311,23 +307,20 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
311 * off secondary threads. 307 * off secondary threads.
312 */ 308 */
313 if (of_get_flat_dt_prop(node, 309 if (of_get_flat_dt_prop(node,
314 "linux,boot-cpu", NULL) != NULL) { 310 "linux,boot-cpu", NULL) != NULL)
315 found = 1; 311 found = boot_cpu_count;
316 break;
317 }
318 } 312 }
319
320#ifdef CONFIG_SMP 313#ifdef CONFIG_SMP
321 /* logical cpu id is always 0 on UP kernels */ 314 /* logical cpu id is always 0 on UP kernels */
322 logical_cpuid++; 315 boot_cpu_count++;
323#endif 316#endif
324 } 317 }
325 318
326 if (found) { 319 if (found >= 0) {
327 DBG("boot cpu: logical %d physical %d\n", logical_cpuid, 320 DBG("boot cpu: logical %d physical %d\n", found,
328 intserv[i]); 321 intserv[i]);
329 boot_cpuid = logical_cpuid; 322 boot_cpuid = found;
330 set_hard_smp_processor_id(boot_cpuid, intserv[i]); 323 set_hard_smp_processor_id(found, intserv[i]);
331 324
332 /* 325 /*
333 * PAPR defines "logical" PVR values for cpus that 326 * PAPR defines "logical" PVR values for cpus that
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 1d2fbc905303..620d792b52e4 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -48,6 +48,7 @@ extern void bootx_init(unsigned long r4, unsigned long phys);
48 48
49int boot_cpuid = -1; 49int boot_cpuid = -1;
50EXPORT_SYMBOL_GPL(boot_cpuid); 50EXPORT_SYMBOL_GPL(boot_cpuid);
51int __initdata boot_cpu_count;
51int boot_cpuid_phys; 52int boot_cpuid_phys;
52 53
53int smp_hw_index[NR_CPUS]; 54int smp_hw_index[NR_CPUS];
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 5a0401fcaebd..91a5cc5f0d02 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -72,6 +72,7 @@
72#endif 72#endif
73 73
74int boot_cpuid = 0; 74int boot_cpuid = 0;
75int __initdata boot_cpu_count;
75u64 ppc64_pft_size; 76u64 ppc64_pft_size;
76 77
77/* Pick defaults since we might want to patch instructions 78/* Pick defaults since we might want to patch instructions
@@ -233,6 +234,7 @@ void early_setup_secondary(void)
233void smp_release_cpus(void) 234void smp_release_cpus(void)
234{ 235{
235 unsigned long *ptr; 236 unsigned long *ptr;
237 int i;
236 238
237 DBG(" -> smp_release_cpus()\n"); 239 DBG(" -> smp_release_cpus()\n");
238 240
@@ -245,7 +247,16 @@ void smp_release_cpus(void)
245 ptr = (unsigned long *)((unsigned long)&__secondary_hold_spinloop 247 ptr = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
246 - PHYSICAL_START); 248 - PHYSICAL_START);
247 *ptr = __pa(generic_secondary_smp_init); 249 *ptr = __pa(generic_secondary_smp_init);
248 mb(); 250
251 /* And wait a bit for them to catch up */
252 for (i = 0; i < 100000; i++) {
253 mb();
254 HMT_low();
255 if (boot_cpu_count == 0)
256 break;
257 udelay(1);
258 }
259 DBG("boot_cpu_count = %d\n", boot_cpu_count);
249 260
250 DBG(" <- smp_release_cpus()\n"); 261 DBG(" <- smp_release_cpus()\n");
251} 262}