Index: sys/arm64/arm64/mp_machdep.c =================================================================== --- sys/arm64/arm64/mp_machdep.c +++ sys/arm64/arm64/mp_machdep.c @@ -124,13 +124,11 @@ struct mtx ap_boot_mtx; struct pcb stoppcbs[MAXCPU]; +uint64_t cpu_mpidrs[MAXCPU]; -/* - * Not all systems boot from the first CPU in the device tree. To work around - * this we need to find which CPU we have booted from so when we later - * enable the secondary CPUs we skip this one. - */ -static int cpu0 = -1; +#ifdef FDT +static u_int fdt_cpuid; +#endif void mpentry(unsigned long cpuid); void init_secondary(uint64_t); @@ -389,33 +387,21 @@ } static bool -start_cpu(u_int id, uint64_t target_cpu) +start_cpu(u_int cpuid, uint64_t target_cpu) { struct pcpu *pcpup; vm_paddr_t pa; - u_int cpuid; int err; /* Check we are able to start this cpu */ - if (id > mp_maxid) + if (cpuid > mp_maxid) return (false); - KASSERT(id < MAXCPU, ("Too many CPUs")); - - /* We are already running on cpu 0 */ - if (id == cpu0) - return (true); + KASSERT(cpuid < MAXCPU, ("Too many CPUs")); + KASSERT(cpu_mpidrs[cpuid] != (target_cpu & CPU_AFF_MASK), + ("Start_cpu() was called on the boot CPU")); - /* - * Rotate the CPU IDs to put the boot CPU as CPU 0. We keep the other - * CPUs ordered as the are likely grouped into clusters so it can be - * useful to keep that property, e.g. for the GICv3 driver to send - * an IPI to all CPUs in the cluster. - */ - cpuid = id; - if (cpuid < cpu0) - cpuid += mp_maxid + 1; - cpuid -= cpu0; + cpu_mpidrs[cpuid] = target_cpu & CPU_AFF_MASK; pcpup = &__pcpu[cpuid]; pcpu_init(pcpup, cpuid, sizeof(struct pcpu)); @@ -435,7 +421,7 @@ */ KASSERT(err == PSCI_MISSING || (mp_quirks & MP_QUIRK_CPULIST) == MP_QUIRK_CPULIST, - ("Failed to start CPU %u (%lx)\n", id, target_cpu)); + ("Failed to start CPU %u (%lx)\n", cpuid, target_cpu)); pcpu_destroy(pcpup); kmem_free((vm_offset_t)dpcpu[cpuid - 1], DPCPU_SIZE); @@ -443,7 +429,7 @@ mp_ncpus--; /* Notify the user that the CPU failed to start */ - printf("Failed to start CPU %u (%lx)\n", id, target_cpu); + printf("Failed to start CPU %u (%lx)\n", cpuid, target_cpu); } else CPU_SET(cpuid, &all_cpus); @@ -463,6 +449,11 @@ intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry; cpuid = arg; id = *cpuid; + + /* Skip boot CPU */ + if (cpu_mpidrs[0] == (intr->ArmMpidr & CPU_AFF_MASK)) + break; + start_cpu(id, intr->ArmMpidr); __pcpu[id].pc_acpi_id = intr->Uid; (*cpuid)++; @@ -489,7 +480,7 @@ return; } - cpuid = 0; + cpuid = 1; acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, madt_handler, &cpuid); @@ -516,16 +507,20 @@ target_cpu |= reg[1]; } - if (!start_cpu(id, target_cpu)) + if (cpu_mpidrs[0] == (target_cpu & CPU_AFF_MASK)) + 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 || OF_getencprop(node, "numa-node-id", &domain, sizeof(domain)) <= 0) domain = 0; - __pcpu[id].pc_domain = domain; + __pcpu[fdt_cpuid].pc_domain = domain; if (domain < MAXMEMDOM) - CPU_SET(id, &cpuset_domain[domain]); + CPU_SET(fdt_cpuid, &cpuset_domain[domain]); return (TRUE); } @@ -537,18 +532,24 @@ { #ifdef FDT phandle_t node; - int i; #endif + int i; mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN); + + /* Initialize MPIDR table with impossible MPIDR. */ + for (i = 0; i < MAXCPU; i++) + cpu_mpidrs[i] = ~0; + + /* CPU 0 is always boot CPU. */ CPU_SET(0, &all_cpus); + cpu_mpidrs[0] = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK; switch(arm64_bus_method) { #ifdef DEV_ACPI case ARM64_BUS_ACPI: mp_quirks = MP_QUIRK_CPULIST; - KASSERT(cpu0 >= 0, ("Current CPU was not found")); cpu_init_acpi(); break; #endif @@ -561,7 +562,7 @@ mp_quirks = fdt_quirks[i].quirks; } } - KASSERT(cpu0 >= 0, ("Current CPU was not found")); + fdt_cpuid = 1; ofw_cpu_early_foreach(cpu_init_fdt, true); break; #endif @@ -582,16 +583,10 @@ { ACPI_MADT_GENERIC_INTERRUPT *intr; u_int *cores = arg; - uint64_t mpidr_reg; switch(entry->Type) { case ACPI_MADT_TYPE_GENERIC_INTERRUPT: intr = (ACPI_MADT_GENERIC_INTERRUPT *)entry; - if (cpu0 < 0) { - mpidr_reg = READ_SPECIALREG(mpidr_el1); - if ((mpidr_reg & 0xff00fffffful) == intr->ArmMpidr) - cpu0 = *cores; - } (*cores)++; break; default: @@ -616,7 +611,7 @@ return (0); } - cores = 0; + cores = 1; acpi_walk_subtables(madt + 1, (char *)madt + madt->Header.Length, cpu_count_acpi_handler, &cores); @@ -626,29 +621,6 @@ } #endif -#ifdef FDT -static boolean_t -cpu_find_cpu0_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg) -{ - uint64_t mpidr_fdt, mpidr_reg; - - if (cpu0 < 0) { - mpidr_fdt = reg[0]; - if (addr_size == 2) { - mpidr_fdt <<= 32; - mpidr_fdt |= reg[1]; - } - - mpidr_reg = READ_SPECIALREG(mpidr_el1); - - if ((mpidr_reg & 0xff00fffffful) == mpidr_fdt) - cpu0 = id; - } - - return (TRUE); -} -#endif - void cpu_mp_setmaxid(void) { @@ -673,7 +645,7 @@ #endif #ifdef FDT case ARM64_BUS_FDT: - cores = ofw_cpu_early_foreach(cpu_find_cpu0_fdt, false); + cores = ofw_cpu_early_foreach(NULL, false); if (cores > 0) { cores = MIN(cores, MAXCPU); if (bootverbose) Index: sys/arm64/include/smp.h =================================================================== --- sys/arm64/include/smp.h +++ sys/arm64/include/smp.h @@ -51,5 +51,6 @@ /* global data in mp_machdep.c */ extern struct pcb stoppcbs[]; +extern uint64_t cpu_mpidrs[]; #endif /* !_MACHINE_SMP_H_ */