]>
Commit | Line | Data |
---|---|---|
96203980 L |
1 | /* Test CPU feature data against /proc/cpuinfo. |
2 | This file is part of the GNU C Library. | |
dff8da6b | 3 | Copyright (C) 2012-2024 Free Software Foundation, Inc. |
96203980 L |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
16 | License along with the GNU C Library; if not, see | |
17 | <https://www.gnu.org/licenses/>. */ | |
18 | ||
e3e3eb0a | 19 | #include <cpu-features.h> |
96203980 L |
20 | #include <stdio.h> |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
e3e3eb0a | 23 | #include <stdbool.h> |
96203980 L |
24 | |
25 | static char *cpu_flags; | |
26 | ||
27 | /* Search for flags in /proc/cpuinfo and store line | |
28 | in cpu_flags. */ | |
29 | void | |
30 | get_cpuinfo (void) | |
31 | { | |
32 | FILE *f; | |
33 | char *line = NULL; | |
34 | size_t len = 0; | |
35 | ssize_t read; | |
36 | ||
37 | f = fopen ("/proc/cpuinfo", "r"); | |
38 | if (f == NULL) | |
39 | { | |
40 | printf ("cannot open /proc/cpuinfo\n"); | |
41 | exit (1); | |
42 | } | |
43 | ||
44 | while ((read = getline (&line, &len, f)) != -1) | |
45 | { | |
46 | if (strncmp (line, "flags", 5) == 0) | |
47 | { | |
48 | cpu_flags = strdup (line); | |
49 | break; | |
50 | } | |
51 | } | |
52 | fclose (f); | |
53 | free (line); | |
54 | } | |
55 | ||
56 | int | |
5f478eb0 | 57 | check_proc (const char *proc_name, const char *search_name, int flag, |
7c124e37 | 58 | int active, const char *name) |
96203980 L |
59 | { |
60 | int found = 0; | |
61 | ||
62 | printf ("Checking %s:\n", name); | |
5f478eb0 L |
63 | printf (" %s: %d\n", name, flag); |
64 | char *str = strstr (cpu_flags, search_name); | |
65 | if (str == NULL) | |
96203980 | 66 | { |
5f478eb0 L |
67 | /* If searching for " XXX " failed, try " XXX\n". */ |
68 | size_t len = strlen (search_name); | |
69 | char buffer[80]; | |
70 | if (len >= sizeof buffer) | |
71 | abort (); | |
72 | memcpy (buffer, search_name, len + 1); | |
73 | buffer[len - 1] = '\n'; | |
74 | str = strstr (cpu_flags, buffer); | |
96203980 | 75 | } |
5f478eb0 | 76 | if (str != NULL) |
96203980 L |
77 | found = 1; |
78 | printf (" cpuinfo (%s): %d\n", proc_name, found); | |
79 | ||
80 | if (found != flag) | |
5f478eb0 | 81 | { |
7c124e37 | 82 | if (found || active) |
5f478eb0 L |
83 | printf (" *** failure ***\n"); |
84 | else | |
85 | { | |
86 | printf (" *** missing in /proc/cpuinfo ***\n"); | |
87 | return 0; | |
88 | } | |
89 | } | |
96203980 L |
90 | |
91 | return (found != flag); | |
92 | } | |
93 | ||
94 | #define CHECK_PROC(str, name) \ | |
5f478eb0 L |
95 | check_proc (#str, " "#str" ", HAS_CPU_FEATURE (name), \ |
96 | CPU_FEATURE_USABLE (name), \ | |
97 | "HAS_CPU_FEATURE (" #name ")") | |
96203980 | 98 | |
743113d4 L |
99 | #define CHECK_PROC_ACTIVE(str, name) \ |
100 | check_proc (#str, " "#str" ", CPU_FEATURE_USABLE (name), \ | |
101 | CPU_FEATURE_USABLE (name), \ | |
102 | "CPU_FEATURE_USABLE (" #name ")") | |
103 | ||
96203980 L |
104 | static int |
105 | do_test (int argc, char **argv) | |
106 | { | |
107 | int fails = 0; | |
e3e3eb0a | 108 | const struct cpu_features *cpu_features = __get_cpu_features (); |
96203980 L |
109 | |
110 | get_cpuinfo (); | |
111 | fails += CHECK_PROC (acpi, ACPI); | |
112 | fails += CHECK_PROC (adx, ADX); | |
113 | fails += CHECK_PROC (apic, APIC); | |
114 | fails += CHECK_PROC (aes, AES); | |
115 | fails += CHECK_PROC (amx_bf16, AMX_BF16); | |
116 | fails += CHECK_PROC (amx_int8, AMX_INT8); | |
117 | fails += CHECK_PROC (amx_tile, AMX_TILE); | |
118 | fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES); | |
119 | fails += CHECK_PROC (avx, AVX); | |
120 | fails += CHECK_PROC (avx2, AVX2); | |
121 | fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS); | |
122 | fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW); | |
123 | fails += CHECK_PROC (avx512_bf16, AVX512_BF16); | |
124 | fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG); | |
125 | fails += CHECK_PROC (avx512ifma, AVX512_IFMA); | |
5f478eb0 | 126 | fails += CHECK_PROC (avx512vbmi, AVX512_VBMI); |
96203980 L |
127 | fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2); |
128 | fails += CHECK_PROC (avx512_vnni, AVX512_VNNI); | |
129 | fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT); | |
130 | fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ); | |
131 | fails += CHECK_PROC (avx512bw, AVX512BW); | |
132 | fails += CHECK_PROC (avx512cd, AVX512CD); | |
133 | fails += CHECK_PROC (avx512er, AVX512ER); | |
134 | fails += CHECK_PROC (avx512dq, AVX512DQ); | |
135 | fails += CHECK_PROC (avx512f, AVX512F); | |
136 | fails += CHECK_PROC (avx512pf, AVX512PF); | |
137 | fails += CHECK_PROC (avx512vl, AVX512VL); | |
138 | fails += CHECK_PROC (bmi1, BMI1); | |
139 | fails += CHECK_PROC (bmi2, BMI2); | |
140 | fails += CHECK_PROC (cldemote, CLDEMOTE); | |
141 | fails += CHECK_PROC (clflushopt, CLFLUSHOPT); | |
142 | fails += CHECK_PROC (clflush, CLFSH); | |
143 | fails += CHECK_PROC (clwb, CLWB); | |
144 | fails += CHECK_PROC (cmov, CMOV); | |
145 | fails += CHECK_PROC (cx16, CMPXCHG16B); | |
146 | fails += CHECK_PROC (cnxt_id, CNXT_ID); | |
147 | fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES); | |
148 | fails += CHECK_PROC (cx8, CX8); | |
149 | fails += CHECK_PROC (dca, DCA); | |
150 | fails += CHECK_PROC (de, DE); | |
151 | fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS); | |
5f478eb0 | 152 | fails += CHECK_PROC (dts, DS); |
96203980 L |
153 | fails += CHECK_PROC (ds_cpl, DS_CPL); |
154 | fails += CHECK_PROC (dtes64, DTES64); | |
155 | fails += CHECK_PROC (est, EIST); | |
156 | fails += CHECK_PROC (enqcmd, ENQCMD); | |
157 | fails += CHECK_PROC (erms, ERMS); | |
158 | fails += CHECK_PROC (f16c, F16C); | |
159 | fails += CHECK_PROC (fma, FMA); | |
160 | fails += CHECK_PROC (fma4, FMA4); | |
161 | fails += CHECK_PROC (fpu, FPU); | |
162 | fails += CHECK_PROC (fsgsbase, FSGSBASE); | |
163 | fails += CHECK_PROC (fsrm, FSRM); | |
164 | fails += CHECK_PROC (fxsr, FXSR); | |
165 | fails += CHECK_PROC (gfni, GFNI); | |
166 | fails += CHECK_PROC (hle, HLE); | |
167 | fails += CHECK_PROC (ht, HTT); | |
168 | fails += CHECK_PROC (hybrid, HYBRID); | |
e3e3eb0a AZ |
169 | if (cpu_features->basic.kind == arch_kind_intel) |
170 | { | |
171 | fails += CHECK_PROC (ibrs, IBRS_IBPB); | |
172 | fails += CHECK_PROC (stibp, STIBP); | |
173 | } | |
174 | else if (cpu_features->basic.kind == arch_kind_amd) | |
175 | { | |
176 | fails += CHECK_PROC (ibpb, AMD_IBPB); | |
94058f6c AJ |
177 | |
178 | /* The IBRS feature on AMD processors is reported using the Intel feature | |
179 | * on KVM guests (synthetic bit). In both cases the cpuinfo entry is the | |
180 | * same. */ | |
181 | if (HAS_CPU_FEATURE (IBRS_IBPB)) | |
182 | fails += CHECK_PROC (ibrs, IBRS_IBPB); | |
183 | else | |
184 | fails += CHECK_PROC (ibrs, AMD_IBRS); | |
e3e3eb0a AZ |
185 | fails += CHECK_PROC (stibp, AMD_STIBP); |
186 | } | |
96203980 L |
187 | fails += CHECK_PROC (ibt, IBT); |
188 | fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC); | |
189 | fails += CHECK_PROC (invpcid, INVPCID); | |
190 | fails += CHECK_PROC (flush_l1d, L1D_FLUSH); | |
191 | fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64); | |
192 | fails += CHECK_PROC (lm, LM); | |
193 | fails += CHECK_PROC (lwp, LWP); | |
194 | fails += CHECK_PROC (abm, LZCNT); | |
195 | fails += CHECK_PROC (mca, MCA); | |
196 | fails += CHECK_PROC (mce, MCE); | |
197 | fails += CHECK_PROC (md_clear, MD_CLEAR); | |
198 | fails += CHECK_PROC (mmx, MMX); | |
199 | fails += CHECK_PROC (monitor, MONITOR); | |
200 | fails += CHECK_PROC (movbe, MOVBE); | |
201 | fails += CHECK_PROC (movdiri, MOVDIRI); | |
202 | fails += CHECK_PROC (movdir64b, MOVDIR64B); | |
203 | fails += CHECK_PROC (mpx, MPX); | |
204 | fails += CHECK_PROC (msr, MSR); | |
205 | fails += CHECK_PROC (mtrr, MTRR); | |
206 | fails += CHECK_PROC (nx, NX); | |
207 | fails += CHECK_PROC (ospke, OSPKE); | |
208 | #if 0 | |
209 | /* NB: /proc/cpuinfo doesn't report this feature. */ | |
210 | fails += CHECK_PROC (osxsave, OSXSAVE); | |
211 | #endif | |
212 | fails += CHECK_PROC (pae, PAE); | |
213 | fails += CHECK_PROC (pdpe1gb, PAGE1GB); | |
214 | fails += CHECK_PROC (pat, PAT); | |
215 | fails += CHECK_PROC (pbe, PBE); | |
216 | fails += CHECK_PROC (pcid, PCID); | |
217 | fails += CHECK_PROC (pclmulqdq, PCLMULQDQ); | |
218 | fails += CHECK_PROC (pconfig, PCONFIG); | |
219 | fails += CHECK_PROC (pdcm, PDCM); | |
220 | fails += CHECK_PROC (pge, PGE); | |
221 | fails += CHECK_PROC (pks, PKS); | |
222 | fails += CHECK_PROC (pku, PKU); | |
223 | fails += CHECK_PROC (popcnt, POPCNT); | |
224 | fails += CHECK_PROC (3dnowprefetch, PREFETCHW); | |
db9b47e9 DD |
225 | #if 0 |
226 | /* NB: /proc/cpuinfo doesn't report this feature. */ | |
96203980 | 227 | fails += CHECK_PROC (prefetchwt1, PREFETCHWT1); |
db9b47e9 | 228 | #endif |
61a4425d L |
229 | #if 0 |
230 | /* NB: /proc/cpuinfo doesn't report this feature. */ | |
5ab25c88 | 231 | fails += CHECK_PROC (ptwrite, PTWRITE); |
61a4425d | 232 | #endif |
96203980 L |
233 | fails += CHECK_PROC (pse, PSE); |
234 | fails += CHECK_PROC (pse36, PSE_36); | |
235 | fails += CHECK_PROC (psn, PSN); | |
236 | fails += CHECK_PROC (rdpid, RDPID); | |
237 | fails += CHECK_PROC (rdrand, RDRAND); | |
238 | fails += CHECK_PROC (rdseed, RDSEED); | |
239 | fails += CHECK_PROC (rdt_a, RDT_A); | |
240 | fails += CHECK_PROC (cqm, RDT_M); | |
241 | fails += CHECK_PROC (rdtscp, RDTSCP); | |
242 | fails += CHECK_PROC (rtm, RTM); | |
243 | fails += CHECK_PROC (sdbg, SDBG); | |
244 | fails += CHECK_PROC (sep, SEP); | |
245 | fails += CHECK_PROC (serialize, SERIALIZE); | |
246 | fails += CHECK_PROC (sgx, SGX); | |
247 | fails += CHECK_PROC (sgx_lc, SGX_LC); | |
248 | fails += CHECK_PROC (sha_ni, SHA); | |
0b850186 | 249 | fails += CHECK_PROC (user_shstk, SHSTK); |
96203980 L |
250 | fails += CHECK_PROC (smap, SMAP); |
251 | fails += CHECK_PROC (smep, SMEP); | |
252 | fails += CHECK_PROC (smx, SMX); | |
253 | fails += CHECK_PROC (ss, SS); | |
e3e3eb0a AZ |
254 | if (cpu_features->basic.kind == arch_kind_intel) |
255 | fails += CHECK_PROC (ssbd, SSBD); | |
256 | else if (cpu_features->basic.kind == arch_kind_amd) | |
469761ea AZ |
257 | { |
258 | /* This feature is implemented in 2 different ways on AMD processors: | |
259 | newer systems provides AMD_SSBD (function 8000_0008, EBX[24]), | |
260 | while older system proviseds AMD_VIRT_SSBD (function 8000_008, | |
261 | EBX[25]). However for AMD_VIRT_SSBD, kernel shows both 'ssbd' | |
262 | and 'virt_ssbd' on /proc/cpuinfo; while for AMD_SSBD only 'ssbd' | |
263 | is provided. */ | |
264 | if (HAS_CPU_FEATURE (AMD_SSBD)) | |
265 | fails += CHECK_PROC (ssbd, AMD_SSBD); | |
266 | else if (HAS_CPU_FEATURE (AMD_VIRT_SSBD)) | |
267 | fails += CHECK_PROC (virt_ssbd, AMD_VIRT_SSBD); | |
268 | } | |
96203980 L |
269 | fails += CHECK_PROC (sse, SSE); |
270 | fails += CHECK_PROC (sse2, SSE2); | |
5f478eb0 | 271 | fails += CHECK_PROC (pni, SSE3); |
96203980 L |
272 | fails += CHECK_PROC (sse4_1, SSE4_1); |
273 | fails += CHECK_PROC (sse4_2, SSE4_2); | |
274 | fails += CHECK_PROC (sse4a, SSE4A); | |
275 | fails += CHECK_PROC (ssse3, SSSE3); | |
96203980 L |
276 | fails += CHECK_PROC (svm, SVM); |
277 | #ifdef __x86_64__ | |
278 | /* NB: SYSCALL_SYSRET is 64-bit only. */ | |
279 | fails += CHECK_PROC (syscall, SYSCALL_SYSRET); | |
280 | #endif | |
281 | fails += CHECK_PROC (tbm, TBM); | |
282 | fails += CHECK_PROC (tm, TM); | |
283 | fails += CHECK_PROC (tm2, TM2); | |
284 | fails += CHECK_PROC (intel_pt, TRACE); | |
285 | fails += CHECK_PROC (tsc, TSC); | |
286 | fails += CHECK_PROC (tsc_adjust, TSC_ADJUST); | |
5f478eb0 | 287 | fails += CHECK_PROC (tsc_deadline_timer, TSC_DEADLINE); |
96203980 L |
288 | fails += CHECK_PROC (tsxldtrk, TSXLDTRK); |
289 | fails += CHECK_PROC (umip, UMIP); | |
290 | fails += CHECK_PROC (vaes, VAES); | |
291 | fails += CHECK_PROC (vme, VME); | |
292 | fails += CHECK_PROC (vmx, VMX); | |
293 | fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ); | |
294 | fails += CHECK_PROC (waitpkg, WAITPKG); | |
295 | fails += CHECK_PROC (wbnoinvd, WBNOINVD); | |
296 | fails += CHECK_PROC (x2apic, X2APIC); | |
297 | fails += CHECK_PROC (xfd, XFD); | |
298 | fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1); | |
299 | fails += CHECK_PROC (xop, XOP); | |
300 | fails += CHECK_PROC (xsave, XSAVE); | |
301 | fails += CHECK_PROC (xsavec, XSAVEC); | |
302 | fails += CHECK_PROC (xsaveopt, XSAVEOPT); | |
303 | fails += CHECK_PROC (xsaves, XSAVES); | |
304 | fails += CHECK_PROC (xtpr, XTPRUPDCTRL); | |
305 | ||
743113d4 L |
306 | fails += CHECK_PROC_ACTIVE (fsgsbase, FSGSBASE); |
307 | ||
96203980 L |
308 | printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails); |
309 | ||
310 | return (fails != 0); | |
311 | } | |
312 | ||
313 | #include "../../../test-skeleton.c" |