Page MenuHomeFreeBSD

D27497.id80404.diff
No OneTemporary

D27497.id80404.diff

Index: sys/arm64/arm64/mp_machdep.c
===================================================================
--- sys/arm64/arm64/mp_machdep.c
+++ sys/arm64/arm64/mp_machdep.c
@@ -148,6 +148,13 @@
/* 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)
{
@@ -430,6 +437,10 @@
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)
{
@@ -441,9 +452,11 @@
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));
@@ -477,14 +490,14 @@
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);
}
@@ -502,21 +515,38 @@
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;
+ KASSERT(is_boot_cpu(intr->ArmMpidr) || id != 0,
+ ("%s: Trying to start a non-boot CPU as CPU 0", __func__));
+
+ /* Only start CPU 0 as CPU 0 */
+ if (is_boot_cpu(intr->ArmMpidr) && id != 0)
break;
+
+ /* Start all non-boot CPUs */
+ if (start_cpu(id, intr->ArmMpidr)) {
+ __pcpu[id].pc_acpi_id = intr->Uid;
+ (*cpuid)++;
}
- start_cpu(id, intr->ArmMpidr);
- __pcpu[id].pc_acpi_id = intr->Uid;
- (*cpuid)++;
break;
default:
break;
}
}
+static void
+madt_cpu0_handler(ACPI_SUBTABLE_HEADER *entry, void *arg)
+{
+ ACPI_MADT_GENERIC_INTERRUPT *intr;
+
+ if (entry->Type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+ intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry;
+ if (is_boot_cpu(intr->ArmMpidr)) {
+ madt_handler(entry, arg);
+ }
+ }
+}
+
static void
cpu_init_acpi(void)
{
@@ -533,8 +563,14 @@
printf("Unable to map the MADT, not starting APs\n");
return;
}
- /* Boot CPU is always 0 */
- cpuid = 1;
+ /* Ensure the boot CPU is started as CPU 0 */
+ cpuid = 0;
+ acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
+ madt_cpu0_handler, &cpuid);
+
+ /* Start the non-boot CPUs */
+ KASSERT(cpuid == 1, ("%s: Invalid cpuid after registering CPU 0: %d",
+ __func__, cpuid));
acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length,
madt_handler, &cpuid);
@@ -547,11 +583,10 @@
#endif
#ifdef FDT
-static boolean_t
-cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+static uint64_t
+get_fdt_target_cpu(u_int addr_size, pcell_t *reg)
{
uint64_t target_cpu;
- int domain;
target_cpu = reg[0];
if (addr_size == 2) {
@@ -559,13 +594,26 @@
target_cpu |= reg[1];
}
- /* Skip boot CPU */
- if (__pcpu[0].pc_mpidr == (target_cpu & CPU_AFF_MASK))
+ return (target_cpu);
+}
+
+static boolean_t
+start_cpu_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+{
+ uint64_t target_cpu;
+ int domain;
+
+ target_cpu = get_fdt_target_cpu(addr_size, reg);
+
+ KASSERT(is_boot_cpu(target_cpu) || fdt_cpuid != 0,
+ ("%s: Trying to start a non-boot CPU as CPU 0", __func__));
+
+ /* Only start CPU 0 as CPU 0 */
+ if (is_boot_cpu(target_cpu) && fdt_cpuid != 0)
return (TRUE);
if (!start_cpu(fdt_cpuid, target_cpu))
return (FALSE);
- fdt_cpuid++;
/* Try to read the numa node of this cpu */
if (vm_ndomains == 1 ||
@@ -574,20 +622,56 @@
__pcpu[fdt_cpuid].pc_domain = domain;
if (domain < MAXMEMDOM)
CPU_SET(fdt_cpuid, &cpuset_domain[domain]);
+ fdt_cpuid++;
return (TRUE);
}
+
+/*
+ * Find CPU 0 and runs any common startup code, e.g. ginf the NUMA ID.
+ */
+static boolean_t
+register_cpu0_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
+{
+ boolean_t ret;
+
+ if (!is_boot_cpu(get_fdt_target_cpu(addr_size, reg)))
+ return (FALSE);
+
+ ret = start_cpu_fdt(id, node, addr_size, reg);
+ KASSERT(ret == TRUE, ("%s: Registration failed for the boot CPU",
+ __func__));
+
+ return (ret);
+}
+
+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;
+ }
+ }
+ /* Ensure the boot CPU is started as CPU 0 */
+ ofw_cpu_early_foreach(register_cpu0_fdt, true);
+ /* Start the non-boot CPUs */
+ KASSERT(fdt_cpuid == 1,
+ ("%s: Invalid cpuid after registering CPU 0: %d", __func__,
+ fdt_cpuid));
+ 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. */
@@ -603,15 +687,7 @@
#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:

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 20, 11:31 AM (22 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36990848
Default Alt Text
D27497.id80404.diff (5 KB)

Event Timeline