git: d057b7aac8ae - main - arm64: Malloc the cpu_desc array

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Thu, 08 Jun 2023 16:11:17 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=d057b7aac8aedd353f2cb047cb0069f6a4db7a83

commit d057b7aac8aedd353f2cb047cb0069f6a4db7a83
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-06-02 16:12:24 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2023-06-08 16:10:10 +0000

    arm64: Malloc the cpu_desc array
    
    We only need this during boot. Allocate the array before starting CPUs
    to reduce the memory usage.
    
    Reviewed by:    Zach Leaf <zachary.leaf@arm.com>
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D40433
---
 sys/arm64/arm64/identcpu.c   | 43 ++++++++++++++++++++++++++++++++++++++-----
 sys/arm64/arm64/mp_machdep.c |  2 ++
 sys/arm64/include/cpu.h      |  2 ++
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index fb1c4537f216..86b669ea2f56 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/pcpu.h>
 #include <sys/sbuf.h>
 #include <sys/smp.h>
@@ -47,6 +48,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/md_var.h>
 #include <machine/undefined.h>
 
+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 @@ struct cpu_desc {
 	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 @@ update_special_regs(u_int cpu)
 		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 @@ update_special_regs(u_int cpu)
 	}
 }
 
+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 @@ identify_cpu_sysinit(void *dummy __unused)
 
 	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 @@ cpu_features_sysinit(void *dummy __unused)
 
 	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 @@ cpu_features_sysinit(void *dummy __unused)
 
 	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 @@ identify_cpu(u_int cpu)
 	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
index 9dd1182e5721..babeee331be0 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -779,6 +779,8 @@ cpu_mp_start(void)
 	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
index 88a9ac18080b..1ea497756698 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -214,6 +214,8 @@ void	update_special_regs(u_int);
 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))))