diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,8 @@ #include #include +static MALLOC_DEFINE(M_IDENTCPU, "CPU ID", "arm64 CPU identification memory"); + struct cpu_desc; static void print_cpu_midr(struct sbuf *sb, u_int cpu); @@ -150,10 +153,22 @@ bool have_sve; }; -static struct cpu_desc cpu_desc[MAXCPU]; +static struct cpu_desc cpu_desc0; +static struct cpu_desc *cpu_desc; static struct cpu_desc kern_cpu_desc; static struct cpu_desc user_cpu_desc; +static struct cpu_desc * +get_cpu_desc(u_int cpu) +{ + /* The cpu_desc for CPU 0 is used before the allocator is ready. */ + if (cpu == 0) + return (&cpu_desc0); + + MPASS(cpu_desc != NULL); + return (&cpu_desc[cpu - 1]); +} + struct cpu_parts { u_int part_id; const char *part_name; @@ -1803,7 +1818,7 @@ user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8; } - desc = &cpu_desc[cpu]; + desc = get_cpu_desc(cpu); for (i = 0; i < nitems(user_regs); i++) { value = CPU_DESC_FIELD(*desc, i); if (cpu == 0) { @@ -1839,6 +1854,22 @@ } } +void +cpu_desc_init(void) +{ + if (mp_ncpus == 1) + return; + + /* + * Allocate memory for the non-boot CPUs to store their registers. + * As this is indexed by CPU ID we need to allocate space for CPUs + * 1 to mp_maxid. Because of this mp_maxid is already the correct + * number of elements. + */ + cpu_desc = mallocarray(mp_maxid, sizeof(*cpu_desc), M_IDENTCPU, + M_ZERO | M_WAITOK); +} + /* HWCAP */ bool __read_frequently lse_supported = false; @@ -1896,7 +1927,7 @@ prev_desc = NULL; CPU_FOREACH(cpu) { - desc = &cpu_desc[cpu]; + desc = get_cpu_desc(cpu); if (cpu != 0) { check_cpu_regs(cpu, desc, prev_desc); update_special_regs(cpu); @@ -1950,7 +1981,7 @@ prev_desc = NULL; CPU_FOREACH(cpu) { - desc = &cpu_desc[cpu]; + desc = get_cpu_desc(cpu); print_cpu_features(cpu, desc, prev_desc); prev_desc = desc; } @@ -1961,6 +1992,8 @@ sbuf_finish(&sb); sbuf_delete(&sb); + + free(cpu_desc, M_IDENTCPU); } /* Log features before APs are released and start printing to the dmesg. */ SYSINIT(cpu_features, SI_SUB_SMP - 1, SI_ORDER_ANY, cpu_features_sysinit, NULL); @@ -2390,7 +2423,7 @@ struct cpu_desc *desc; uint64_t clidr; - desc = &cpu_desc[cpu]; + desc = get_cpu_desc(cpu); /* Save affinity for current CPU */ desc->mpidr = get_mpidr(); CPU_AFFINITY(cpu) = desc->mpidr & CPU_AFF_MASK; diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -779,6 +779,8 @@ mpidr = READ_SPECIALREG(mpidr_el1) & CPU_AFF_MASK; cpuid_to_pcpu[0]->pc_mpidr = mpidr; + cpu_desc_init(); + switch(arm64_bus_method) { #ifdef DEV_ACPI case ARM64_BUS_ACPI: diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h --- a/sys/arm64/include/cpu.h +++ b/sys/arm64/include/cpu.h @@ -214,6 +214,8 @@ bool extract_user_id_field(u_int, u_int, uint8_t *); bool get_kernel_reg(u_int, uint64_t *); +void cpu_desc_init(void); + #define CPU_AFFINITY(cpu) __cpu_affinity[(cpu)] #define CPU_CURRENT_SOCKET \ (CPU_AFF2(CPU_AFFINITY(PCPU_GET(cpuid))))