tst-cpu-features-cpuinfo.c 10 KB

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