LCOV - code coverage report
Current view: top level - arch/x86/kernel/cpu - cpuid-deps.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 26 31 83.9 %
Date: 2021-04-22 12:43:58 Functions: 4 4 100.0 %

          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             :         { X86_FEATURE_AVX512_FP16,              X86_FEATURE_AVX512BW  },
      73             :         { X86_FEATURE_ENQCMD,                   X86_FEATURE_XSAVES    },
      74             :         { X86_FEATURE_PER_THREAD_MBA,           X86_FEATURE_MBA       },
      75             :         {}
      76             : };
      77             : 
      78          27 : static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
      79             : {
      80             :         /*
      81             :          * Note: This could use the non atomic __*_bit() variants, but the
      82             :          * rest of the cpufeature code uses atomics as well, so keep it for
      83             :          * consistency. Cleanup all of it separately.
      84             :          */
      85          27 :         if (!c) {
      86          18 :                 clear_cpu_cap(&boot_cpu_data, feature);
      87           9 :                 set_bit(feature, (unsigned long *)cpu_caps_cleared);
      88             :         } else {
      89          18 :                 clear_bit(feature, (unsigned long *)c->x86_capability);
      90             :         }
      91          27 : }
      92             : 
      93             : /* Take the capabilities and the BUG bits into account */
      94             : #define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
      95             : 
      96          27 : static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
      97             : {
      98          27 :         DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
      99          27 :         const struct cpuid_dep *d;
     100          27 :         bool changed;
     101             : 
     102          27 :         if (WARN_ON(feature >= MAX_FEATURE_BITS))
     103           0 :                 return;
     104             : 
     105          27 :         clear_feature(c, feature);
     106             : 
     107             :         /* Collect all features to disable, handling dependencies */
     108          27 :         memset(disable, 0, sizeof(disable));
     109          27 :         __set_bit(feature, disable);
     110             : 
     111             :         /* Loop until we get a stable state. */
     112          27 :         do {
     113          27 :                 changed = false;
     114        1431 :                 for (d = cpuid_deps; d->feature; d++) {
     115        1404 :                         if (!test_bit(d->depends, disable))
     116        1404 :                                 continue;
     117           0 :                         if (__test_and_set_bit(d->feature, disable))
     118           0 :                                 continue;
     119             : 
     120           0 :                         changed = true;
     121           0 :                         clear_feature(c, d->feature);
     122             :                 }
     123          27 :         } while (changed);
     124             : }
     125             : 
     126          18 : void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
     127             : {
     128          18 :         do_clear_cpu_cap(c, feature);
     129           9 : }
     130             : 
     131           9 : void setup_clear_cpu_cap(unsigned int feature)
     132             : {
     133           9 :         do_clear_cpu_cap(NULL, feature);
     134           9 : }

Generated by: LCOV version 1.14