diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -42,6 +42,8 @@ option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) +option(COMPILER_RT_DISABLE_AARCH64_FMV "Disable AArch64 Function Multi Versioning support" OFF) +mark_as_advanced(COMPILER_RT_DISABLE_AARCH64_FMV) option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON) mark_as_advanced(COMPILER_RT_BUILD_CRT) option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" ON) diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -770,6 +770,10 @@ append_list_if(COMPILER_RT_HAS_VISIBILITY_HIDDEN_FLAG VISIBILITY_HIDDEN BUILTIN_DEFS) endif() + if(COMPILER_RT_DISABLE_AARCH64_FMV) + list(APPEND BUILTIN_DEFS DISABLE_AARCH64_FMV) + endif() + append_list_if(COMPILER_RT_HAS_ASM_LSE HAS_ASM_LSE BUILTIN_DEFS) foreach (arch ${BUILTIN_SUPPORTED_ARCH}) diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -838,6 +838,66 @@ return 0; } #elif defined(__aarch64__) +// LSE support detection for out-of-line atomics +// using HWCAP and Auxiliary vector +_Bool __aarch64_have_lse_atomics + __attribute__((visibility("hidden"), nocommon)); + +#if defined(__has_include) +#if __has_include() +#include +#if __has_include() +#include + +#if defined(__ANDROID__) +#include +#include +#elif defined(__Fuchsia__) +#include +#include +#endif + +// Detect Exynos 9810 CPU +#define IF_EXYNOS9810 \ + char arch[PROP_VALUE_MAX]; \ + if (__system_property_get("ro.arch", arch) > 0 && \ + strncmp(arch, "exynos9810", sizeof("exynos9810") - 1) == 0) + +static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) { +#if defined(__FreeBSD__) + unsigned long hwcap; + int result = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap); + __aarch64_have_lse_atomics = result == 0 && (hwcap & HWCAP_ATOMICS) != 0; +#elif defined(__Fuchsia__) + // This ensures the vDSO is a direct link-time dependency of anything that + // needs this initializer code. +#pragma comment(lib, "zircon") + uint32_t features; + zx_status_t status = _zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); + __aarch64_have_lse_atomics = + status == ZX_OK && (features & ZX_ARM64_FEATURE_ISA_ATOMICS) != 0; +#else + unsigned long hwcap = getauxval(AT_HWCAP); + _Bool result = (hwcap & HWCAP_ATOMICS) != 0; +#if defined(__ANDROID__) + if (result) { + // Some cores in the Exynos 9810 CPU are ARMv8.2 and others are ARMv8.0; + // only the former support LSE atomics. However, the kernel in the + // initial Android 8.0 release of Galaxy S9/S9+ devices incorrectly + // reported the feature as being supported. + // + // The kernel appears to have been corrected to mark it unsupported as of + // the Android 9.0 release on those devices, and this issue has not been + // observed anywhere else. Thus, this workaround may be removed if + // compiler-rt ever drops support for Android 8.0. + IF_EXYNOS9810 result = false; + } +#endif // defined(__ANDROID__) + __aarch64_have_lse_atomics = result; +#endif // defined(__FreeBSD__) +} + +#if !defined(DISABLE_AARCH64_FMV) // CPUFeatures must correspond to the same AArch64 features in // AArch64TargetParser.h enum CPUFeatures { @@ -901,6 +961,7 @@ FEAT_SME2, FEAT_MAX }; + // Architecture features used // in Function Multi Versioning struct { @@ -908,20 +969,9 @@ // As features grows new fields could be added } __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon)); -// LSE support detection for out-of-line atomics -// using HWCAP and Auxiliary vector -_Bool __aarch64_have_lse_atomics - __attribute__((visibility("hidden"), nocommon)); -#if defined(__has_include) -#if __has_include() -#include -#if __has_include() -#include - #ifndef AT_HWCAP #define AT_HWCAP 16 #endif - #ifndef HWCAP_CPUID #define HWCAP_CPUID (1 << 11) #endif @@ -1086,54 +1136,6 @@ #define HWCAP2_SVE_EBF16 (1UL << 33) #endif -#if defined(__ANDROID__) -#include -#include -#elif defined(__Fuchsia__) -#include -#include -#endif - -// Detect Exynos 9810 CPU -#define IF_EXYNOS9810 \ - char arch[PROP_VALUE_MAX]; \ - if (__system_property_get("ro.arch", arch) > 0 && \ - strncmp(arch, "exynos9810", sizeof("exynos9810") - 1) == 0) - -static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) { -#if defined(__FreeBSD__) - unsigned long hwcap; - int result = elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap); - __aarch64_have_lse_atomics = result == 0 && (hwcap & HWCAP_ATOMICS) != 0; -#elif defined(__Fuchsia__) - // This ensures the vDSO is a direct link-time dependency of anything that - // needs this initializer code. -#pragma comment(lib, "zircon") - uint32_t features; - zx_status_t status = _zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); - __aarch64_have_lse_atomics = - status == ZX_OK && (features & ZX_ARM64_FEATURE_ISA_ATOMICS) != 0; -#else - unsigned long hwcap = getauxval(AT_HWCAP); - _Bool result = (hwcap & HWCAP_ATOMICS) != 0; -#if defined(__ANDROID__) - if (result) { - // Some cores in the Exynos 9810 CPU are ARMv8.2 and others are ARMv8.0; - // only the former support LSE atomics. However, the kernel in the - // initial Android 8.0 release of Galaxy S9/S9+ devices incorrectly - // reported the feature as being supported. - // - // The kernel appears to have been corrected to mark it unsupported as of - // the Android 9.0 release on those devices, and this issue has not been - // observed anywhere else. Thus, this workaround may be removed if - // compiler-rt ever drops support for Android 8.0. - IF_EXYNOS9810 result = false; - } -#endif // defined(__ANDROID__) - __aarch64_have_lse_atomics = result; -#endif // defined(__FreeBSD__) -} - void init_cpu_features_resolver(unsigned long hwcap, unsigned long hwcap2) { #define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F #define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) @@ -1344,6 +1346,7 @@ #undef setCPUFeature #undef IF_EXYNOS9810 } +#endif // !defined(DISABLE_AARCH64_FMV) #endif // defined(__has_include) #endif // __has_include() #endif // __has_include()