summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-04-21 11:33:44 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-05-20 18:31:05 +0000
commitfe6dc9dc8549cd9de7a0ddb04d921fd3263b51df (patch)
tree88c2121c20c9c6290bd1cbb7b50e1b6c0eb05175 /src/corelib
parent5b64e5950cf984abb7d47e0802bcb4b5a21e06fa (diff)
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>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qsimd.cpp41
-rw-r--r--src/corelib/global/qsimd_p.h46
-rw-r--r--src/corelib/tools/qhash.cpp11
3 files changed, 66 insertions, 32 deletions
diff --git a/src/corelib/global/qsimd.cpp b/src/corelib/global/qsimd.cpp
index 37d6dd4e14..025c50b6e8 100644
--- a/src/corelib/global/qsimd.cpp
+++ b/src/corelib/global/qsimd.cpp
@@ -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)
+# 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>
-#endif
// 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)
@@ -84,7 +81,9 @@
#define AT_HWCAP2 26 /* extension of AT_HWCAP */
#elif defined(Q_CC_GHS)
-#include <INTEGRITY_types.h>
+# 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
diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h
index 2806a29cf1..c8134964af 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) && defined(__ARM_FEATURE_CRC32)
+# include <arm_acle.h>
+#endif
+
#if defined(Q_PROCESSOR_ARM_64)
-// only available on aarch64
+#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
-# include <arm_acle.h>
+#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>
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 2221de1461..46917cfbe9 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<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)