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