aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt
diff options
context:
space:
mode:
authorPavel Iliin <Pavel.Iliin@arm.com>2023-07-11 12:46:28 +0100
committerPavel Iliin <Pavel.Iliin@arm.com>2023-07-14 00:37:48 +0100
commit61962aa1eec922c7dddd36897bb29888b4c98174 (patch)
tree71511bb6d7f081ebad9d35d6d22612f9c3595ad3 /compiler-rt
parentd3316bc1114d17aac1a53d1fd32de92bdd70c837 (diff)
downloadllvm-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.c29
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