apple.inc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include <TargetConditionals.h>
  2. #if TARGET_OS_OSX || TARGET_OS_IPHONE
  3. #include <sys/sysctl.h>
  4. #if __has_include(<arm/cpu_capabilities_public.h>)
  5. #include <arm/cpu_capabilities_public.h>
  6. #define HAS_CPU_CAPABILITIES_PUBLIC_H 1
  7. // FB13964283 - A few of these didn't make it into the public SDK yet.
  8. #ifndef CAP_BIT_FEAT_SME
  9. #define CAP_BIT_FEAT_SME 40
  10. #endif
  11. #ifndef CAP_BIT_FEAT_SME2
  12. #define CAP_BIT_FEAT_SME2 41
  13. #endif
  14. #ifndef CAP_BIT_FEAT_SME_F64F64
  15. #define CAP_BIT_FEAT_SME_F64F64 42
  16. #endif
  17. #ifndef CAP_BIT_FEAT_SME_I16I64
  18. #define CAP_BIT_FEAT_SME_I16I64 43
  19. #endif
  20. #endif
  21. static bool isKnownAndSupported(const char *name) {
  22. int32_t val = 0;
  23. size_t size = sizeof(val);
  24. if (sysctlbyname(name, &val, &size, NULL, 0))
  25. return false;
  26. return val;
  27. }
  28. static uint64_t deriveImplicitFeatures(uint64_t features) {
  29. // FEAT_SSBS2 implies FEAT_SSBS
  30. if ((1ULL << FEAT_SSBS2) & features)
  31. features |= (1ULL << FEAT_SSBS);
  32. // FEAT_FP is always enabled
  33. features |= (1ULL << FEAT_FP);
  34. features |= (1ULL << FEAT_INIT);
  35. return features;
  36. }
  37. void __init_cpu_features_resolver(void) {
  38. // On Darwin platforms, this may be called concurrently by multiple threads
  39. // because the resolvers that use it are called lazily at runtime (unlike on
  40. // ELF platforms, where IFuncs are resolved serially at load time). This
  41. // function's effect on __aarch64_cpu_features must be idempotent.
  42. if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
  43. return;
  44. uint64_t features = 0;
  45. #ifdef HAS_CPU_CAPABILITIES_PUBLIC_H
  46. uint8_t feats_bitvec[(CAP_BIT_NB + 7) / 8] = {0};
  47. size_t len = sizeof(feats_bitvec);
  48. // When hw.optional.arm.feats is available (macOS 15.0+, iOS 18.0+), use the
  49. // fast path to get all the feature bits, otherwise fall back to the slow
  50. // ~20-something sysctls path.
  51. if (!sysctlbyname("hw.optional.arm.caps", &feats_bitvec, &len, 0, 0)) {
  52. #define CHECK_BIT(FROM, TO) \
  53. do { \
  54. if (feats_bitvec[FROM / 8] & (1u << ((FROM) & 7))) { \
  55. features |= (1ULL << TO); \
  56. } \
  57. } while (0)
  58. CHECK_BIT(CAP_BIT_FEAT_FlagM, FEAT_FLAGM);
  59. CHECK_BIT(CAP_BIT_FEAT_FlagM2, FEAT_FLAGM2);
  60. CHECK_BIT(CAP_BIT_FEAT_FHM, FEAT_FP16FML);
  61. CHECK_BIT(CAP_BIT_FEAT_DotProd, FEAT_DOTPROD);
  62. CHECK_BIT(CAP_BIT_FEAT_SHA3, FEAT_SHA3);
  63. CHECK_BIT(CAP_BIT_FEAT_RDM, FEAT_RDM);
  64. CHECK_BIT(CAP_BIT_FEAT_LSE, FEAT_LSE);
  65. CHECK_BIT(CAP_BIT_FEAT_SHA256, FEAT_SHA2);
  66. CHECK_BIT(CAP_BIT_FEAT_SHA1, FEAT_SHA1);
  67. CHECK_BIT(CAP_BIT_FEAT_AES, FEAT_AES);
  68. CHECK_BIT(CAP_BIT_FEAT_PMULL, FEAT_PMULL);
  69. CHECK_BIT(CAP_BIT_FEAT_SPECRES, FEAT_PREDRES);
  70. CHECK_BIT(CAP_BIT_FEAT_SB, FEAT_SB);
  71. CHECK_BIT(CAP_BIT_FEAT_FRINTTS, FEAT_FRINTTS);
  72. CHECK_BIT(CAP_BIT_FEAT_LRCPC, FEAT_RCPC);
  73. CHECK_BIT(CAP_BIT_FEAT_LRCPC2, FEAT_RCPC2);
  74. CHECK_BIT(CAP_BIT_FEAT_FCMA, FEAT_FCMA);
  75. CHECK_BIT(CAP_BIT_FEAT_JSCVT, FEAT_JSCVT);
  76. CHECK_BIT(CAP_BIT_FEAT_DPB, FEAT_DPB);
  77. CHECK_BIT(CAP_BIT_FEAT_DPB2, FEAT_DPB2);
  78. CHECK_BIT(CAP_BIT_FEAT_BF16, FEAT_BF16);
  79. CHECK_BIT(CAP_BIT_FEAT_I8MM, FEAT_I8MM);
  80. CHECK_BIT(CAP_BIT_FEAT_DIT, FEAT_DIT);
  81. CHECK_BIT(CAP_BIT_FEAT_FP16, FEAT_FP16);
  82. CHECK_BIT(CAP_BIT_FEAT_SSBS, FEAT_SSBS2);
  83. CHECK_BIT(CAP_BIT_FEAT_BTI, FEAT_BTI);
  84. CHECK_BIT(CAP_BIT_AdvSIMD, FEAT_SIMD);
  85. CHECK_BIT(CAP_BIT_CRC32, FEAT_CRC);
  86. CHECK_BIT(CAP_BIT_FEAT_SME, FEAT_SME);
  87. CHECK_BIT(CAP_BIT_FEAT_SME2, FEAT_SME2);
  88. CHECK_BIT(CAP_BIT_FEAT_SME_F64F64, FEAT_SME_F64);
  89. CHECK_BIT(CAP_BIT_FEAT_SME_I16I64, FEAT_SME_I64);
  90. features = deriveImplicitFeatures(features);
  91. __atomic_store(&__aarch64_cpu_features.features, &features,
  92. __ATOMIC_RELAXED);
  93. return;
  94. }
  95. #endif
  96. // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
  97. static const struct {
  98. const char *sysctl_name;
  99. enum CPUFeatures feature;
  100. } feature_checks[] = {
  101. {"hw.optional.arm.FEAT_FlagM", FEAT_FLAGM},
  102. {"hw.optional.arm.FEAT_FlagM2", FEAT_FLAGM2},
  103. {"hw.optional.arm.FEAT_FHM", FEAT_FP16FML},
  104. {"hw.optional.arm.FEAT_DotProd", FEAT_DOTPROD},
  105. {"hw.optional.arm.FEAT_RDM", FEAT_RDM},
  106. {"hw.optional.arm.FEAT_LSE", FEAT_LSE},
  107. {"hw.optional.AdvSIMD", FEAT_SIMD},
  108. {"hw.optional.armv8_crc32", FEAT_CRC},
  109. {"hw.optional.arm.FEAT_SHA1", FEAT_SHA1},
  110. {"hw.optional.arm.FEAT_SHA256", FEAT_SHA2},
  111. {"hw.optional.arm.FEAT_SHA3", FEAT_SHA3},
  112. {"hw.optional.arm.FEAT_AES", FEAT_AES},
  113. {"hw.optional.arm.FEAT_PMULL", FEAT_PMULL},
  114. {"hw.optional.arm.FEAT_FP16", FEAT_FP16},
  115. {"hw.optional.arm.FEAT_DIT", FEAT_DIT},
  116. {"hw.optional.arm.FEAT_DPB", FEAT_DPB},
  117. {"hw.optional.arm.FEAT_DPB2", FEAT_DPB2},
  118. {"hw.optional.arm.FEAT_JSCVT", FEAT_JSCVT},
  119. {"hw.optional.arm.FEAT_FCMA", FEAT_FCMA},
  120. {"hw.optional.arm.FEAT_LRCPC", FEAT_RCPC},
  121. {"hw.optional.arm.FEAT_LRCPC2", FEAT_RCPC2},
  122. {"hw.optional.arm.FEAT_FRINTTS", FEAT_FRINTTS},
  123. {"hw.optional.arm.FEAT_I8MM", FEAT_I8MM},
  124. {"hw.optional.arm.FEAT_BF16", FEAT_BF16},
  125. {"hw.optional.arm.FEAT_SB", FEAT_SB},
  126. {"hw.optional.arm.FEAT_SPECRES", FEAT_PREDRES},
  127. {"hw.optional.arm.FEAT_SSBS", FEAT_SSBS2},
  128. {"hw.optional.arm.FEAT_BTI", FEAT_BTI},
  129. };
  130. for (size_t I = 0, E = sizeof(feature_checks) / sizeof(feature_checks[0]);
  131. I != E; ++I)
  132. if (isKnownAndSupported(feature_checks[I].sysctl_name))
  133. features |= (1ULL << feature_checks[I].feature);
  134. features = deriveImplicitFeatures(features);
  135. __atomic_store(&__aarch64_cpu_features.features, &features,
  136. __ATOMIC_RELAXED);
  137. }
  138. #endif // TARGET_OS_OSX || TARGET_OS_IPHONE