aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2023-09-06 11:07:41 +0000
committerAndrew Turner <andrew@FreeBSD.org>2023-09-06 17:32:49 +0000
commit9e2cafe4fb901214903484998adf51a6cc5e4ebb (patch)
tree71348d87bb9ef5f84324cbb59e922563d911bac9
parentaacbe7384221d2eafa326864bbbe2f22a10063ce (diff)
downloadsrc-9e2cafe4fb901214903484998adf51a6cc5e4ebb.tar.gz
src-9e2cafe4fb901214903484998adf51a6cc5e4ebb.zip
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
-rw-r--r--sys/arm64/arm64/identcpu.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index fced2ffab258..e84ac338497b 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -2259,6 +2259,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)