@@ -948,6 +948,8 @@ _Bool __aarch64_have_lse_atomics
948
948
#if defined(__has_include )
949
949
#if __has_include (< sys /auxv .h > )
950
950
#include <sys/auxv.h>
951
+ #define HAVE_SYS_AUXV
952
+ #endif
951
953
952
954
#if __has_include (< sys /ifunc .h > )
953
955
#include <sys/ifunc.h>
@@ -961,6 +963,8 @@ typedef struct __ifunc_arg_t {
961
963
962
964
#if __has_include (< asm /hwcap .h > )
963
965
#include <asm/hwcap.h>
966
+ #include HAVE_SYS_HWCAP
967
+ #endif
964
968
965
969
#if defined(__ANDROID__ )
966
970
#include <string.h>
@@ -997,6 +1001,9 @@ typedef struct __ifunc_arg_t {
997
1001
#ifndef HWCAP_SHA2
998
1002
#define HWCAP_SHA2 (1 << 6)
999
1003
#endif
1004
+ #ifndef HWCAP_CRC32
1005
+ #define HWCAP_CRC32 (1 << 7)
1006
+ #endif
1000
1007
#ifndef HWCAP_ATOMICS
1001
1008
#define HWCAP_ATOMICS (1 << 8)
1002
1009
#endif
@@ -1149,6 +1156,7 @@ typedef struct __ifunc_arg_t {
1149
1156
if (__system_property_get("ro.arch", arch) > 0 && \
1150
1157
strncmp(arch, "exynos9810", sizeof("exynos9810") - 1) == 0)
1151
1158
1159
+ #if !defined(__APPLE__ )
1152
1160
static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics (void ) {
1153
1161
#if defined(__FreeBSD__ )
1154
1162
unsigned long hwcap ;
@@ -1162,7 +1170,7 @@ static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) {
1162
1170
zx_status_t status = _zx_system_get_features (ZX_FEATURE_KIND_CPU , & features );
1163
1171
__aarch64_have_lse_atomics =
1164
1172
status == ZX_OK && (features & ZX_ARM64_FEATURE_ISA_ATOMICS ) != 0 ;
1165
- #else
1173
+ #elif defined( HAVE_SYS_AUXV )
1166
1174
unsigned long hwcap = getauxval (AT_HWCAP );
1167
1175
_Bool result = (hwcap & HWCAP_ATOMICS ) != 0 ;
1168
1176
#if defined(__ANDROID__ )
@@ -1180,8 +1188,11 @@ static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) {
1180
1188
}
1181
1189
#endif // defined(__ANDROID__)
1182
1190
__aarch64_have_lse_atomics = result ;
1191
+ #else
1192
+ #error No support for checking for lse atomics on this platfrom yet.
1183
1193
#endif // defined(__FreeBSD__)
1184
1194
}
1195
+ #endif // !defined(__APPLE__)
1185
1196
1186
1197
#if !defined(DISABLE_AARCH64_FMV )
1187
1198
// CPUFeatures must correspond to the same AArch64 features in
@@ -1259,6 +1270,76 @@ struct {
1259
1270
// As features grows new fields could be added
1260
1271
} __aarch64_cpu_features __attribute__((visibility ("hidden" ), nocommon ));
1261
1272
1273
+ #if defined(__APPLE__ )
1274
+ #include <TargetConditionals.h>
1275
+ #if TARGET_OS_OSX || TARGET_OS_IPHONE
1276
+ #include <dispatch/dispatch.h>
1277
+ #include <sys/sysctl.h>
1278
+
1279
+ static bool isKnownAndSupported (const char * name ) {
1280
+ int32_t val = 0 ;
1281
+ size_t size = sizeof (val );
1282
+ if (sysctlbyname (name , & val , & size , NULL , 0 ))
1283
+ return false;
1284
+ return val ;
1285
+ }
1286
+
1287
+ void __init_cpu_features_resolver (void ) {
1288
+ // On Darwin platforms, this may be called concurrently by multiple threads
1289
+ // because the resolvers that use it are called lazily at runtime (unlike on
1290
+ // ELF platforms, where IFuncs are resolved serially at load time). This
1291
+ // function's effect on __aarch64_cpu_features should be idempotent, but even
1292
+ // so we need dispatch_once to resolve the race condition. Dispatch is
1293
+ // available through libSystem, which we need anyway for the sysctl, so this
1294
+ // does not add a new dependency.
1295
+
1296
+ static dispatch_once_t onceToken = 0 ;
1297
+ dispatch_once (& onceToken , ^{
1298
+ // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
1299
+ static struct {
1300
+ const char * sysctl_name ;
1301
+ enum CPUFeatures feature ;
1302
+ } features [] = {
1303
+ {"hw.optional.arm.FEAT_FlagM" , FEAT_FLAGM },
1304
+ {"hw.optional.arm.FEAT_FlagM2" , FEAT_FLAGM2 },
1305
+ {"hw.optional.arm.FEAT_FHM" , FEAT_FP16FML },
1306
+ {"hw.optional.arm.FEAT_DotProd" , FEAT_DOTPROD },
1307
+ {"hw.optional.arm.FEAT_RDM" , FEAT_RDM },
1308
+ {"hw.optional.arm.FEAT_LSE" , FEAT_LSE },
1309
+ {"hw.optional.floatingpoint" , FEAT_FP },
1310
+ {"hw.optional.AdvSIMD" , FEAT_SIMD },
1311
+ {"hw.optional.armv8_crc32" , FEAT_CRC },
1312
+ {"hw.optional.arm.FEAT_SHA1" , FEAT_SHA1 },
1313
+ {"hw.optional.arm.FEAT_SHA256" , FEAT_SHA2 },
1314
+ {"hw.optional.arm.FEAT_SHA3" , FEAT_SHA3 },
1315
+ {"hw.optional.arm.FEAT_AES" , FEAT_AES },
1316
+ {"hw.optional.arm.FEAT_PMULL" , FEAT_PMULL },
1317
+ {"hw.optional.arm.FEAT_FP16" , FEAT_FP16 },
1318
+ {"hw.optional.arm.FEAT_DIT" , FEAT_DIT },
1319
+ {"hw.optional.arm.FEAT_DPB" , FEAT_DPB },
1320
+ {"hw.optional.arm.FEAT_DPB2" , FEAT_DPB2 },
1321
+ {"hw.optional.arm.FEAT_JSCVT" , FEAT_JSCVT },
1322
+ {"hw.optional.arm.FEAT_FCMA" , FEAT_FCMA },
1323
+ {"hw.optional.arm.FEAT_LRCPC" , FEAT_RCPC },
1324
+ {"hw.optional.arm.FEAT_LRCPC2" , FEAT_RCPC2 },
1325
+ {"hw.optional.arm.FEAT_FRINTTS" , FEAT_FRINTTS },
1326
+ {"hw.optional.arm.FEAT_I8MM" , FEAT_I8MM },
1327
+ {"hw.optional.arm.FEAT_BF16" , FEAT_BF16 },
1328
+ {"hw.optional.arm.FEAT_SB" , FEAT_SB },
1329
+ {"hw.optional.arm.FEAT_SPECRES" , FEAT_PREDRES },
1330
+ {"hw.optional.arm.FEAT_SSBS" , FEAT_SSBS2 },
1331
+ {"hw.optional.arm.FEAT_BTI" , FEAT_BTI },
1332
+ };
1333
+
1334
+ for (size_t I = 0 , E = sizeof (features ) / sizeof (features [0 ]); I != E ; ++ I )
1335
+ if (isKnownAndSupported (features [I ].sysctl_name ))
1336
+ __aarch64_cpu_features .features |= (1ULL << features [I ].feature );
1337
+
1338
+ __aarch64_cpu_features .features |= (1ULL << FEAT_INIT );
1339
+ });
1340
+ }
1341
+ #endif // TARGET_OS_OSX || TARGET_OS_IPHONE
1342
+ #else // defined(__APPLE__)
1262
1343
static void __init_cpu_features_constructor (unsigned long hwcap ,
1263
1344
const __ifunc_arg_t * arg ) {
1264
1345
#define setCPUFeature (F ) __aarch64_cpu_features.features |= 1ULL << F
@@ -1467,8 +1548,8 @@ void __init_cpu_features_resolver(unsigned long hwcap,
1467
1548
}
1468
1549
1469
1550
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features (void ) {
1470
- unsigned long hwcap ;
1471
- unsigned long hwcap2 ;
1551
+ unsigned long hwcap = 0 ;
1552
+ unsigned long hwcap2 = 0 ;
1472
1553
// CPU features already initialized.
1473
1554
if (__aarch64_cpu_features .features )
1474
1555
return ;
@@ -1478,14 +1559,16 @@ void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
1478
1559
res |= elf_aux_info (AT_HWCAP2 , & hwcap2 , sizeof hwcap2 );
1479
1560
if (res )
1480
1561
return ;
1481
- #else
1562
+ #elif defined( HAVE_SYS_AUXV )
1482
1563
#if defined(__ANDROID__ )
1483
1564
// Don't set any CPU features,
1484
1565
// detection could be wrong on Exynos 9810.
1485
1566
IF_EXYNOS9810 return ;
1486
1567
#endif // defined(__ANDROID__)
1487
1568
hwcap = getauxval (AT_HWCAP );
1488
1569
hwcap2 = getauxval (AT_HWCAP2 );
1570
+ #else
1571
+ #error No support for checking hwcap on this platform yet.
1489
1572
#endif // defined(__FreeBSD__)
1490
1573
__ifunc_arg_t arg ;
1491
1574
arg ._size = sizeof (__ifunc_arg_t );
@@ -1497,8 +1580,7 @@ void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
1497
1580
#undef setCPUFeature
1498
1581
#undef IF_EXYNOS9810
1499
1582
}
1583
+ #endif // defined(__APPLE__)
1500
1584
#endif // !defined(DISABLE_AARCH64_FMV)
1501
1585
#endif // defined(__has_include)
1502
- #endif // __has_include(<sys/auxv.h>)
1503
- #endif // __has_include(<asm/hwcap.h>)
1504
1586
#endif // defined(__aarch64__)
0 commit comments