From fe6dc9dc8549cd9de7a0ddb04d921fd3263b51df Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 21 Apr 2021 11:33:44 +0200 Subject: [PATCH] Add runtime ARM64 AES check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds runtime CPU detection for Windows and macOS, and switches feature detection of AES to runtime like for x86, So far only on ARM64, since gcc doesn't do function versioning on ARM32, but clang can, so it could be added later. Change-Id: Ibe5d60f48cdae3e366a8ecd6263534ba2b09b131 Reviewed-by: Tor Arne Vestbø Reviewed-by: Alexandru Croitor --- .prev_configure.cmake | 34 ++++++++++++++++-------- config.tests/arch/arch.cpp | 3 +++ configure.cmake | 30 ++++++++++++++++------ configure.json | 33 +++++++++++++++++++----- src/corelib/global/qsimd.cpp | 41 ++++++++++++++++++++--------- src/corelib/global/qsimd_p.h | 50 ++++++++++++++++++++++-------------- src/corelib/tools/qhash.cpp | 11 +++++--- 7 files changed, 143 insertions(+), 59 deletions(-) diff --git a/.prev_configure.cmake b/.prev_configure.cmake index 84741e4406f..e93ca1ba73d 100644 --- a/.prev_configure.cmake +++ b/.prev_configure.cmake @@ -763,12 +763,12 @@ qt_feature("shani" PRIVATE ) qt_feature_definition("shani" "QT_COMPILER_SUPPORTS_SHA" VALUE "1") qt_feature_config("shani" QMAKE_PRIVATE_CONFIG) -qt_feature("x86SimdAlways" - LABEL "Intrinsics without -mXXX option" - CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND ON +qt_feature("simdAlways" + LABEL "Intrinsics without compiler architecture option" + CONDITION ( ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND ON ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) -qt_feature_definition("x86SimdAlways" "QT_COMPILER_SUPPORTS_SIMD_ALWAYS" VALUE "1") -qt_feature_config("x86SimdAlways" QMAKE_PRIVATE_CONFIG) +qt_feature_definition("simdAlways" "QT_COMPILER_SUPPORTS_SIMD_ALWAYS" VALUE "1") +qt_feature_config("simdAlways" QMAKE_PRIVATE_CONFIG) qt_feature("mips_dsp" PRIVATE LABEL "DSP" CONDITION ( TEST_architecture_arch STREQUAL mips ) AND TEST_arch_${TEST_architecture_arch}_subarch_dsp @@ -787,6 +787,18 @@ qt_feature("neon" PRIVATE ) qt_feature_definition("neon" "QT_COMPILER_SUPPORTS_NEON" VALUE "1") qt_feature_config("neon" QMAKE_PRIVATE_CONFIG) +qt_feature("arm_crc32" PRIVATE + LABEL "CRC32" + CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_crc32 +) +qt_feature_definition("arm_crc32" "QT_COMPILER_SUPPORTS_CRC32" VALUE "1") +qt_feature_config("arm_crc32" QMAKE_PRIVATE_CONFIG) +qt_feature("arm_crypto" PRIVATE + LABEL "AES" + CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_crypto +) +qt_feature_definition("arm_crypto" "QT_COMPILER_SUPPORTS_AES" VALUE "1") +qt_feature_config("arm_crypto" QMAKE_PRIVATE_CONFIG) qt_feature("posix_fallocate" PRIVATE LABEL "POSIX fallocate()" CONDITION TEST_posix_fallocate @@ -983,11 +995,13 @@ qt_configure_add_summary_entry( CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) ) qt_configure_add_summary_entry( - ARGS "x86SimdAlways" - CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND NOT MSVC + ARGS "simdAlways" + CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND NOT MSVC ) qt_configure_add_summary_entry( - ARGS "neon" + TYPE "featureList" + ARGS "neon arm_crc32 arm_crypto" + MESSAGE "Extensions" CONDITION ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) qt_configure_add_summary_entry( @@ -1043,8 +1057,8 @@ qt_configure_add_report_entry( ) qt_configure_add_report_entry( TYPE NOTE - MESSAGE "Using pthreads" - CONDITION QT_FEATURE_thread + MESSAGE "Enable thread support" + CONDITION QT_FEATURE_thread AND WASM ) qt_configure_add_report_entry( TYPE ERROR diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp index 2ccfe127b52..6f57430caa3 100644 --- a/config.tests/arch/arch.cpp +++ b/config.tests/arch/arch.cpp @@ -284,6 +284,9 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:" #ifdef __ARM_FEATURE_CRC32 " crc32" #endif +#ifdef __ARM_FEATURE_CRYPTO +" crypto" +#endif // -- SPARC -- #ifdef __VIS__ diff --git a/configure.cmake b/configure.cmake index 78d585f670c..c21452583c1 100644 --- a/configure.cmake +++ b/configure.cmake @@ -790,12 +790,12 @@ qt_feature("shani" PRIVATE ) qt_feature_definition("shani" "QT_COMPILER_SUPPORTS_SHA" VALUE "1") qt_feature_config("shani" QMAKE_PRIVATE_CONFIG) -qt_feature("x86SimdAlways" - LABEL "Intrinsics without -mXXX option" - CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND ON +qt_feature("simdAlways" + LABEL "Intrinsics without compiler architecture option" + CONDITION ( ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND ON ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) -qt_feature_definition("x86SimdAlways" "QT_COMPILER_SUPPORTS_SIMD_ALWAYS" VALUE "1") -qt_feature_config("x86SimdAlways" QMAKE_PRIVATE_CONFIG) +qt_feature_definition("simdAlways" "QT_COMPILER_SUPPORTS_SIMD_ALWAYS" VALUE "1") +qt_feature_config("simdAlways" QMAKE_PRIVATE_CONFIG) qt_feature("mips_dsp" PRIVATE LABEL "DSP" CONDITION ( TEST_architecture_arch STREQUAL mips ) AND TEST_arch_${TEST_architecture_arch}_subarch_dsp @@ -814,6 +814,18 @@ qt_feature("neon" PRIVATE ) qt_feature_definition("neon" "QT_COMPILER_SUPPORTS_NEON" VALUE "1") qt_feature_config("neon" QMAKE_PRIVATE_CONFIG) +qt_feature("arm_crc32" PRIVATE + LABEL "CRC32" + CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_crc32 +) +qt_feature_definition("arm_crc32" "QT_COMPILER_SUPPORTS_CRC32" VALUE "1") +qt_feature_config("arm_crc32" QMAKE_PRIVATE_CONFIG) +qt_feature("arm_crypto" PRIVATE + LABEL "AES" + CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_crypto +) +qt_feature_definition("arm_crypto" "QT_COMPILER_SUPPORTS_AES" VALUE "1") +qt_feature_config("arm_crypto" QMAKE_PRIVATE_CONFIG) qt_feature("posix_fallocate" PRIVATE LABEL "POSIX fallocate()" CONDITION TEST_posix_fallocate @@ -1033,11 +1045,13 @@ qt_configure_add_summary_entry( CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) ) qt_configure_add_summary_entry( - ARGS "x86SimdAlways" - CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) ) AND NOT MSVC + ARGS "simdAlways" + CONDITION ( ( TEST_architecture_arch STREQUAL i386 ) OR ( TEST_architecture_arch STREQUAL x86_64 ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND NOT MSVC ) qt_configure_add_summary_entry( - ARGS "neon" + TYPE "featureList" + ARGS "neon arm_crc32 arm_crypto" + MESSAGE "Extensions" CONDITION ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) qt_configure_add_summary_entry( diff --git a/configure.json b/configure.json index 7d5f6e77a07..e4379b8be9d 100644 --- a/configure.json +++ b/configure.json @@ -1244,9 +1244,9 @@ { "type": "define", "name": "QT_COMPILER_SUPPORTS_SHA", "value": 1 } ] }, - "x86SimdAlways": { - "label": "Intrinsics without -mXXX option", - "condition": "(arch.i386 || arch.x86_64) && tests.x86SimdAlways", + "simdAlways": { + "label": "Intrinsics without compiler architecture option", + "condition": "((arch.i386 || arch.x86_64) && tests.x86SimdAlways) || arch.arm64", "output": [ "privateConfig", { "type": "define", "name": "QT_COMPILER_SUPPORTS_SIMD_ALWAYS", "value": 1 } @@ -1279,6 +1279,24 @@ { "type": "define", "name": "QT_COMPILER_SUPPORTS_NEON", "value": 1 } ] }, + "arm_crc32": { + "label": "CRC32", + "condition": "(arch.arm || arch.arm64) && subarch.crc32", + "output": [ + "privateConfig", + "privateFeature", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_CRC32", "value": 1 } + ] + }, + "arm_crypto": { + "label": "AES", + "condition": "(arch.arm || arch.arm64) && subarch.crypto", + "output": [ + "privateConfig", + "privateFeature", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_AES", "value": 1 } + ] + }, "posix_fallocate": { "label": "POSIX fallocate()", "condition": "tests.posix_fallocate", @@ -1609,12 +1627,13 @@ }, { "type": "feature", - "args": "x86SimdAlways", - "condition": "(arch.i386 || arch.x86_64) && !config.msvc" + "args": "simdAlways", + "condition": "(arch.i386 || arch.x86_64 || arch.arm64) && !config.msvc" }, { - "type": "feature", - "args": "neon", + "message": "Extensions", + "type": "featureList", + "args": "neon arm_crc32 arm_crypto", "condition": "arch.arm || arch.arm64" }, { diff --git a/src/corelib/global/qsimd.cpp b/src/corelib/global/qsimd.cpp index 37d6dd4e145..025c50b6e8a 100644 --- a/src/corelib/global/qsimd.cpp +++ b/src/corelib/global/qsimd.cpp @@ -54,22 +54,19 @@ # if !defined(Q_CC_GNU) # include # endif -#elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32)) -#include "private/qcore_unix_p.h" - -#if QT_CONFIG(getauxval) +# if defined(Q_PROCESSOR_ARM64) +# include +# endif +#elif defined(Q_OS_LINUX) && defined(Q_PROCESSOR_MIPS_32) +# include "private/qcore_unix_p.h" +#elif QT_CONFIG(getauxval) && defined(Q_PROCESSOR_ARM) # include -#endif // the kernel header definitions for HWCAP_* // (the ones we need/may need anyway) // copied from (ARM) -#define HWCAP_CRUNCH 1024 -#define HWCAP_THUMBEE 2048 #define HWCAP_NEON 4096 -#define HWCAP_VFPv3 8192 -#define HWCAP_VFPv3D16 16384 // copied from (ARM): #define HWCAP2_AES (1 << 0) @@ -84,7 +81,9 @@ #define AT_HWCAP2 26 /* extension of AT_HWCAP */ #elif defined(Q_CC_GHS) -#include +# include +#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM) +# include #endif QT_BEGIN_NAMESPACE @@ -155,8 +154,26 @@ static inline quint64 detectProcessorFeatures() return features; } // fall back to compile-time flags if getauxval failed -#endif // QT_CONFIG(getauxval) - +#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM) + unsigned feature; + size_t len = sizeof(feature); + if (sysctlbyname("hw.optional.neon", &feature, &len, nullptr, 0) == 0) + features |= feature ? CpuFeatureNEON : 0; + if (sysctlbyname("hw.optional.armv8_crc32", &feature, &len, nullptr, 0) == 0) + features |= feature ? CpuFeatureCRC32 : 0; + // There is currently no optional value for crypto/AES. +#if defined(__ARM_FEATURE_CRYPTO) + features |= CpuFeatureAES; +#endif + return features; +#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM64) + features |= CpuFeatureNEON; + if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0) + features |= CpuFeatureCRC32; + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0) + features |= CpuFeatureAES; + return features; +#endif #if defined(__ARM_NEON__) || defined(__ARM_NEON) features |= CpuFeatureNEON; #endif diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h index 2806a29cf11..c8134964af6 100644 --- a/src/corelib/global/qsimd_p.h +++ b/src/corelib/global/qsimd_p.h @@ -145,17 +145,14 @@ #define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0) -#if defined(Q_PROCESSOR_ARM) -# define QT_COMPILER_SUPPORTS_HERE(x) (__ARM_FEATURE_ ## x) -# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 600 +#if defined(Q_PROCESSOR_ARM) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) +# define QT_COMPILER_SUPPORTS_HERE(x) ((__ARM_FEATURE_ ## x) || (__ ## x ## __) || QT_COMPILER_SUPPORTS(x)) +# if defined(Q_CC_GNU) /* GCC requires attributes for a function */ # define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x))) # else # define QT_FUNCTION_TARGET(x) # endif -# if !defined(__ARM_FEATURE_NEON) && defined(__ARM_NEON__) -# define __ARM_FEATURE_NEON // also support QT_COMPILER_SUPPORTS_HERE(NEON) -# endif #elif defined(Q_PROCESSOR_MIPS) # define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __) # define QT_FUNCTION_TARGET(x) @@ -173,6 +170,9 @@ # else # define QT_FUNCTION_TARGET(x) # endif +#elif defined(Q_PROCESSOR_ARM) +# define QT_COMPILER_SUPPORTS_HERE(x) ((__ARM_FEATURE_ ## x) || (__ ## x ## __)) +# define QT_FUNCTION_TARGET(x) #else # define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __) # define QT_FUNCTION_TARGET(x) @@ -259,17 +259,14 @@ QT_END_NAMESPACE #endif /* Q_PROCESSOR_X86 */ -// Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html -// This should be tweaked with an "upper version" of clang once we know which release fixes the -// issue. At that point we can rely on __ARM_FEATURE_CRC32 again. -#if defined(Q_CC_CLANG) && defined(Q_OS_DARWIN) && defined (__ARM_FEATURE_CRC32) -# undef __ARM_FEATURE_CRC32 -#endif - // NEON intrinsics // note: as of GCC 4.9, does not support function targets for ARM #if defined(__ARM_NEON) || defined(__ARM_NEON__) +#if defined(Q_CC_CLANG) +#define QT_FUNCTION_TARGET_STRING_NEON "neon" +#else #define QT_FUNCTION_TARGET_STRING_NEON "+neon" // unused: gcc doesn't support function targets on non-aarch64, and on Aarch64 NEON is always available. +#endif #ifndef __ARM_NEON__ // __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection. #define __ARM_NEON__ @@ -291,15 +288,30 @@ inline uint8_t vaddv_u8(uint8x8_t v8) #endif #endif -// AArch64/ARM64 -#if defined(Q_PROCESSOR_ARM_V8) && defined(__ARM_FEATURE_CRC32) -#if defined(Q_PROCESSOR_ARM_64) -// only available on aarch64 -#define QT_FUNCTION_TARGET_STRING_CRC32 "+crc" -#endif + +#if defined(Q_PROCESSOR_ARM) && defined(__ARM_FEATURE_CRC32) # include #endif +#if defined(Q_PROCESSOR_ARM_64) +#if defined(Q_CC_CLANG) +#define QT_FUNCTION_TARGET_STRING_AES "crypto" +#define QT_FUNCTION_TARGET_STRING_CRC32 "crc" +#elif defined(Q_CC_GNU) +#define QT_FUNCTION_TARGET_STRING_AES "+crypto" +#define QT_FUNCTION_TARGET_STRING_CRC32 "+crc" +#endif +#elif defined(Q_PROCESSOR_ARM_32) +#if defined(Q_CC_CLANG) +#define QT_FUNCTION_TARGET_STRING_AES "armv8-a,crypto" +#define QT_FUNCTION_TARGET_STRING_CRC32 "armv8-a,crc" +#elif defined(Q_CC_GNU) +#define QT_FUNCTION_TARGET_STRING_AES "arch=armv8-a+crypto" +#define QT_FUNCTION_TARGET_STRING_CRC32 "arch=armv8-a+crc" +#endif +#endif + + #ifdef __cplusplus #include diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 2221de14616..46917cfbe93 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -527,7 +527,8 @@ lt16: } #endif -#if defined(__ARM_FEATURE_CRYPTO) && !defined(QT_BOOTSTRAPPED) +#if defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED) +QT_FUNCTION_TARGET(AES) static size_t aeshash(const uchar *p, size_t len, size_t seed) noexcept { uint8x16_t key; @@ -669,10 +670,14 @@ size_t qHashBits(const void *p, size_t size, size_t seed) noexcept #ifdef AESHASH if (seed && qCpuHasFeature(AES) && qCpuHasFeature(SSE4_2)) return aeshash(reinterpret_cast(p), size, seed); -#elif defined(__ARM_FEATURE_CRYPTO) && !defined(QT_BOOTSTRAPPED) - // Do additional runtime check as Yocto hard enables Crypto extension for +#elif defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED) +# if defined(Q_OS_LINUX) + // Do specific runtime-only check as Yocto hard enables Crypto extension for // all armv8 configs if (seed && (qCpuFeatures() & CpuFeatureAES)) +# else + if (seed && qCpuHasFeature(AES)) +# endif return aeshash(reinterpret_cast(p), size, seed); #endif if (size <= QT_POINTER_SIZE)