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 <p...@semihalf.com>
  Submitted by:          Wojciech Macek <w...@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);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to