svn commit: r368416 - head/sys/arm64/arm64
Andrew Turner
andrew at FreeBSD.org
Mon Dec 7 17:54:49 UTC 2020
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:
More information about the svn-src-head
mailing list