Commit 3e6c69a0 authored by Mark Brown's avatar Mark Brown Committed by Will Deacon
Browse files

arm64: Add initial support for E0PD



Kernel Page Table Isolation (KPTI) is used to mitigate some speculation
based security issues by ensuring that the kernel is not mapped when
userspace is running but this approach is expensive and is incompatible
with SPE.  E0PD, introduced in the ARMv8.5 extensions, provides an
alternative to this which ensures that accesses from userspace to the
kernel's half of the memory map to always fault with constant time,
preventing timing attacks without requiring constant unmapping and
remapping or preventing legitimate accesses.

Currently this feature will only be enabled if all CPUs in the system
support E0PD, if some CPUs do not support the feature at boot time then
the feature will not be enabled and in the unlikely event that a late
CPU is the first CPU to lack the feature then we will reject that CPU.

This initial patch does not yet integrate with KPTI, this will be dealt
with in followup patches.  Ideally we could ensure that by default we
don't use KPTI on CPUs where E0PD is present.

Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
[will: Fixed typo in Kconfig text]
Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 46cf053e
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1484,6 +1484,22 @@ config ARM64_PTR_AUTH

endmenu

menu "ARMv8.5 architectural features"

config ARM64_E0PD
	bool "Enable support for E0PD"
	default y
	help
	   E0PD (part of the ARMv8.5 extensions) allows us to ensure
	   that EL0 accesses made via TTBR1 always fault in constant time,
	   providing similar benefits to KASLR as those provided by KPTI, but
	   with lower overhead and without disrupting legitimate access to
	   kernel memory such as SPE.

	   This option enables E0PD for TTBR1 where available.

endmenu

config ARM64_SVE
	bool "ARM Scalable Vector Extension support"
	default y
+2 −1
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@
#define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM	46
#define ARM64_WORKAROUND_1542419		47
#define ARM64_WORKAROUND_1319367		48
#define ARM64_HAS_E0PD				49

#define ARM64_NCAPS				49
#define ARM64_NCAPS				50

#endif /* __ASM_CPUCAPS_H */
+2 −0
Original line number Diff line number Diff line
@@ -292,6 +292,8 @@
#define TCR_HD			(UL(1) << 40)
#define TCR_NFD0		(UL(1) << 53)
#define TCR_NFD1		(UL(1) << 54)
#define TCR_E0PD0		(UL(1) << 55)
#define TCR_E0PD1		(UL(1) << 56)

/*
 * TTBR.
+1 −0
Original line number Diff line number Diff line
@@ -655,6 +655,7 @@
#define ID_AA64MMFR1_VMIDBITS_16	2

/* id_aa64mmfr2 */
#define ID_AA64MMFR2_E0PD_SHIFT		60
#define ID_AA64MMFR2_FWB_SHIFT		40
#define ID_AA64MMFR2_AT_SHIFT		32
#define ID_AA64MMFR2_LVA_SHIFT		16
+22 −0
Original line number Diff line number Diff line
@@ -225,6 +225,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
};

static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_E0PD_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_FWB_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_AT_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
@@ -1251,6 +1252,14 @@ static void cpu_enable_address_auth(struct arm64_cpu_capabilities const *cap)
}
#endif /* CONFIG_ARM64_PTR_AUTH */

#ifdef CONFIG_ARM64_E0PD
static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap)
{
	if (this_cpu_has_cap(ARM64_HAS_E0PD))
		sysreg_clear_set(tcr_el1, 0, TCR_E0PD1);
}
#endif /* CONFIG_ARM64_E0PD */

#ifdef CONFIG_ARM64_PSEUDO_NMI
static bool enable_pseudo_nmi;

@@ -1566,6 +1575,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.sign = FTR_UNSIGNED,
		.min_field_value = 1,
	},
#endif
#ifdef CONFIG_ARM64_E0PD
	{
		.desc = "E0PD",
		.capability = ARM64_HAS_E0PD,
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.sys_reg = SYS_ID_AA64MMFR2_EL1,
		.sign = FTR_UNSIGNED,
		.field_pos = ID_AA64MMFR2_E0PD_SHIFT,
		.matches = has_cpuid_feature,
		.min_field_value = 1,
		.cpu_enable = cpu_enable_e0pd,
	},
#endif
	{},
};