Add runtime ARM64 AES check

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ø <tor.arne.vestbo@qt.io>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2021-04-21 11:33:44 +02:00 committed by Tor Arne Vestbø
parent 5b64e5950c
commit fe6dc9dc85
7 changed files with 143 additions and 59 deletions

View File

@ -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

View File

@ -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__

View File

@ -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(

View File

@ -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"
},
{

View File

@ -54,22 +54,19 @@
# if !defined(Q_CC_GNU)
# include <intrin.h>
# 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)
# include <sys/auxv.h>
# if defined(Q_PROCESSOR_ARM64)
# include <processthreadsapi.h>
# 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 <sys/auxv.h>
// the kernel header definitions for HWCAP_*
// (the ones we need/may need anyway)
// copied from <asm/hwcap.h> (ARM)
#define HWCAP_CRUNCH 1024
#define HWCAP_THUMBEE 2048
#define HWCAP_NEON 4096
#define HWCAP_VFPv3 8192
#define HWCAP_VFPv3D16 16384
// copied from <asm/hwcap.h> (ARM):
#define HWCAP2_AES (1 << 0)
@ -85,6 +82,8 @@
#elif defined(Q_CC_GHS)
# include <INTEGRITY_types.h>
#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM)
# include <sys/sysctl.h>
#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

View File

@ -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 <arm_acle.h>
#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 <qatomic.h>

View File

@ -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<const uchar *>(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<const uchar *>(p), size, seed);
#endif
if (size <= QT_POINTER_SIZE)