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)
This commit is contained in:
Andrew Turner 2023-09-06 12:07:41 +01:00
parent bcedcc2aad
commit 628fd849f5

View file

@ -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)