Properly guard an include of <sys/auxv.h>.
[valgrind.git] / tests / arm64_features.c
blobebfc774187203739f0c9bf145817c50cf8d492b8
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #if !defined(__APPLE__) && defined(VGA_arm64)
5 #include <sys/auxv.h>
6 #endif
8 // This file determines arm64 features a processor supports.
9 // Arm processors do not have a x86-like cpuinfo instruction. Instead the
10 // getauxval() syscall is used with capabilities parameters: getauxval(AT_HWCAP)
11 // and getauxval(AT_HWCAP2).
13 // We return:
14 // - 0 if the machine has the asked-for feature.
15 // - 1 if the machine doesn't have the asked-for feature.
16 // - 2 if the asked-for feature isn't recognised (this will always be the case
17 // for any feature if run on a non-arm64 machine).
18 // - 3 if there was a usage error (it also prints an error message).
19 #define FEATURE_PRESENT 0
20 #define FEATURE_NOT_PRESENT 1
21 #define UNRECOGNISED_FEATURE 2
22 #define USAGE_ERROR 3
24 #define False 0
25 #define True 1
26 typedef int Bool;
28 #if defined(VGA_arm64)
30 // The processor's capabilities/features are returned by getauxval() as an
31 // unsigned long with each bit representing a capability/feature.
32 #define HWCAP_FP (1 << 0)
33 #define HWCAP_ASIMD (1 << 1)
34 #define HWCAP_EVTSTRM (1 << 2)
35 #define HWCAP_AES (1 << 3)
36 #define HWCAP_PMULL (1 << 4)
37 #define HWCAP_SHA1 (1 << 5)
38 #define HWCAP_SHA2 (1 << 6)
39 #define HWCAP_CRC32 (1 << 7)
40 #define HWCAP_ATOMICS (1 << 8)
41 #define HWCAP_FPHP (1 << 9)
42 #define HWCAP_ASIMDHP (1 << 10)
43 #define HWCAP_CPUID (1 << 11)
44 #define HWCAP_ASIMDRDM (1 << 12)
45 #define HWCAP_JSCVT (1 << 13)
46 #define HWCAP_FCMA (1 << 14)
47 #define HWCAP_LRCPC (1 << 15)
48 #define HWCAP_DCPOP (1 << 16)
49 #define HWCAP_SHA3 (1 << 17)
50 #define HWCAP_SM3 (1 << 18)
51 #define HWCAP_SM4 (1 << 19)
52 #define HWCAP_ASIMDDP (1 << 20)
53 #define HWCAP_SHA512 (1 << 21)
54 #define HWCAP_SVE (1 << 22)
55 #define HWCAP_ASIMDFHM (1 << 23)
56 #define HWCAP_DIT (1 << 24)
57 #define HWCAP_USCAT (1 << 25)
58 #define HWCAP_ILRCPC (1 << 26)
59 #define HWCAP_FLAGM (1 << 27)
60 #define HWCAP_SSBS (1 << 28)
61 #define HWCAP_SB (1 << 29)
62 #define HWCAP_PACA (1 << 30)
63 #define HWCAP_PACG (1UL << 31)
65 #define HWCAP2_DCPODP (1 << 0)
66 #define HWCAP2_SVE2 (1 << 1)
67 #define HWCAP2_SVEAES (1 << 2)
68 #define HWCAP2_SVEPMULL (1 << 3)
69 #define HWCAP2_SVEBITPERM (1 << 4)
70 #define HWCAP2_SVESHA3 (1 << 5)
71 #define HWCAP2_SVESM4 (1 << 6)
72 #define HWCAP2_FLAGM2 (1 << 7)
73 #define HWCAP2_FRINT (1 << 8)
75 unsigned long hwcaps[] = {
76 HWCAP_FP, HWCAP_ASIMD, HWCAP_EVTSTRM, HWCAP_AES, HWCAP_PMULL,
77 HWCAP_SHA1, HWCAP_SHA2, HWCAP_CRC32, HWCAP_ATOMICS, HWCAP_FPHP,
78 HWCAP_ASIMDHP,HWCAP_CPUID, HWCAP_ASIMDRDM,HWCAP_JSCVT, HWCAP_FCMA,
79 HWCAP_LRCPC, HWCAP_DCPOP, HWCAP_SHA3, HWCAP_SM3, HWCAP_SM4,
80 HWCAP_ASIMDDP,HWCAP_SHA512, HWCAP_SVE, HWCAP_ASIMDFHM,HWCAP_DIT,
81 HWCAP_USCAT, HWCAP_ILRCPC, HWCAP_FLAGM, HWCAP_SSBS, HWCAP_SB,
82 HWCAP_PACA, HWCAP_PACG, 0ul};
84 unsigned long hwcaps2[] = {
85 HWCAP2_DCPODP, HWCAP2_SVE2, HWCAP2_SVEAES, HWCAP2_SVEPMULL,
86 HWCAP2_SVEBITPERM, HWCAP2_SVESHA3, HWCAP2_SVESM4, HWCAP2_FLAGM2,
87 HWCAP2_FRINT, 0ul};
89 typedef struct
91 char name[16];
92 unsigned long cap_bit;
93 } capability;
95 capability capabilities[] = {
96 {"fp", HWCAP_FP}, {"asimd", HWCAP_ASIMD},
97 {"evtstrm", HWCAP_EVTSTRM}, {"aes", HWCAP_AES},
98 {"pmull", HWCAP_PMULL}, {"sha1", HWCAP_SHA1},
99 {"sha2", HWCAP_SHA2}, {"crc32", HWCAP_CRC32},
100 {"atomics", HWCAP_ATOMICS}, {"fphp", HWCAP_FPHP},
101 {"asimdhp", HWCAP_ASIMDHP}, {"cpuid", HWCAP_CPUID},
102 {"asimdrdm", HWCAP_ASIMDRDM}, {"jscvt", HWCAP_JSCVT},
103 {"fcma", HWCAP_FCMA}, {"lrcpc", HWCAP_LRCPC},
104 {"dcpop", HWCAP_DCPOP}, {"sha3", HWCAP_SHA3},
105 {"sm3", HWCAP_SM3}, {"sm4", HWCAP_SM4},
106 {"asimddp", HWCAP_ASIMDDP}, {"sha512", HWCAP_SHA512},
107 {"sve", HWCAP_SVE}, {"asimdfhm", HWCAP_ASIMDFHM},
108 {"dit", HWCAP_DIT}, {"uscat", HWCAP_USCAT},
109 {"ilrcpc", HWCAP_ILRCPC}, {"flagm", HWCAP_FLAGM},
110 {"ssbs", HWCAP_SSBS}, {"sb", HWCAP_SB},
111 {"paca", HWCAP_PACA}, {"pacg", HWCAP_PACG},
112 {"", 0ul}
115 capability capabilities2[] = {
116 {"dcpodp", HWCAP2_DCPODP}, {"sve2", HWCAP2_SVE2},
117 {"sveaes", HWCAP2_SVEAES}, {"svepmull", HWCAP2_SVEPMULL},
118 {"svebitperm", HWCAP2_SVEBITPERM}, {"svesha3", HWCAP2_SVESHA3},
119 {"svesm4", HWCAP2_SVESM4}, {"flagm2", HWCAP2_FLAGM2},
120 {"frint", HWCAP2_FRINT}, {"", 0ul}
123 typedef struct
125 unsigned long hwcap;
126 unsigned long hwcap2;
127 } hwc;
129 #define CAPABILITIES_SEARCH_LOOP(hwcversion) \
130 for (int i = 0; capabilities ## hwcversion[i].cap_bit; ++i) \
131 if (strcmp(name, capabilities ## hwcversion[i].name) == 0) { \
132 caps->hwcap ## hwcversion = capabilities ## hwcversion[i].cap_bit; \
133 return True; \
136 static Bool get_feature_from_string(const char *name, hwc *caps)
138 caps->hwcap = caps->hwcap2 = 0;
139 CAPABILITIES_SEARCH_LOOP()
140 CAPABILITIES_SEARCH_LOOP(2)
141 return False;
144 static int go(const char* feature_name)
146 hwc hw;
147 unsigned long hwcap = getauxval(AT_HWCAP);
148 unsigned long hwcap2 = getauxval(AT_HWCAP2);
150 if (!get_feature_from_string(feature_name, &hw))
151 return UNRECOGNISED_FEATURE;
153 if ((hw.hwcap & hwcap) || (hw.hwcap2 & hwcap2))
154 return FEATURE_PRESENT;
156 return FEATURE_NOT_PRESENT;
159 #else
161 static Bool go(const char* feature_name)
163 // Feature not recognised (non-arm64 machine!)
164 return UNRECOGNISED_FEATURE;
167 #endif // defined(VGA_arm64)
170 //---------------------------------------------------------------------------
171 // main
172 //---------------------------------------------------------------------------
173 int main(int argc, char **argv)
175 if (argc != 2) {
176 fprintf(stderr, "usage: arm64_features <feature>\n");
177 exit(USAGE_ERROR);
179 return go(argv[1]);