LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - cpuid-deps.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 26 31 83.9 %
Date: 2022-03-28 15:32:58 Functions: 4 4 100.0 %
Branches: 8 14 57.1 %

           Branch data     Line data    Source code
       1                 :            : /* Declare dependencies between CPUIDs */
       2                 :            : #include <linux/kernel.h>
       3                 :            : #include <linux/init.h>
       4                 :            : #include <linux/module.h>
       5                 :            : #include <asm/cpufeature.h>
       6                 :            : 
       7                 :            : struct cpuid_dep {
       8                 :            :         unsigned int    feature;
       9                 :            :         unsigned int    depends;
      10                 :            : };
      11                 :            : 
      12                 :            : /*
      13                 :            :  * Table of CPUID features that depend on others.
      14                 :            :  *
      15                 :            :  * This only includes dependencies that can be usefully disabled, not
      16                 :            :  * features part of the base set (like FPU).
      17                 :            :  *
      18                 :            :  * Note this all is not __init / __initdata because it can be
      19                 :            :  * called from cpu hotplug. It shouldn't do anything in this case,
      20                 :            :  * but it's difficult to tell that to the init reference checker.
      21                 :            :  */
      22                 :            : static const struct cpuid_dep cpuid_deps[] = {
      23                 :            :         { X86_FEATURE_FXSR,                     X86_FEATURE_FPU       },
      24                 :            :         { X86_FEATURE_XSAVEOPT,                 X86_FEATURE_XSAVE     },
      25                 :            :         { X86_FEATURE_XSAVEC,                   X86_FEATURE_XSAVE     },
      26                 :            :         { X86_FEATURE_XSAVES,                   X86_FEATURE_XSAVE     },
      27                 :            :         { X86_FEATURE_AVX,                      X86_FEATURE_XSAVE     },
      28                 :            :         { X86_FEATURE_PKU,                      X86_FEATURE_XSAVE     },
      29                 :            :         { X86_FEATURE_MPX,                      X86_FEATURE_XSAVE     },
      30                 :            :         { X86_FEATURE_XGETBV1,                  X86_FEATURE_XSAVE     },
      31                 :            :         { X86_FEATURE_CMOV,                     X86_FEATURE_FXSR      },
      32                 :            :         { X86_FEATURE_MMX,                      X86_FEATURE_FXSR      },
      33                 :            :         { X86_FEATURE_MMXEXT,                   X86_FEATURE_MMX       },
      34                 :            :         { X86_FEATURE_FXSR_OPT,                 X86_FEATURE_FXSR      },
      35                 :            :         { X86_FEATURE_XSAVE,                    X86_FEATURE_FXSR      },
      36                 :            :         { X86_FEATURE_XMM,                      X86_FEATURE_FXSR      },
      37                 :            :         { X86_FEATURE_XMM2,                     X86_FEATURE_XMM       },
      38                 :            :         { X86_FEATURE_XMM3,                     X86_FEATURE_XMM2      },
      39                 :            :         { X86_FEATURE_XMM4_1,                   X86_FEATURE_XMM2      },
      40                 :            :         { X86_FEATURE_XMM4_2,                   X86_FEATURE_XMM2      },
      41                 :            :         { X86_FEATURE_XMM3,                     X86_FEATURE_XMM2      },
      42                 :            :         { X86_FEATURE_PCLMULQDQ,                X86_FEATURE_XMM2      },
      43                 :            :         { X86_FEATURE_SSSE3,                    X86_FEATURE_XMM2,     },
      44                 :            :         { X86_FEATURE_F16C,                     X86_FEATURE_XMM2,     },
      45                 :            :         { X86_FEATURE_AES,                      X86_FEATURE_XMM2      },
      46                 :            :         { X86_FEATURE_SHA_NI,                   X86_FEATURE_XMM2      },
      47                 :            :         { X86_FEATURE_FMA,                      X86_FEATURE_AVX       },
      48                 :            :         { X86_FEATURE_AVX2,                     X86_FEATURE_AVX,      },
      49                 :            :         { X86_FEATURE_AVX512F,                  X86_FEATURE_AVX,      },
      50                 :            :         { X86_FEATURE_AVX512IFMA,               X86_FEATURE_AVX512F   },
      51                 :            :         { X86_FEATURE_AVX512PF,                 X86_FEATURE_AVX512F   },
      52                 :            :         { X86_FEATURE_AVX512ER,                 X86_FEATURE_AVX512F   },
      53                 :            :         { X86_FEATURE_AVX512CD,                 X86_FEATURE_AVX512F   },
      54                 :            :         { X86_FEATURE_AVX512DQ,                 X86_FEATURE_AVX512F   },
      55                 :            :         { X86_FEATURE_AVX512BW,                 X86_FEATURE_AVX512F   },
      56                 :            :         { X86_FEATURE_AVX512VL,                 X86_FEATURE_AVX512F   },
      57                 :            :         { X86_FEATURE_AVX512VBMI,               X86_FEATURE_AVX512F   },
      58                 :            :         { X86_FEATURE_AVX512_VBMI2,             X86_FEATURE_AVX512VL  },
      59                 :            :         { X86_FEATURE_GFNI,                     X86_FEATURE_AVX512VL  },
      60                 :            :         { X86_FEATURE_VAES,                     X86_FEATURE_AVX512VL  },
      61                 :            :         { X86_FEATURE_VPCLMULQDQ,               X86_FEATURE_AVX512VL  },
      62                 :            :         { X86_FEATURE_AVX512_VNNI,              X86_FEATURE_AVX512VL  },
      63                 :            :         { X86_FEATURE_AVX512_BITALG,            X86_FEATURE_AVX512VL  },
      64                 :            :         { X86_FEATURE_AVX512_4VNNIW,            X86_FEATURE_AVX512F   },
      65                 :            :         { X86_FEATURE_AVX512_4FMAPS,            X86_FEATURE_AVX512F   },
      66                 :            :         { X86_FEATURE_AVX512_VPOPCNTDQ,         X86_FEATURE_AVX512F   },
      67                 :            :         { X86_FEATURE_AVX512_VP2INTERSECT,      X86_FEATURE_AVX512VL  },
      68                 :            :         { X86_FEATURE_CQM_OCCUP_LLC,            X86_FEATURE_CQM_LLC   },
      69                 :            :         { X86_FEATURE_CQM_MBM_TOTAL,            X86_FEATURE_CQM_LLC   },
      70                 :            :         { X86_FEATURE_CQM_MBM_LOCAL,            X86_FEATURE_CQM_LLC   },
      71                 :            :         { X86_FEATURE_AVX512_BF16,              X86_FEATURE_AVX512VL  },
      72                 :            :         {}
      73                 :            : };
      74                 :            : 
      75                 :         84 : static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
      76                 :            : {
      77                 :            :         /*
      78                 :            :          * Note: This could use the non atomic __*_bit() variants, but the
      79                 :            :          * rest of the cpufeature code uses atomics as well, so keep it for
      80                 :            :          * consistency. Cleanup all of it separately.
      81                 :            :          */
      82         [ +  + ]:         84 :         if (!c) {
      83                 :         28 :                 clear_cpu_cap(&boot_cpu_data, feature);
      84                 :         28 :                 set_bit(feature, (unsigned long *)cpu_caps_cleared);
      85                 :            :         } else {
      86                 :         56 :                 clear_bit(feature, (unsigned long *)c->x86_capability);
      87                 :            :         }
      88                 :         84 : }
      89                 :            : 
      90                 :            : /* Take the capabilities and the BUG bits into account */
      91                 :            : #define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
      92                 :            : 
      93                 :         84 : static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
      94                 :            : {
      95                 :         84 :         DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
      96                 :         84 :         const struct cpuid_dep *d;
      97                 :         84 :         bool changed;
      98                 :            : 
      99   [ -  +  -  + ]:         84 :         if (WARN_ON(feature >= MAX_FEATURE_BITS))
     100                 :          0 :                 return;
     101                 :            : 
     102                 :         84 :         clear_feature(c, feature);
     103                 :            : 
     104                 :            :         /* Collect all features to disable, handling dependencies */
     105                 :         84 :         memset(disable, 0, sizeof(disable));
     106                 :         84 :         __set_bit(feature, disable);
     107                 :            : 
     108                 :            :         /* Loop until we get a stable state. */
     109                 :         84 :         do {
     110                 :         84 :                 changed = false;
     111         [ +  + ]:       4200 :                 for (d = cpuid_deps; d->feature; d++) {
     112         [ +  - ]:       4116 :                         if (!test_bit(d->depends, disable))
     113                 :       4116 :                                 continue;
     114         [ #  # ]:          0 :                         if (__test_and_set_bit(d->feature, disable))
     115                 :          0 :                                 continue;
     116                 :            : 
     117                 :          0 :                         changed = true;
     118                 :          0 :                         clear_feature(c, d->feature);
     119                 :            :                 }
     120         [ -  + ]:         84 :         } while (changed);
     121                 :            : }
     122                 :            : 
     123                 :         56 : void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
     124                 :            : {
     125                 :         56 :         do_clear_cpu_cap(c, feature);
     126                 :         28 : }
     127                 :            : 
     128                 :         28 : void setup_clear_cpu_cap(unsigned int feature)
     129                 :            : {
     130                 :         28 :         do_clear_cpu_cap(NULL, feature);
     131                 :         28 : }

Generated by: LCOV version 1.14