Skip to content

Commit bbbb657

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: Avoid cpus_have_const_cap() for ARM64_HAS_BTI
In system_supports_bti() we use cpus_have_const_cap() to check for ARM64_HAS_BTI, but this is not necessary and alternative_has_cap_*() or cpus_have_final_*cap() would be preferable. For historical reasons, cpus_have_const_cap() is more complicated than it needs to be. Before cpucaps are finalized, it will perform a bitmap test of the system_cpucaps bitmap, and once cpucaps are finalized it will use an alternative branch. This used to be necessary to handle some race conditions in the window between cpucap detection and the subsequent patching of alternatives and static branches, where different branches could be out-of-sync with one another (or w.r.t. alternative sequences). Now that we use alternative branches instead of static branches, these are all patched atomically w.r.t. one another, and there are only a handful of cases that need special care in the window between cpucap detection and alternative patching. Due to the above, it would be nice to remove cpus_have_const_cap(), and migrate callers over to alternative_has_cap_*(), cpus_have_final_cap(), or cpus_have_cap() depending on when their requirements. This will remove redundant instructions and improve code generation, and will make it easier to determine how each callsite will behave before, during, and after alternative patching. When CONFIG_ARM64_BTI_KERNEL=y, the ARM64_HAS_BTI cpucap is a strict boot cpu feature which is detected and patched early on the boot cpu. All uses guarded by CONFIG_ARM64_BTI_KERNEL happen after the boot CPU has detected ARM64_HAS_BTI and patched boot alternatives, and hence can safely use alternative_has_cap_*() or cpus_have_final_boot_cap(). Regardless of CONFIG_ARM64_BTI_KERNEL, all other uses of ARM64_HAS_BTI happen after system capabilities have been finalized and alternatives have been patched. Hence these can safely use alternative_has_cap_*) or cpus_have_final_cap(). This patch splits system_supports_bti() into system_supports_bti() and system_supports_bti_kernel(), with the former handling where the cpucap affects userspace functionality, and ther latter handling where the cpucap affects kernel functionality. The use of cpus_have_const_cap() is replaced by cpus_have_final_cap() in cpus_have_const_cap, and cpus_have_final_boot_cap() in system_supports_bti_kernel(). This will avoid generating code to test the system_cpucaps bitmap and should be better for all subsequent calls at runtime. The use of cpus_have_final_cap() and cpus_have_final_boot_cap() will make it easier to spot if code is chaanged such that these run before the ARM64_HAS_BTI cpucap is guaranteed to have been finalized. Signed-off-by: Mark Rutland <[email protected]> Reviewed-by: Mark Brown <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Suzuki K Poulose <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent d70bac1 commit bbbb657

File tree

5 files changed

+11
-10
lines changed

5 files changed

+11
-10
lines changed

arch/arm64/include/asm/cpufeature.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,13 @@ static inline bool system_has_prio_mask_debugging(void)
837837

838838
static inline bool system_supports_bti(void)
839839
{
840-
return cpus_have_const_cap(ARM64_BTI);
840+
return cpus_have_final_cap(ARM64_BTI);
841+
}
842+
843+
static inline bool system_supports_bti_kernel(void)
844+
{
845+
return IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
846+
cpus_have_final_boot_cap(ARM64_BTI);
841847
}
842848

843849
static inline bool system_supports_tlb_range(void)

arch/arm64/include/asm/pgtable-prot.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,7 @@ extern bool arm64_use_ng_mappings;
7575
* If we have userspace only BTI we don't want to mark kernel pages
7676
* guarded even if the system does support BTI.
7777
*/
78-
#ifdef CONFIG_ARM64_BTI_KERNEL
79-
#define PTE_MAYBE_GP (system_supports_bti() ? PTE_GP : 0)
80-
#else
81-
#define PTE_MAYBE_GP 0
82-
#endif
78+
#define PTE_MAYBE_GP (system_supports_bti_kernel() ? PTE_GP : 0)
8379

8480
#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
8581
#define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL_RO)

arch/arm64/kernel/efi.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data)
113113
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
114114
if (md->attribute & EFI_MEMORY_XP)
115115
pte = set_pte_bit(pte, __pgprot(PTE_PXN));
116-
else if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
117-
system_supports_bti() && spd->has_bti)
116+
else if (system_supports_bti_kernel() && spd->has_bti)
118117
pte = set_pte_bit(pte, __pgprot(PTE_GP));
119118
set_pte(ptep, pte);
120119
return 0;

arch/arm64/kernel/vdso.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ static int __setup_additional_pages(enum vdso_abi abi,
212212
if (IS_ERR(ret))
213213
goto up_fail;
214214

215-
if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti())
215+
if (system_supports_bti_kernel())
216216
gp_flags = VM_ARM64_BTI;
217217

218218
vdso_base += VVAR_NR_PAGES * PAGE_SIZE;

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ static int hyp_set_prot_attr(enum kvm_pgtable_prot prot, kvm_pte_t *ptep)
401401
if (device)
402402
return -EINVAL;
403403

404-
if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti())
404+
if (system_supports_bti_kernel())
405405
attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP;
406406
} else {
407407
attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN;

0 commit comments

Comments
 (0)