Dynamically select LSE-based atomic(9)s on arm64.
Once all CPUs are online, determine if they all support LSE atomics and set lse_supported to indicate this. For now the atomic(9) implementations are still always inlined, though it would be preferable to create out-of-line functions to avoid text bloat. This was not done here since big.little systems exist in which some CPUs implement LSE while others do not, and ifunc resolution must occur well before this scenario can be detected. It does seem unlikely that FreeBSD will ever run on such platforms, however, so converting atomic(9) to use ifuncs is probably a good next step. Add a LSE_ATOMICS arm64 kernel configuration option to unconditionally select LSE-based atomic(9) implementations when the target system is known. Reviewed by: andrew, kib MFC after: 1 month Sponsored by: The FreeBSD Foundation, Amazon (hardware) Differential Revision: https://reviews.freebsd.org/D23325
This commit is contained in:
parent
1f66354182
commit
73a1608d91
@ -114,8 +114,8 @@ struct cpu_desc {
|
||||
uint64_t id_aa64pfr1;
|
||||
};
|
||||
|
||||
struct cpu_desc cpu_desc[MAXCPU];
|
||||
struct cpu_desc user_cpu_desc;
|
||||
static struct cpu_desc cpu_desc[MAXCPU];
|
||||
static struct cpu_desc user_cpu_desc;
|
||||
static u_int cpu_print_regs;
|
||||
#define PRINT_ID_AA64_AFR0 0x00000001
|
||||
#define PRINT_ID_AA64_AFR1 0x00000002
|
||||
@ -961,6 +961,7 @@ update_user_regs(u_int cpu)
|
||||
|
||||
/* HWCAP */
|
||||
extern u_long elf_hwcap;
|
||||
bool __read_frequently lse_supported = false;
|
||||
|
||||
static void
|
||||
identify_cpu_sysinit(void *dummy __unused)
|
||||
@ -975,7 +976,6 @@ identify_cpu_sysinit(void *dummy __unused)
|
||||
ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 | ID_AA64PFR0_EL0_64;
|
||||
user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
|
||||
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
print_cpu_features(cpu);
|
||||
hwcap = parse_cpu_features_hwcap(cpu);
|
||||
@ -986,6 +986,16 @@ identify_cpu_sysinit(void *dummy __unused)
|
||||
update_user_regs(cpu);
|
||||
}
|
||||
|
||||
if ((elf_hwcap & HWCAP_ATOMICS) != 0) {
|
||||
lse_supported = true;
|
||||
if (bootverbose)
|
||||
printf("Enabling LSE atomics in the kernel\n");
|
||||
}
|
||||
#ifdef LSE_ATOMICS
|
||||
if (!lse_supported)
|
||||
panic("CPU does not support LSE atomic instructions");
|
||||
#endif
|
||||
|
||||
install_undef_handler(true, user_mrs_handler);
|
||||
}
|
||||
SYSINIT(idenrity_cpu, SI_SUB_SMP, SI_ORDER_ANY, identify_cpu_sysinit, NULL);
|
||||
|
@ -59,6 +59,18 @@
|
||||
|
||||
#include <sys/atomic_common.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern bool lse_supported;
|
||||
|
||||
#ifdef LSE_ATOMICS
|
||||
#define _ATOMIC_LSE_SUPPORTED 1
|
||||
#else
|
||||
#define _ATOMIC_LSE_SUPPORTED lse_supported
|
||||
#endif
|
||||
#else
|
||||
#define _ATOMIC_LSE_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
#define _ATOMIC_OP_PROTO(t, op, bar, flav) \
|
||||
static __inline void \
|
||||
atomic_##op##_##bar##t##flav(volatile uint##t##_t *p, uint##t##_t val)
|
||||
@ -98,7 +110,10 @@ _ATOMIC_OP_PROTO(t, op, bar, _lse) \
|
||||
\
|
||||
_ATOMIC_OP_PROTO(t, op, bar, ) \
|
||||
{ \
|
||||
atomic_##op##_##bar##t##_llsc(p, val); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
atomic_##op##_##bar##t##_lse(p, val); \
|
||||
else \
|
||||
atomic_##op##_##bar##t##_llsc(p, val); \
|
||||
}
|
||||
|
||||
#define __ATOMIC_OP(op, llsc_asm_op, lse_asm_op, pre, bar, a, l) \
|
||||
@ -175,7 +190,12 @@ _ATOMIC_CMPSET_PROTO(t, bar, _lse) \
|
||||
\
|
||||
_ATOMIC_CMPSET_PROTO(t, bar, ) \
|
||||
{ \
|
||||
return (atomic_cmpset_##bar##t##_llsc(p, cmpval, newval)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_cmpset_##bar##t##_lse(p, cmpval, \
|
||||
newval)); \
|
||||
else \
|
||||
return (atomic_cmpset_##bar##t##_llsc(p, cmpval, \
|
||||
newval)); \
|
||||
} \
|
||||
\
|
||||
_ATOMIC_FCMPSET_PROTO(t, bar, _llsc) \
|
||||
@ -223,7 +243,12 @@ _ATOMIC_FCMPSET_PROTO(t, bar, _lse) \
|
||||
\
|
||||
_ATOMIC_FCMPSET_PROTO(t, bar, ) \
|
||||
{ \
|
||||
return (atomic_fcmpset_##bar##t##_llsc(p, cmpval, newval)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_fcmpset_##bar##t##_lse(p, cmpval, \
|
||||
newval)); \
|
||||
else \
|
||||
return (atomic_fcmpset_##bar##t##_llsc(p, cmpval, \
|
||||
newval)); \
|
||||
}
|
||||
|
||||
#define _ATOMIC_CMPSET(bar, a, l) \
|
||||
@ -277,7 +302,10 @@ _ATOMIC_FETCHADD_PROTO(t, _lse) \
|
||||
\
|
||||
_ATOMIC_FETCHADD_PROTO(t, ) \
|
||||
{ \
|
||||
return (atomic_fetchadd_##t##_llsc(p, val)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_fetchadd_##t##_lse(p, val)); \
|
||||
else \
|
||||
return (atomic_fetchadd_##t##_llsc(p, val)); \
|
||||
}
|
||||
|
||||
_ATOMIC_FETCHADD_IMPL(32, w)
|
||||
@ -327,7 +355,10 @@ _ATOMIC_SWAP_PROTO(t, _lse) \
|
||||
\
|
||||
_ATOMIC_SWAP_PROTO(t, ) \
|
||||
{ \
|
||||
return (atomic_swap_##t##_llsc(p, val)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_swap_##t##_lse(p, val)); \
|
||||
else \
|
||||
return (atomic_swap_##t##_llsc(p, val)); \
|
||||
} \
|
||||
\
|
||||
_ATOMIC_READANDCLEAR_PROTO(t, _llsc) \
|
||||
@ -354,7 +385,10 @@ _ATOMIC_READANDCLEAR_PROTO(t, _lse) \
|
||||
\
|
||||
_ATOMIC_READANDCLEAR_PROTO(t, ) \
|
||||
{ \
|
||||
return (atomic_readandclear_##t##_llsc(p)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_readandclear_##t##_lse(p)); \
|
||||
else \
|
||||
return (atomic_readandclear_##t##_llsc(p)); \
|
||||
}
|
||||
|
||||
_ATOMIC_SWAP_IMPL(32, w, wzr)
|
||||
@ -403,7 +437,10 @@ _ATOMIC_TEST_OP_PROTO(t, op, _lse) \
|
||||
\
|
||||
_ATOMIC_TEST_OP_PROTO(t, op, ) \
|
||||
{ \
|
||||
return (atomic_testand##op##_##t##_llsc(p, val)); \
|
||||
if (_ATOMIC_LSE_SUPPORTED) \
|
||||
return (atomic_testand##op##_##t##_lse(p, val)); \
|
||||
else \
|
||||
return (atomic_testand##op##_##t##_llsc(p, val)); \
|
||||
}
|
||||
|
||||
#define _ATOMIC_TEST_OP(op, llsc_asm_op, lse_asm_op) \
|
||||
|
@ -7,6 +7,7 @@ SOCDEV_VA opt_global.h
|
||||
THUNDERX_PASS_1_1_ERRATA opt_global.h
|
||||
VFP opt_global.h
|
||||
LINUX_BOOT_ABI opt_global.h
|
||||
LSE_ATOMICS opt_global.h
|
||||
|
||||
# Binary compatibility
|
||||
COMPAT_FREEBSD32 opt_global.h
|
||||
|
Loading…
Reference in New Issue
Block a user