arm64: Set GP bit in kernel page tables to enable BTI for the kernel
Now that the kernel is built with BTI annotations enable the feature by setting the GP bit in the stage 1 translation tables. This is done based on the features supported by the boot CPU so that we do not need to rewrite the translation tables. In order to avoid potential issues on big.LITTLE systems when there are a mix of BTI and non-BTI capable CPUs in the system when we have enabled kernel mode BTI we change BTI to be a _STRICT_BOOT_CPU_FEATURE when we have kernel BTI. This will prevent any CPUs that don't support BTI being started if the boot CPU supports BTI rather than simply not using BTI as we do when supporting BTI only in userspace. The main concern is the possibility of BTYPE being preserved by a CPU that does not implement BTI when a thread is migrated to it resulting in an incorrect state which could generate an exception when the thread migrates back to a CPU that does support BTI. If we encounter practical systems which mix BTI and non-BTI CPUs we will need to revisit this implementation. Since we currently do not generate landing pads in the BPF JIT we only map the base kernel text in this way. Signed-off-by: Mark Brown <broonie@kernel.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Link: https://lore.kernel.org/r/20200506195138.22086-5-broonie@kernel.org Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
parent
714a8d02ca
commit
c8027285e3
|
@ -21,6 +21,7 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/pgtable-types.h>
|
||||
|
||||
extern bool arm64_use_ng_mappings;
|
||||
|
@ -31,6 +32,8 @@ extern bool arm64_use_ng_mappings;
|
|||
#define PTE_MAYBE_NG (arm64_use_ng_mappings ? PTE_NG : 0)
|
||||
#define PMD_MAYBE_NG (arm64_use_ng_mappings ? PMD_SECT_NG : 0)
|
||||
|
||||
#define PTE_MAYBE_GP (system_supports_bti() ? PTE_GP : 0)
|
||||
|
||||
#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG)
|
||||
#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
|
||||
|
||||
|
|
|
@ -1800,7 +1800,11 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
|||
{
|
||||
.desc = "Branch Target Identification",
|
||||
.capability = ARM64_BTI,
|
||||
#ifdef CONFIG_ARM64_BTI_KERNEL
|
||||
.type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE,
|
||||
#else
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
#endif
|
||||
.matches = has_cpuid_feature,
|
||||
.cpu_enable = bti_enable,
|
||||
.sys_reg = SYS_ID_AA64PFR1_EL1,
|
||||
|
|
|
@ -609,6 +609,22 @@ static int __init map_entry_trampoline(void)
|
|||
core_initcall(map_entry_trampoline);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Open coded check for BTI, only for use to determine configuration
|
||||
* for early mappings for before the cpufeature code has run.
|
||||
*/
|
||||
static bool arm64_early_this_cpu_has_bti(void)
|
||||
{
|
||||
u64 pfr1;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_ARM64_BTI_KERNEL))
|
||||
return false;
|
||||
|
||||
pfr1 = read_sysreg_s(SYS_ID_AA64PFR1_EL1);
|
||||
return cpuid_feature_extract_unsigned_field(pfr1,
|
||||
ID_AA64PFR1_BT_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create fine-grained mappings for the kernel.
|
||||
*/
|
||||
|
@ -624,6 +640,14 @@ static void __init map_kernel(pgd_t *pgdp)
|
|||
*/
|
||||
pgprot_t text_prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;
|
||||
|
||||
/*
|
||||
* If we have a CPU that supports BTI and a kernel built for
|
||||
* BTI then mark the kernel executable text as guarded pages
|
||||
* now so we don't have to rewrite the page tables later.
|
||||
*/
|
||||
if (arm64_early_this_cpu_has_bti())
|
||||
text_prot = __pgprot_modify(text_prot, PTE_GP, PTE_GP);
|
||||
|
||||
/*
|
||||
* Only rodata will be remapped with different permissions later on,
|
||||
* all other segments are allowed to use contiguous mappings.
|
||||
|
|
Loading…
Reference in New Issue