git: 3c4bc06f9b91 - main - arm64: Move DBM errata to the cpu feat framework

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Fri, 24 Jan 2025 12:11:51 UTC
The branch main has been updated by andrew:

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

commit 3c4bc06f9b91b719c2797f1cbd0b541ae4632332
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2025-01-24 11:42:44 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-01-24 12:09:28 +0000

    arm64: Move DBM errata to the cpu feat framework
    
    Move to the new cpu feature framework for enabling DBM and disabling
    when there are errata affecting it.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D47815
---
 sys/arm64/arm64/mp_machdep.c |  1 -
 sys/arm64/arm64/pmap.c       | 87 +++++++++++++++++++++++++++++++-------------
 sys/arm64/include/pmap.h     |  1 -
 3 files changed, 61 insertions(+), 28 deletions(-)

diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index fe04e39edecc..987ff9ac1ceb 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -220,7 +220,6 @@ init_secondary(uint64_t cpu)
 	pcpup = cpuid_to_pcpu[cpu];
 	pcpup->pc_midr = get_midr();
 	identify_cpu(cpu);
-	pmap_cpu_init();
 
 	/* Ensure the stores in identify_cpu have completed */
 	atomic_thread_fence_acq_rel();
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 5c1e5bb63e4d..5a3dbbf00203 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -146,6 +146,7 @@
 #include <vm/uma.h>
 
 #include <machine/asan.h>
+#include <machine/cpu_feat.h>
 #include <machine/machdep.h>
 #include <machine/md_var.h>
 #include <machine/pcb.h>
@@ -1309,8 +1310,6 @@ pmap_bootstrap(vm_size_t kernlen)
 	vm_paddr_t start_pa, pa;
 	uint64_t tcr;
 
-	pmap_cpu_init();
-
 	tcr = READ_SPECIALREG(tcr_el1);
 
 	/* Verify that the ASID is set through TTBR0. */
@@ -1625,39 +1624,75 @@ pmap_init_pv_table(void)
 	}
 }
 
-void
-pmap_cpu_init(void)
+static bool
+pmap_dbm_check(const struct cpu_feat *feat __unused, u_int midr __unused)
 {
-	uint64_t id_aa64mmfr1, tcr;
-	bool enable_dbm;
-
-	enable_dbm = false;
+	uint64_t id_aa64mmfr1;
 
-	/* Enable HAFDBS if supported */
 	id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
-	if (ID_AA64MMFR1_HAFDBS_VAL(id_aa64mmfr1) >= ID_AA64MMFR1_HAFDBS_AF_DBS)
-		enable_dbm = true;
+	return (ID_AA64MMFR1_HAFDBS_VAL(id_aa64mmfr1) >=
+	    ID_AA64MMFR1_HAFDBS_AF_DBS);
+}
+
+static bool
+pmap_dbm_has_errata(const struct cpu_feat *feat __unused, u_int midr,
+    u_int **errata_list, u_int *errata_count)
+{
 	/* Disable on Cortex-A55 for erratum 1024718 - all revisions */
 	if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK, CPU_IMPL_ARM,
-	    CPU_PART_CORTEX_A55, 0, 0))
-		enable_dbm = false;
+	    CPU_PART_CORTEX_A55, 0, 0)) {
+		static u_int errata_id = 1024718;
+
+		*errata_list = &errata_id;
+		*errata_count = 1;
+		return (true);
+	}
+
 	/* Disable on Cortex-A510 for erratum 2051678 - r0p0 to r0p2 */
-	else if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK | CPU_VAR_MASK,
-	    CPU_IMPL_ARM, CPU_PART_CORTEX_A510, 0, 0))
-		if (CPU_REV(PCPU_GET(midr)) < 3)
-			enable_dbm = false;
-	if (enable_dbm) {
-		tcr = READ_SPECIALREG(tcr_el1) | TCR_HD;
-		WRITE_SPECIALREG(tcr_el1, tcr);
-		isb();
-		/* Flush the local TLB for the TCR_HD flag change */
-		dsb(nshst);
-		__asm __volatile("tlbi vmalle1");
-		dsb(nsh);
-		isb();
+	if (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK | CPU_VAR_MASK,
+	    CPU_IMPL_ARM, CPU_PART_CORTEX_A510, 0, 0)) {
+		if (CPU_REV(PCPU_GET(midr)) < 3) {
+			static u_int errata_id = 2051678;
+
+			*errata_list = &errata_id;
+			*errata_count = 1;
+			return (true);
+		}
 	}
+
+	return (false);
+}
+
+static void
+pmap_dbm_enable(const struct cpu_feat *feat __unused,
+    cpu_feat_errata errata_status, u_int *errata_list __unused,
+    u_int errata_count)
+{
+	uint64_t tcr;
+
+	/* Skip if there is an erratum affecting DBM */
+	if (errata_status != ERRATA_NONE)
+		return;
+
+	tcr = READ_SPECIALREG(tcr_el1) | TCR_HD;
+	WRITE_SPECIALREG(tcr_el1, tcr);
+	isb();
+	/* Flush the local TLB for the TCR_HD flag change */
+	dsb(nshst);
+	__asm __volatile("tlbi vmalle1");
+	dsb(nsh);
+	isb();
 }
 
+static struct cpu_feat feat_dbm = {
+	.feat_name		= "FEAT_HAFDBS (DBM)",
+	.feat_check		= pmap_dbm_check,
+	.feat_has_errata	= pmap_dbm_has_errata,
+	.feat_enable		= pmap_dbm_enable,
+	.feat_flags		= CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU,
+};
+DATA_SET(cpu_feat_set, feat_dbm);
+
 /*
  *	Initialize the pmap module.
  *
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index 75de9e342c72..2503f1df8404 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -142,7 +142,6 @@ extern pt_entry_t pmap_sh_attr;
 
 void	pmap_activate_vm(pmap_t);
 void	pmap_bootstrap(vm_size_t);
-void	pmap_cpu_init(void);
 int	pmap_change_attr(vm_offset_t va, vm_size_t size, int mode);
 int	pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot);
 void	pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode);