Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: Introduce system_capabilities_finalized() marker

We finalize the system wide capabilities after the SMP CPUs
are booted by the kernel. This is used as a marker for deciding
various checks in the kernel. e.g, sanity check the hotplugged
CPUs for missing mandatory features.

However there is no explicit helper available for this in the
kernel. There is sys_caps_initialised, which is not exposed.
The other closest one we have is the jump_label arm64_const_caps_ready
which denotes that the capabilities are set and the capability checks
could use the individual jump_labels for fast path. This is
performed before setting the ELF Hwcaps, which must be checked
against the new CPUs. We also perform some of the other initialization
e.g, SVE setup, which is important for the use of FP/SIMD
where SVE is supported. Normally userspace doesn't get to run
before we finish this. However the in-kernel users may
potentially start using the neon mode. So, we need to
reject uses of neon mode before we are set. Instead of defining
a new marker for the completion of SVE setup, we could simply
reuse the arm64_const_caps_ready and enable it once we have
finished all the setup. Also we could expose this to the
various users as "system_capabilities_finalized()" to make
it more meaningful than "const_caps_ready".

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Suzuki K Poulose and committed by
Will Deacon
b51c6ac2 46cf053e

+16 -19
+5
arch/arm64/include/asm/cpufeature.h
··· 613 613 system_uses_irq_prio_masking(); 614 614 } 615 615 616 + static inline bool system_capabilities_finalized(void) 617 + { 618 + return static_branch_likely(&arm64_const_caps_ready); 619 + } 620 + 616 621 #define ARM64_BP_HARDEN_UNKNOWN -1 617 622 #define ARM64_BP_HARDEN_WA_NEEDED 0 618 623 #define ARM64_BP_HARDEN_NOT_REQUIRED 1
+1 -1
arch/arm64/include/asm/kvm_host.h
··· 547 547 * wrong, and hyp will crash and burn when it uses any 548 548 * cpus_have_const_cap() wrapper. 549 549 */ 550 - BUG_ON(!static_branch_likely(&arm64_const_caps_ready)); 550 + BUG_ON(!system_capabilities_finalized()); 551 551 __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2); 552 552 553 553 /*
+9 -17
arch/arm64/kernel/cpufeature.c
··· 53 53 * will be used to determine if a new booting CPU should 54 54 * go through the verification process to make sure that it 55 55 * supports the system capabilities, without using a hotplug 56 - * notifier. 56 + * notifier. This is also used to decide if we could use 57 + * the fast path for checking constant CPU caps. 57 58 */ 58 - static bool sys_caps_initialised; 59 - 60 - static inline void set_sys_caps_initialised(void) 59 + DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready); 60 + EXPORT_SYMBOL(arm64_const_caps_ready); 61 + static inline void finalize_system_capabilities(void) 61 62 { 62 - sys_caps_initialised = true; 63 + static_branch_enable(&arm64_const_caps_ready); 63 64 } 64 65 65 66 static int dump_cpu_hwcaps(struct notifier_block *self, unsigned long v, void *p) ··· 786 785 787 786 /* Probe vector lengths, unless we already gave up on SVE */ 788 787 if (id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1)) && 789 - !sys_caps_initialised) 788 + !system_capabilities_finalized()) 790 789 sve_update_vq_map(); 791 790 } 792 791 ··· 1975 1974 * Otherwise, this CPU should verify that it has all the system 1976 1975 * advertised capabilities. 1977 1976 */ 1978 - if (!sys_caps_initialised) 1977 + if (!system_capabilities_finalized()) 1979 1978 update_cpu_capabilities(SCOPE_LOCAL_CPU); 1980 1979 else 1981 1980 verify_local_cpu_capabilities(); ··· 1987 1986 update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU); 1988 1987 /* Enable the SCOPE_BOOT_CPU capabilities alone right away */ 1989 1988 enable_cpu_capabilities(SCOPE_BOOT_CPU); 1990 - } 1991 - 1992 - DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready); 1993 - EXPORT_SYMBOL(arm64_const_caps_ready); 1994 - 1995 - static void __init mark_const_caps_ready(void) 1996 - { 1997 - static_branch_enable(&arm64_const_caps_ready); 1998 1989 } 1999 1990 2000 1991 bool this_cpu_has_cap(unsigned int n) ··· 2047 2054 u32 cwg; 2048 2055 2049 2056 setup_system_capabilities(); 2050 - mark_const_caps_ready(); 2051 2057 setup_elf_hwcaps(arm64_elf_hwcaps); 2052 2058 2053 2059 if (system_supports_32bit_el0()) ··· 2059 2067 minsigstksz_setup(); 2060 2068 2061 2069 /* Advertise that we have computed the system capabilities */ 2062 - set_sys_caps_initialised(); 2070 + finalize_system_capabilities(); 2063 2071 2064 2072 /* 2065 2073 * Check for sane CTR_EL0.CWG value.
+1 -1
arch/arm64/kernel/process.c
··· 646 646 * Only allow a task to be preempted once cpufeatures have been 647 647 * enabled. 648 648 */ 649 - if (static_branch_likely(&arm64_const_caps_ready)) 649 + if (system_capabilities_finalized()) 650 650 preempt_schedule_irq(); 651 651 }