(root)/
glibc-2.38/
sysdeps/
x86/
tst-cpu-features-cpuinfo.c
       1  /* Test CPU feature data against /proc/cpuinfo.
       2     This file is part of the GNU C Library.
       3     Copyright (C) 2012-2023 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
      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
      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  #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  
     104  static int
     105  do_test (int argc, char **argv)
     106  {
     107    int fails = 0;
     108    const struct cpu_features *cpu_features = __get_cpu_features ();
     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);
     126    fails += CHECK_PROC (avx512vbmi, AVX512_VBMI);
     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);
     152    fails += CHECK_PROC (dts, DS);
     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);
     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);
     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);
     185        fails += CHECK_PROC (stibp, AMD_STIBP);
     186      }
     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);
     225  #if 0
     226    /* NB: /proc/cpuinfo doesn't report this feature.  */
     227    fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
     228  #endif
     229  #if 0
     230    /* NB: /proc/cpuinfo doesn't report this feature.  */
     231    fails += CHECK_PROC (ptwrite, PTWRITE);
     232  #endif
     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);
     249    fails += CHECK_PROC (shstk, SHSTK);
     250    fails += CHECK_PROC (smap, SMAP);
     251    fails += CHECK_PROC (smep, SMEP);
     252    fails += CHECK_PROC (smx, SMX);
     253    fails += CHECK_PROC (ss, SS);
     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)
     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      }
     269    fails += CHECK_PROC (sse, SSE);
     270    fails += CHECK_PROC (sse2, SSE2);
     271    fails += CHECK_PROC (pni, SSE3);
     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);
     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);
     287    fails += CHECK_PROC (tsc_deadline_timer, TSC_DEADLINE);
     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  
     306    fails += CHECK_PROC_ACTIVE (fsgsbase, FSGSBASE);
     307  
     308    printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
     309  
     310    return (fails != 0);
     311  }
     312  
     313  #include "../../../test-skeleton.c"