diff options
author | Pavel Iliin <Pavel.Iliin@arm.com> | 2023-07-11 12:46:28 +0100 |
---|---|---|
committer | Pavel Iliin <Pavel.Iliin@arm.com> | 2023-07-14 00:37:48 +0100 |
commit | 61962aa1eec922c7dddd36897bb29888b4c98174 (patch) | |
tree | 71511bb6d7f081ebad9d35d6d22612f9c3595ad3 /compiler-rt | |
parent | d3316bc1114d17aac1a53d1fd32de92bdd70c837 (diff) | |
download | llvm-61962aa1eec922c7dddd36897bb29888b4c98174.zip llvm-61962aa1eec922c7dddd36897bb29888b4c98174.tar.gz llvm-61962aa1eec922c7dddd36897bb29888b4c98174.tar.bz2 |
[compiler-rt][AArch64] Correct how FMV use ifunc resolver abi.
The patch fixes second argument of Function Multi Versioning resolvers,
it is pointer to an extendible struct containing hwcap and hwcap2 not a
unsigned long hwcap2. Also fixes FMV features caching in resolver.
Differential Revision: https://reviews.llvm.org/D155026
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/builtins/cpu_model.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c index c013bb6..20a03e8 100644 --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -847,6 +847,17 @@ _Bool __aarch64_have_lse_atomics #if defined(__has_include) #if __has_include(<sys/auxv.h>) #include <sys/auxv.h> + +#if __has_include(<sys/ifunc.h>) +#include <sys/ifunc.h> +#else +typedef struct __ifunc_arg_t { + unsigned long _size; + unsigned long _hwcap; + unsigned long _hwcap2; +} __ifunc_arg_t; +#endif // __has_include(<sys/ifunc.h>) + #if __has_include(<asm/hwcap.h>) #include <asm/hwcap.h> @@ -858,6 +869,9 @@ _Bool __aarch64_have_lse_atomics #include <zircon/syscalls.h> #endif +#ifndef _IFUNC_ARG_HWCAP +#define _IFUNC_ARG_HWCAP (1ULL << 62) +#endif #ifndef AT_HWCAP #define AT_HWCAP 16 #endif @@ -1140,11 +1154,16 @@ struct { // As features grows new fields could be added } __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon)); -void init_cpu_features_resolver(unsigned long hwcap, unsigned long hwcap2) { +void init_cpu_features_resolver(unsigned long hwcap, const __ifunc_arg_t *arg) { #define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F #define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) #define extractBits(val, start, number) \ (val & ((1ULL << number) - 1ULL) << start) >> start + if (__aarch64_cpu_features.features) + return; + unsigned long hwcap2 = 0; + if (hwcap & _IFUNC_ARG_HWCAP) + hwcap2 = arg->_hwcap2; if (hwcap & HWCAP_CRC32) setCPUFeature(FEAT_CRC); if (hwcap & HWCAP_PMULL) @@ -1320,6 +1339,7 @@ void init_cpu_features_resolver(unsigned long hwcap, unsigned long hwcap2) { if (hwcap & HWCAP_SHA3) setCPUFeature(FEAT_SHA3); } + setCPUFeature(FEAT_MAX); } void CONSTRUCTOR_ATTRIBUTE init_cpu_features(void) { @@ -1328,7 +1348,6 @@ void CONSTRUCTOR_ATTRIBUTE init_cpu_features(void) { // CPU features already initialized. if (__aarch64_cpu_features.features) return; - setCPUFeature(FEAT_MAX); #if defined(__FreeBSD__) int res = 0; res = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap); @@ -1344,7 +1363,11 @@ void CONSTRUCTOR_ATTRIBUTE init_cpu_features(void) { hwcap = getauxval(AT_HWCAP); hwcap2 = getauxval(AT_HWCAP2); #endif // defined(__FreeBSD__) - init_cpu_features_resolver(hwcap, hwcap2); + __ifunc_arg_t arg; + arg._size = sizeof(__ifunc_arg_t); + arg._hwcap = hwcap; + arg._hwcap2 = hwcap2; + init_cpu_features_resolver(hwcap | _IFUNC_ARG_HWCAP, &arg); #undef extractBits #undef getCPUFeature #undef setCPUFeature |