Author: andrew
Date: Mon Dec  7 17:54:49 2020
New Revision: 368416
URL: https://svnweb.freebsd.org/changeset/base/368416

Log:
  Ensure the boot CPU is CPU 0 on arm64
  
  We assume the boot CPU is always CPU 0 on arm64. To allow for this reserve
  cpuid 0 for the boot CPU in the ACPI and FDT cases but otherwise start the
  CPU as normal. We then check for the boot CPU in start_cpu and return as if
  it was started.
  
  While here extract the FDT CPU init code into a new function to simplify
  cpu_mp_start and return FALSE from start_cpu when the CPU fails to start.
  
  Reviewed by:  mmel
  Sponsored by: Innovate UK
  Differential Revision:        https://reviews.freebsd.org/D27497

Modified:
  head/sys/arm64/arm64/mp_machdep.c

Modified: head/sys/arm64/arm64/mp_machdep.c
==============================================================================
--- head/sys/arm64/arm64/mp_machdep.c   Mon Dec  7 16:08:31 2020        
(r368415)
+++ head/sys/arm64/arm64/mp_machdep.c   Mon Dec  7 17:54:49 2020        
(r368416)
@@ -148,6 +148,13 @@ static volatile int aps_ready;
 /* Temporary variables for init_secondary()  */
 void *dpcpu[MAXCPU - 1];
 
+static bool
+is_boot_cpu(uint64_t target_cpu)
+{
+
+       return (__pcpu[0].pc_mpidr == (target_cpu & CPU_AFF_MASK));
+}
+
 static void
 release_aps(void *dummy __unused)
 {
@@ -428,6 +435,10 @@ cpu_mp_probe(void)
        return (1);
 }
 
+/*
+ * Starts a given CPU. If the CPU is already running, i.e. it is the boot CPU,
+ * do nothing. Returns true if the CPU is present and running.
+ */
 static bool
 start_cpu(u_int cpuid, uint64_t target_cpu)
 {
@@ -439,9 +450,11 @@ start_cpu(u_int cpuid, uint64_t target_cpu)
        if (cpuid > mp_maxid)
                return (false);
 
+       /* Skip boot CPU */
+       if (is_boot_cpu(target_cpu))
+               return (true);
+
        KASSERT(cpuid < MAXCPU, ("Too many CPUs"));
-       KASSERT(__pcpu[0].pc_mpidr != (target_cpu & CPU_AFF_MASK),
-           ("Start_cpu() was called on the boot CPU"));
 
        pcpup = &__pcpu[cpuid];
        pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
@@ -475,14 +488,14 @@ start_cpu(u_int cpuid, uint64_t target_cpu)
                kmem_free((vm_offset_t)bootstacks[cpuid], PAGE_SIZE);
                bootstacks[cpuid] = NULL;
                mp_ncpus--;
-
-       } else {
-               /* Wait for the AP to switch to its boot stack. */
-               while (atomic_load_int(&aps_started) < naps + 1)
-                       cpu_spinwait();
-               CPU_SET(cpuid, &all_cpus);
+               return (false);
        }
 
+       /* Wait for the AP to switch to its boot stack. */
+       while (atomic_load_int(&aps_started) < naps + 1)
+               cpu_spinwait();
+       CPU_SET(cpuid, &all_cpus);
+
        return (true);
 }
 
@@ -498,17 +511,22 @@ madt_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
        case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
                intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
                cpuid = arg;
-               id = *cpuid;
 
-               /* Skip the boot CPU, but save its ACPI id. */
-               if (__pcpu[0].pc_mpidr == (intr->ArmMpidr & CPU_AFF_MASK)) {
-                       __pcpu[0].pc_acpi_id = intr->Uid;
-                       break;
+               if (is_boot_cpu(intr->ArmMpidr))
+                       id = 0;
+               else
+                       id = *cpuid;
+
+               if (start_cpu(id, intr->ArmMpidr)) {
+                       __pcpu[id].pc_acpi_id = intr->Uid;
+                       /*
+                        * Don't increment for the boot CPU, its CPU ID is
+                        * reserved.
+                        */
+                       if (!is_boot_cpu(intr->ArmMpidr))
+                               (*cpuid)++;
                }
 
-               start_cpu(id, intr->ArmMpidr);
-               __pcpu[id].pc_acpi_id = intr->Uid;
-               (*cpuid)++;
                break;
        default:
                break;
@@ -546,10 +564,11 @@ cpu_init_acpi(void)
 
 #ifdef FDT
 static boolean_t
-cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
 {
        uint64_t target_cpu;
        int domain;
+       int cpuid;
 
        target_cpu = reg[0];
        if (addr_size == 2) {
@@ -557,35 +576,51 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size
                target_cpu |= reg[1];
        }
 
-       /* Skip boot CPU */
-       if (__pcpu[0].pc_mpidr == (target_cpu & CPU_AFF_MASK))
-               return (TRUE);
+       if (is_boot_cpu(target_cpu))
+               cpuid = 0;
+       else
+               cpuid = fdt_cpuid;
 
-       if (!start_cpu(fdt_cpuid, target_cpu))
+       if (!start_cpu(cpuid, target_cpu))
                return (FALSE);
-       fdt_cpuid++;
 
+       /*
+        * Don't increment for the boot CPU, its CPU ID is reserved.
+        */
+       if (!is_boot_cpu(target_cpu))
+               fdt_cpuid++;
+
        /* Try to read the numa node of this cpu */
        if (vm_ndomains == 1 ||
            OF_getencprop(node, "numa-node-id", &domain, sizeof(domain)) <= 0)
                domain = 0;
-       __pcpu[fdt_cpuid].pc_domain = domain;
+       __pcpu[cpuid].pc_domain = domain;
        if (domain < MAXMEMDOM)
-               CPU_SET(fdt_cpuid, &cpuset_domain[domain]);
-
+               CPU_SET(cpuid, &cpuset_domain[domain]);
        return (TRUE);
 }
+static void
+cpu_init_fdt(void)
+{
+       phandle_t node;
+       int i;
+
+       node = OF_peer(0);
+       for (i = 0; fdt_quirks[i].compat != NULL; i++) {
+               if (ofw_bus_node_is_compatible(node,
+                   fdt_quirks[i].compat) != 0) {
+                       mp_quirks = fdt_quirks[i].quirks;
+               }
+       }
+       fdt_cpuid = 1;
+       ofw_cpu_early_foreach(start_cpu_fdt, true);
+}
 #endif
 
 /* Initialize and fire up non-boot processors */
 void
 cpu_mp_start(void)
 {
-#ifdef FDT
-       phandle_t node;
-#endif
-       int i;
-
        mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
 
        /* CPU 0 is always boot CPU. */
@@ -601,15 +636,7 @@ cpu_mp_start(void)
 #endif
 #ifdef FDT
        case ARM64_BUS_FDT:
-               node = OF_peer(0);
-               for (i = 0; fdt_quirks[i].compat != NULL; i++) {
-                       if (ofw_bus_node_is_compatible(node,
-                           fdt_quirks[i].compat) != 0) {
-                               mp_quirks = fdt_quirks[i].quirks;
-                       }
-               }
-               fdt_cpuid = 1;
-               ofw_cpu_early_foreach(cpu_init_fdt, true);
+               cpu_init_fdt();
                break;
 #endif
        default:
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to