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