Feedback from the kernel team suggests that it's best to only use HWCAPs
rather than also use low-level checks as done by has_lse128() and has_rcpc3().
So change these to just use HWCAPs which simplifies the code and speeds up
ifunc selection by avoiding expensive system register accesses.
libatomic:
* config/linux/aarch64/host-config.h (has_lse2): Mark unused arg.
(has_lse128): Change to use HWCAPs and check size of struct.
(has_rcpc3): Likewise.
---
diff --git a/libatomic/config/linux/aarch64/host-config.h
b/libatomic/config/linux/aarch64/host-config.h
index
7f91528de5b2d04c4cda0a29622b32cdb1b442aa..78f56bad5aee39afc613836ebaea66fe6cf76790
100644
--- a/libatomic/config/linux/aarch64/host-config.h
+++ b/libatomic/config/linux/aarch64/host-config.h
@@ -90,7 +90,7 @@ typedef struct __ifunc_arg_t {
#define MIDR_PARTNUM(midr) (((midr) >> 4) & 0xfff)
static inline bool
-has_lse2 (unsigned long hwcap, const __ifunc_arg_t *features)
+has_lse2 (unsigned long hwcap, const __ifunc_arg_t *features UNUSED)
{
/* Check for LSE2. */
if (hwcap & HWCAP_USCAT)
@@ -109,50 +109,23 @@ has_lse2 (unsigned long hwcap, const __ifunc_arg_t
*features)
return false;
}
-/* LSE128 atomic support encoded in ID_AA64ISAR0_EL1.Atomic, bits[23:20].
- The minimum value for LSE128 is 0b0011. */
-
-#define AT_FEAT_FIELD(isar0) (((isar0) >> 20) & 15)
-
static inline bool
has_lse128 (unsigned long hwcap, const __ifunc_arg_t *features)
{
- if (hwcap & _IFUNC_ARG_HWCAP && features->_hwcap2 & HWCAP2_LSE128)
- return true;
-
- /* If LSE2 and CPUID are supported, check for LSE128. */
- if (hwcap & HWCAP_CPUID && hwcap & HWCAP_USCAT)
- {
- unsigned long isar0;
- asm volatile ("mrs %0, ID_AA64ISAR0_EL1" : "=r" (isar0));
- return AT_FEAT_FIELD (isar0) >= 3;
- }
-
- return false;
+ return (hwcap & _IFUNC_ARG_HWCAP
+ && features->_size > offsetof (__ifunc_arg_t, _hwcap2)
+ && features->_hwcap2 & HWCAP2_LSE128);
}
-/* LRCPC atomic support encoded in ID_AA64ISAR1_EL1.Atomic, bits[23:20].
- The minimum value for LRCPC3 is 0b0011. */
-
static inline bool
has_rcpc3 (unsigned long hwcap, const __ifunc_arg_t *features)
{
/* LSE2 is a prerequisite for atomic LDIAPP/STILP - check HWCAP_USCAT since
- has_lse2 is more expensive and Neoverse N1 does not have LRCPC3. */
- if (!(hwcap & HWCAP_USCAT))
- return false;
-
- if (hwcap & _IFUNC_ARG_HWCAP && features->_hwcap2 & HWCAP2_LRCPC3)
- return true;
-
- if (hwcap & HWCAP_CPUID)
- {
- unsigned long isar1;
- asm volatile ("mrs %0, ID_AA64ISAR1_EL1" : "=r" (isar1));
- return AT_FEAT_FIELD (isar1) >= 3;
- }
-
- return false;
+ has_lse2 is more expensive and Neoverse N1 does not have LRCPC3. */
+ return (hwcap & _IFUNC_ARG_HWCAP
+ && features->_size > offsetof (__ifunc_arg_t, _hwcap2)
+ && features->_hwcap & HWCAP_USCAT
+ && features->_hwcap2 & HWCAP2_LRCPC3);
}
#endif /* HAVE_IFUNC */