svn commit: r328533 - in head/sys/powerpc: powernv powerpc

Wojciech Macek wma at FreeBSD.org
Mon Jan 29 08:10:04 UTC 2018


Author: wma
Date: Mon Jan 29 08:10:03 2018
New Revision: 328533
URL: https://svnweb.freebsd.org/changeset/base/328533

Log:
  PPC64: cleanup APs startup routines
  
  Cleaning up AP startup routines. This is a mix of changes
  required to make PowerNV running and to modify the code
  to be more robust. Previously, some races were seen if more
  than 90CPUs were online.
  
  Authored by:           Patryk Duda <pdk at semihalf.com>
  Submitted by:          Wojciech Macek <wma at semihalf.com>
  Obtained from:         Semihalf
  Sponsored by:          IBM, QCM Technologies
  Differential revision: https://reviews.freebsd.org/D14026

Modified:
  head/sys/powerpc/powernv/platform_powernv.c
  head/sys/powerpc/powerpc/mp_machdep.c

Modified: head/sys/powerpc/powernv/platform_powernv.c
==============================================================================
--- head/sys/powerpc/powernv/platform_powernv.c	Mon Jan 29 05:29:28 2018	(r328532)
+++ head/sys/powerpc/powernv/platform_powernv.c	Mon Jan 29 08:10:03 2018	(r328533)
@@ -425,9 +425,21 @@ powernv_reset(platform_t platform)
 static void
 powernv_smp_ap_init(platform_t platform)
 {
+	register_t msr;
 
+	/* LPID must not be altered when PSL_DR or PSL_IR is set */
+	msr = mfmsr();
+	mtmsr(msr & ~(PSL_DR | PSL_IR));
+
+	isync();
 	/* Direct interrupts to SRR instead of HSRR and reset LPCR otherwise */
+	mtspr(SPR_LPID, 0);
+	isync();
+
+	mtmsr(msr);
+
 	mtspr(SPR_LPCR, LPCR_LPES);
+	isync();
 }
 
 static void

Modified: head/sys/powerpc/powerpc/mp_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/mp_machdep.c	Mon Jan 29 05:29:28 2018	(r328532)
+++ head/sys/powerpc/powerpc/mp_machdep.c	Mon Jan 29 08:10:03 2018	(r328533)
@@ -94,6 +94,9 @@ machdep_ap_bootstrap(void)
 	printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid));
 	mtx_unlock_spin(&ap_boot_mtx);
 
+	while(smp_started == 0)
+		;
+
 	/* Start per-CPU event timers. */
 	cpu_initclocks_ap();
 
@@ -197,6 +200,7 @@ cpu_mp_unleash(void *dummy)
 {
 	struct pcpu *pc;
 	int cpus, timeout;
+	int ret;
 
 	if (mp_ncpus <= 1)
 		return;
@@ -215,12 +219,12 @@ cpu_mp_unleash(void *dummy)
 				printf("Waking up CPU %d (dev=%x)\n",
 				    pc->pc_cpuid, (int)pc->pc_hwref);
 
-			platform_smp_start_cpu(pc);
-			
-			timeout = 2000;	/* wait 2sec for the AP */
-			while (!pc->pc_awake && --timeout > 0)
-				DELAY(1000);
-
+			ret = platform_smp_start_cpu(pc);
+			if (ret == 0) {
+				timeout = 2000;	/* wait 2sec for the AP */
+				while (!pc->pc_awake && --timeout > 0)
+					DELAY(1000);
+			}
 		} else {
 			pc->pc_awake = 1;
 		}
@@ -253,11 +257,12 @@ cpu_mp_unleash(void *dummy)
 		    mp_ncpus, cpus, smp_cpus);
 	}
 
+	if (smp_cpus > 1)
+		atomic_store_rel_int(&smp_started, 1);
+
 	/* Let the APs get into the scheduler */
 	DELAY(10000);
 
-	/* XXX Atomic set operation? */
-	smp_started = 1;
 }
 
 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);


More information about the svn-src-head mailing list