git: c553f62a3007 - stable/13 - Add arm64 CnP support

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 19 Jul 2022 07:37:17 UTC
The branch stable/13 has been updated by andrew:

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

commit c553f62a300735ceaf1c3ca6a9a012e78a69e662
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2022-05-25 09:55:40 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2022-07-19 07:03:30 +0000

    Add arm64 CnP support
    
    Set the Common not Private bit in the ttbr registers when supported on
    arm64. This tells the hardware it can share the translation table
    entries on multiple CPUs.
    
    Reviewed by:    alc, kib
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 9e0716f4610158936c0b9cec1a9930c4ebe924fb)
---
 sys/arm64/arm64/pmap.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 0c6f3630c42d..a8615b0a3902 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -6845,6 +6845,8 @@ out:
 	mtx_unlock_spin(&set->asid_set_mutex);
 }
 
+static uint64_t __read_mostly ttbr_flags;
+
 /*
  * Compute the value that should be stored in ttbr0 to activate the specified
  * pmap.  This value may change from time to time.
@@ -6852,10 +6854,70 @@ out:
 uint64_t
 pmap_to_ttbr0(pmap_t pmap)
 {
+	uint64_t ttbr;
+
+	ttbr = pmap->pm_ttbr;
+	ttbr |= ASID_TO_OPERAND(COOKIE_TO_ASID(pmap->pm_cookie));
+	ttbr |= ttbr_flags;
+
+	return (ttbr);
+}
+
+static void
+pmap_set_cnp(void *arg)
+{
+	uint64_t ttbr0, ttbr1;
+	u_int cpuid;
+
+	cpuid = *(u_int *)arg;
+	if (cpuid == curcpu) {
+		/*
+		 * Set the flags while all CPUs are handling the
+		 * smp_rendezvous so will not call pmap_to_ttbr0. Any calls
+		 * to pmap_to_ttbr0 after this will have the CnP flag set.
+		 * The dsb after invalidating the TLB will act as a barrier
+		 * to ensure all CPUs can observe this change.
+		 */
+		ttbr_flags |= TTBR_CnP;
+	}
+
+	ttbr0 = READ_SPECIALREG(ttbr0_el1);
+	ttbr0 |= TTBR_CnP;
+
+	ttbr1 = READ_SPECIALREG(ttbr1_el1);
+	ttbr1 |= TTBR_CnP;
+
+	/* Update ttbr{0,1}_el1 with the CnP flag */
+	WRITE_SPECIALREG(ttbr0_el1, ttbr0);
+	WRITE_SPECIALREG(ttbr1_el1, ttbr1);
+	isb();
+	__asm __volatile("tlbi vmalle1is");
+	dsb(ish);
+	isb();
+}
+
+/*
+ * Defer enabling CnP until we have read the ID registers to know if it's
+ * supported on all CPUs.
+ */
+static void
+pmap_init_cnp(void *dummy __unused)
+{
+	uint64_t reg;
+	u_int cpuid;
+
+	if (!get_kernel_reg(ID_AA64MMFR2_EL1, &reg))
+		return;
+
+	if (ID_AA64MMFR2_CnP_VAL(reg) != ID_AA64MMFR2_CnP_NONE) {
+		if (bootverbose)
+			printf("Enabling CnP\n");
+		cpuid = curcpu;
+		smp_rendezvous(NULL, pmap_set_cnp, NULL, &cpuid);
+	}
 
-	return (ASID_TO_OPERAND(COOKIE_TO_ASID(pmap->pm_cookie)) |
-	    pmap->pm_ttbr);
 }
+SYSINIT(pmap_init_cnp, SI_SUB_SMP, SI_ORDER_ANY, pmap_init_cnp, NULL);
 
 static bool
 pmap_activate_int(pmap_t pmap)