Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
Merge branch 'for-next/cpus_have_const_cap' into for-next/core
Browse files Browse the repository at this point in the history
* for-next/cpus_have_const_cap: (38 commits)
  : cpus_have_const_cap() removal
  arm64: Remove cpus_have_const_cap()
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_REPEAT_TLBI
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_NVIDIA_CARMEL_CNP
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_CAVIUM_23154
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_2645198
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_1742098
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_1542419
  arm64: Avoid cpus_have_const_cap() for ARM64_WORKAROUND_843419
  arm64: Avoid cpus_have_const_cap() for ARM64_UNMAP_KERNEL_AT_EL0
  arm64: Avoid cpus_have_const_cap() for ARM64_{SVE,SME,SME2,FA64}
  arm64: Avoid cpus_have_const_cap() for ARM64_SPECTRE_V2
  arm64: Avoid cpus_have_const_cap() for ARM64_SSBS
  arm64: Avoid cpus_have_const_cap() for ARM64_MTE
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_TLB_RANGE
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_WFXT
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_RNG
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_EPAN
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_PAN
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_GIC_PRIO_MASKING
  arm64: Avoid cpus_have_const_cap() for ARM64_HAS_DIT
  ...
  • Loading branch information
ctmarinas committed Oct 26, 2023
2 parents 2baca17 + e8d4006 commit 14dcf78
Show file tree
Hide file tree
Showing 50 changed files with 430 additions and 287 deletions.
25 changes: 16 additions & 9 deletions arch/arm/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ static int xen_starting_cpu(unsigned int cpu)
BUG_ON(err);
per_cpu(xen_vcpu, cpu) = vcpup;

if (!xen_kernel_unmapped_at_usr())
xen_setup_runstate_info(cpu);

after_register_vcpu_info:
enable_percpu_irq(xen_events_irq, 0);
return 0;
Expand Down Expand Up @@ -523,9 +520,6 @@ static int __init xen_guest_init(void)
return -EINVAL;
}

if (!xen_kernel_unmapped_at_usr())
xen_time_setup_guest();

if (xen_initial_domain())
pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);

Expand All @@ -535,7 +529,13 @@ static int __init xen_guest_init(void)
}
early_initcall(xen_guest_init);

static int __init xen_pm_init(void)
static int xen_starting_runstate_cpu(unsigned int cpu)
{
xen_setup_runstate_info(cpu);
return 0;
}

static int __init xen_late_init(void)
{
if (!xen_domain())
return -ENODEV;
Expand All @@ -548,9 +548,16 @@ static int __init xen_pm_init(void)
do_settimeofday64(&ts);
}

return 0;
if (xen_kernel_unmapped_at_usr())
return 0;

xen_time_setup_guest();

return cpuhp_setup_state(CPUHP_AP_ARM_XEN_RUNSTATE_STARTING,
"arm/xen_runstate:starting",
xen_starting_runstate_cpu, NULL);
}
late_initcall(xen_pm_init);
late_initcall(xen_late_init);


/* empty stubs */
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ generic-y += qspinlock.h
generic-y += parport.h
generic-y += user.h

generated-y += cpucaps.h
generated-y += cpucap-defs.h
generated-y += sysreg-defs.h
8 changes: 4 additions & 4 deletions arch/arm64/include/asm/alternative-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ alternative_endif
static __always_inline bool
alternative_has_cap_likely(const unsigned long cpucap)
{
compiletime_assert(cpucap < ARM64_NCAPS,
"cpucap must be < ARM64_NCAPS");
if (!cpucap_is_possible(cpucap))
return false;

asm_volatile_goto(
ALTERNATIVE_CB("b %l[l_no]", %[cpucap], alt_cb_patch_nops)
Expand All @@ -244,8 +244,8 @@ alternative_has_cap_likely(const unsigned long cpucap)
static __always_inline bool
alternative_has_cap_unlikely(const unsigned long cpucap)
{
compiletime_assert(cpucap < ARM64_NCAPS,
"cpucap must be < ARM64_NCAPS");
if (!cpucap_is_possible(cpucap))
return false;

asm_volatile_goto(
ALTERNATIVE("nop", "b %l[l_yes]", %[cpucap])
Expand Down
8 changes: 8 additions & 0 deletions arch/arm64/include/asm/arch_gicv3.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ static inline u64 gic_read_iar_cavium_thunderx(void)
return 0x3ff;
}

static u64 __maybe_unused gic_read_iar(void)
{
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_CAVIUM_23154))
return gic_read_iar_cavium_thunderx();
else
return gic_read_iar_common();
}

static inline void gic_write_ctlr(u32 val)
{
write_sysreg_s(val, SYS_ICC_CTLR_EL1);
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/archrandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static __always_inline bool __cpu_has_rng(void)
{
if (unlikely(!system_capabilities_finalized() && !preemptible()))
return this_cpu_has_cap(ARM64_HAS_RNG);
return cpus_have_const_cap(ARM64_HAS_RNG);
return alternative_has_cap_unlikely(ARM64_HAS_RNG);
}

static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void flush_dcache_folio(struct folio *);

static __always_inline void icache_inval_all_pou(void)
{
if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
if (alternative_has_cap_unlikely(ARM64_HAS_CACHE_DIC))
return;

asm("ic ialluis");
Expand Down
67 changes: 67 additions & 0 deletions arch/arm64/include/asm/cpucaps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ASM_CPUCAPS_H
#define __ASM_CPUCAPS_H

#include <asm/cpucap-defs.h>

#ifndef __ASSEMBLY__
#include <linux/types.h>
/*
* Check whether a cpucap is possible at compiletime.
*/
static __always_inline bool
cpucap_is_possible(const unsigned int cap)
{
compiletime_assert(__builtin_constant_p(cap),
"cap must be a constant");
compiletime_assert(cap < ARM64_NCAPS,
"cap must be < ARM64_NCAPS");

switch (cap) {
case ARM64_HAS_PAN:
return IS_ENABLED(CONFIG_ARM64_PAN);
case ARM64_HAS_EPAN:
return IS_ENABLED(CONFIG_ARM64_EPAN);
case ARM64_SVE:
return IS_ENABLED(CONFIG_ARM64_SVE);
case ARM64_SME:
case ARM64_SME2:
case ARM64_SME_FA64:
return IS_ENABLED(CONFIG_ARM64_SME);
case ARM64_HAS_CNP:
return IS_ENABLED(CONFIG_ARM64_CNP);
case ARM64_HAS_ADDRESS_AUTH:
case ARM64_HAS_GENERIC_AUTH:
return IS_ENABLED(CONFIG_ARM64_PTR_AUTH);
case ARM64_HAS_GIC_PRIO_MASKING:
return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI);
case ARM64_MTE:
return IS_ENABLED(CONFIG_ARM64_MTE);
case ARM64_BTI:
return IS_ENABLED(CONFIG_ARM64_BTI);
case ARM64_HAS_TLB_RANGE:
return IS_ENABLED(CONFIG_ARM64_TLB_RANGE);
case ARM64_UNMAP_KERNEL_AT_EL0:
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
case ARM64_WORKAROUND_843419:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_843419);
case ARM64_WORKAROUND_1742098:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_1742098);
case ARM64_WORKAROUND_2645198:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_2645198);
case ARM64_WORKAROUND_2658417:
return IS_ENABLED(CONFIG_ARM64_ERRATUM_2658417);
case ARM64_WORKAROUND_CAVIUM_23154:
return IS_ENABLED(CONFIG_CAVIUM_ERRATUM_23154);
case ARM64_WORKAROUND_NVIDIA_CARMEL_CNP:
return IS_ENABLED(CONFIG_NVIDIA_CARMEL_CNP_ERRATUM);
case ARM64_WORKAROUND_REPEAT_TLBI:
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
}

return true;
}
#endif /* __ASSEMBLY__ */

#endif /* __ASM_CPUCAPS_H */
96 changes: 41 additions & 55 deletions arch/arm64/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@ unsigned long cpu_get_elf_hwcap2(void);
#define cpu_set_named_feature(name) cpu_set_feature(cpu_feature(name))
#define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name))

static __always_inline bool boot_capabilities_finalized(void)
{
return alternative_has_cap_likely(ARM64_ALWAYS_BOOT);
}

static __always_inline bool system_capabilities_finalized(void)
{
return alternative_has_cap_likely(ARM64_ALWAYS_SYSTEM);
Expand All @@ -452,6 +457,8 @@ static __always_inline bool system_capabilities_finalized(void)
*/
static __always_inline bool cpus_have_cap(unsigned int num)
{
if (__builtin_constant_p(num) && !cpucap_is_possible(num))
return false;
if (num >= ARM64_NCAPS)
return false;
return arch_test_bit(num, system_cpucaps);
Expand All @@ -460,55 +467,37 @@ static __always_inline bool cpus_have_cap(unsigned int num)
/*
* Test for a capability without a runtime check.
*
* Before capabilities are finalized, this returns false.
* After capabilities are finalized, this is patched to avoid a runtime check.
* Before boot capabilities are finalized, this will BUG().
* After boot capabilities are finalized, this is patched to avoid a runtime
* check.
*
* @num must be a compile-time constant.
*/
static __always_inline bool __cpus_have_const_cap(int num)
static __always_inline bool cpus_have_final_boot_cap(int num)
{
if (num >= ARM64_NCAPS)
return false;
return alternative_has_cap_unlikely(num);
if (boot_capabilities_finalized())
return alternative_has_cap_unlikely(num);
else
BUG();
}

/*
* Test for a capability without a runtime check.
*
* Before capabilities are finalized, this will BUG().
* After capabilities are finalized, this is patched to avoid a runtime check.
* Before system capabilities are finalized, this will BUG().
* After system capabilities are finalized, this is patched to avoid a runtime
* check.
*
* @num must be a compile-time constant.
*/
static __always_inline bool cpus_have_final_cap(int num)
{
if (system_capabilities_finalized())
return __cpus_have_const_cap(num);
return alternative_has_cap_unlikely(num);
else
BUG();
}

/*
* Test for a capability, possibly with a runtime check for non-hyp code.
*
* For hyp code, this behaves the same as cpus_have_final_cap().
*
* For non-hyp code:
* Before capabilities are finalized, this behaves as cpus_have_cap().
* After capabilities are finalized, this is patched to avoid a runtime check.
*
* @num must be a compile-time constant.
*/
static __always_inline bool cpus_have_const_cap(int num)
{
if (is_hyp_code())
return cpus_have_final_cap(num);
else if (system_capabilities_finalized())
return __cpus_have_const_cap(num);
else
return cpus_have_cap(num);
}

static inline int __attribute_const__
cpuid_feature_extract_signed_field_width(u64 features, int field, int width)
{
Expand Down Expand Up @@ -628,7 +617,9 @@ static inline bool id_aa64pfr1_mte(u64 pfr1)
return val >= ID_AA64PFR1_EL1_MTE_MTE2;
}

void __init setup_cpu_features(void);
void __init setup_system_features(void);
void __init setup_user_features(void);

void check_local_cpu_capabilities(void);

u64 read_sanitised_ftr_reg(u32 id);
Expand Down Expand Up @@ -737,13 +728,12 @@ static inline bool system_supports_mixed_endian(void)

static __always_inline bool system_supports_fpsimd(void)
{
return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
return alternative_has_cap_likely(ARM64_HAS_FPSIMD);
}

static inline bool system_uses_hw_pan(void)
{
return IS_ENABLED(CONFIG_ARM64_PAN) &&
cpus_have_const_cap(ARM64_HAS_PAN);
return alternative_has_cap_unlikely(ARM64_HAS_PAN);
}

static inline bool system_uses_ttbr0_pan(void)
Expand All @@ -754,26 +744,22 @@ static inline bool system_uses_ttbr0_pan(void)

static __always_inline bool system_supports_sve(void)
{
return IS_ENABLED(CONFIG_ARM64_SVE) &&
cpus_have_const_cap(ARM64_SVE);
return alternative_has_cap_unlikely(ARM64_SVE);
}

static __always_inline bool system_supports_sme(void)
{
return IS_ENABLED(CONFIG_ARM64_SME) &&
cpus_have_const_cap(ARM64_SME);
return alternative_has_cap_unlikely(ARM64_SME);
}

static __always_inline bool system_supports_sme2(void)
{
return IS_ENABLED(CONFIG_ARM64_SME) &&
cpus_have_const_cap(ARM64_SME2);
return alternative_has_cap_unlikely(ARM64_SME2);
}

static __always_inline bool system_supports_fa64(void)
{
return IS_ENABLED(CONFIG_ARM64_SME) &&
cpus_have_const_cap(ARM64_SME_FA64);
return alternative_has_cap_unlikely(ARM64_SME_FA64);
}

static __always_inline bool system_supports_tpidr2(void)
Expand All @@ -783,20 +769,17 @@ static __always_inline bool system_supports_tpidr2(void)

static __always_inline bool system_supports_cnp(void)
{
return IS_ENABLED(CONFIG_ARM64_CNP) &&
cpus_have_const_cap(ARM64_HAS_CNP);
return alternative_has_cap_unlikely(ARM64_HAS_CNP);
}

static inline bool system_supports_address_auth(void)
{
return IS_ENABLED(CONFIG_ARM64_PTR_AUTH) &&
cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH);
return cpus_have_final_boot_cap(ARM64_HAS_ADDRESS_AUTH);
}

static inline bool system_supports_generic_auth(void)
{
return IS_ENABLED(CONFIG_ARM64_PTR_AUTH) &&
cpus_have_const_cap(ARM64_HAS_GENERIC_AUTH);
return alternative_has_cap_unlikely(ARM64_HAS_GENERIC_AUTH);
}

static inline bool system_has_full_ptr_auth(void)
Expand All @@ -806,14 +789,12 @@ static inline bool system_has_full_ptr_auth(void)

static __always_inline bool system_uses_irq_prio_masking(void)
{
return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
cpus_have_const_cap(ARM64_HAS_GIC_PRIO_MASKING);
return alternative_has_cap_unlikely(ARM64_HAS_GIC_PRIO_MASKING);
}

static inline bool system_supports_mte(void)
{
return IS_ENABLED(CONFIG_ARM64_MTE) &&
cpus_have_const_cap(ARM64_MTE);
return alternative_has_cap_unlikely(ARM64_MTE);
}

static inline bool system_has_prio_mask_debugging(void)
Expand All @@ -824,13 +805,18 @@ static inline bool system_has_prio_mask_debugging(void)

static inline bool system_supports_bti(void)
{
return IS_ENABLED(CONFIG_ARM64_BTI) && cpus_have_const_cap(ARM64_BTI);
return cpus_have_final_cap(ARM64_BTI);
}

static inline bool system_supports_bti_kernel(void)
{
return IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
cpus_have_final_boot_cap(ARM64_BTI);
}

static inline bool system_supports_tlb_range(void)
{
return IS_ENABLED(CONFIG_ARM64_TLB_RANGE) &&
cpus_have_const_cap(ARM64_HAS_TLB_RANGE);
return alternative_has_cap_unlikely(ARM64_HAS_TLB_RANGE);
}

int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
Expand Down
Loading

0 comments on commit 14dcf78

Please sign in to comment.