git: 9fbac657f11b - stable/13 - arm64: Enable FEAT_E0PD when supported

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 19 Feb 2024 16:44:45 UTC
The branch stable/13 has been updated by andrew:

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

commit 9fbac657f11b868186ea4ad52af203d9c94ebb51
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-09-06 11:07:41 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-02-19 12:37:44 +0000

    arm64: Enable FEAT_E0PD when supported
    
    FEAT_E0PD adds two fields to the tcr_el1 special register that, when
    set, cause userspace access to either the top or bottom half of the
     address spaces without a page walk.
    
    This can be used to stop userspace probing the kernel address space
    as the CPU will raise an exception in the same time if the probed
    address is in the TLB or not.
    
    Reviewed by:    kevans
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D41760
    
    (cherry picked from commit 9e2cafe4fb901214903484998adf51a6cc5e4ebb)
---
 sys/arm64/arm64/identcpu.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 200841782f03..cb7850c2aa2a 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -2090,6 +2090,31 @@ cpu_features_sysinit(void *dummy __unused)
 /* 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);
 
+static void
+tcr_set_e0pd1(void *arg __unused)
+{
+	uint64_t tcr;
+
+	tcr = READ_SPECIALREG(tcr_el1);
+	tcr |= TCR_E0PD1;
+	WRITE_SPECIALREG(tcr_el1, tcr);
+	isb();
+}
+
+/* Enable support for more recent architecture features */
+static void
+cpu_feat_support(void *arg __unused)
+{
+	/*
+	 * If FEAT_E0PD is supported use it to cause faults without a page
+	 * table walk if userspace tries to access kernel memory.
+	 */
+	if (ID_AA64MMFR2_E0PD_VAL(kern_cpu_desc.id_aa64mmfr2) !=
+	    ID_AA64MMFR2_E0PD_NONE)
+		smp_rendezvous(NULL, tcr_set_e0pd1, NULL, NULL);
+}
+SYSINIT(cpu_feat_support, SI_SUB_SMP, SI_ORDER_ANY, cpu_feat_support, NULL);
+
 #ifdef COMPAT_FREEBSD32
 static u_long
 parse_cpu_features_hwcap32(void)