linux/arch/x86/kernel/cpu/cpuid-deps.c
<<
>>
Prefs
   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
   7struct 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 */
  22static const struct cpuid_dep cpuid_deps[] = {
  23        { X86_FEATURE_XSAVEOPT,         X86_FEATURE_XSAVE     },
  24        { X86_FEATURE_XSAVEC,           X86_FEATURE_XSAVE     },
  25        { X86_FEATURE_XSAVES,           X86_FEATURE_XSAVE     },
  26        { X86_FEATURE_AVX,              X86_FEATURE_XSAVE     },
  27        { X86_FEATURE_PKU,              X86_FEATURE_XSAVE     },
  28        { X86_FEATURE_MPX,              X86_FEATURE_XSAVE     },
  29        { X86_FEATURE_XGETBV1,          X86_FEATURE_XSAVE     },
  30        { X86_FEATURE_FXSR_OPT,         X86_FEATURE_FXSR      },
  31        { X86_FEATURE_XMM,              X86_FEATURE_FXSR      },
  32        { X86_FEATURE_XMM2,             X86_FEATURE_XMM       },
  33        { X86_FEATURE_XMM3,             X86_FEATURE_XMM2      },
  34        { X86_FEATURE_XMM4_1,           X86_FEATURE_XMM2      },
  35        { X86_FEATURE_XMM4_2,           X86_FEATURE_XMM2      },
  36        { X86_FEATURE_XMM3,             X86_FEATURE_XMM2      },
  37        { X86_FEATURE_PCLMULQDQ,        X86_FEATURE_XMM2      },
  38        { X86_FEATURE_SSSE3,            X86_FEATURE_XMM2,     },
  39        { X86_FEATURE_F16C,             X86_FEATURE_XMM2,     },
  40        { X86_FEATURE_AES,              X86_FEATURE_XMM2      },
  41        { X86_FEATURE_SHA_NI,           X86_FEATURE_XMM2      },
  42        { X86_FEATURE_FMA,              X86_FEATURE_AVX       },
  43        { X86_FEATURE_AVX2,             X86_FEATURE_AVX,      },
  44        { X86_FEATURE_AVX512F,          X86_FEATURE_AVX,      },
  45        { X86_FEATURE_AVX512IFMA,       X86_FEATURE_AVX512F   },
  46        { X86_FEATURE_AVX512PF,         X86_FEATURE_AVX512F   },
  47        { X86_FEATURE_AVX512ER,         X86_FEATURE_AVX512F   },
  48        { X86_FEATURE_AVX512CD,         X86_FEATURE_AVX512F   },
  49        { X86_FEATURE_AVX512DQ,         X86_FEATURE_AVX512F   },
  50        { X86_FEATURE_AVX512BW,         X86_FEATURE_AVX512F   },
  51        { X86_FEATURE_AVX512VL,         X86_FEATURE_AVX512F   },
  52        { X86_FEATURE_AVX512VBMI,       X86_FEATURE_AVX512F   },
  53        { X86_FEATURE_AVX512_VBMI2,     X86_FEATURE_AVX512VL  },
  54        { X86_FEATURE_GFNI,             X86_FEATURE_AVX512VL  },
  55        { X86_FEATURE_VAES,             X86_FEATURE_AVX512VL  },
  56        { X86_FEATURE_VPCLMULQDQ,       X86_FEATURE_AVX512VL  },
  57        { X86_FEATURE_AVX512_VNNI,      X86_FEATURE_AVX512VL  },
  58        { X86_FEATURE_AVX512_BITALG,    X86_FEATURE_AVX512VL  },
  59        { X86_FEATURE_AVX512_4VNNIW,    X86_FEATURE_AVX512F   },
  60        { X86_FEATURE_AVX512_4FMAPS,    X86_FEATURE_AVX512F   },
  61        { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F   },
  62        {}
  63};
  64
  65static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
  66{
  67        /*
  68         * Note: This could use the non atomic __*_bit() variants, but the
  69         * rest of the cpufeature code uses atomics as well, so keep it for
  70         * consistency. Cleanup all of it separately.
  71         */
  72        if (!c) {
  73                clear_cpu_cap(&boot_cpu_data, feature);
  74                set_bit(feature, (unsigned long *)cpu_caps_cleared);
  75        } else {
  76                clear_bit(feature, (unsigned long *)c->x86_capability);
  77        }
  78}
  79
  80/* Take the capabilities and the BUG bits into account */
  81#define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
  82
  83static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
  84{
  85        DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
  86        const struct cpuid_dep *d;
  87        bool changed;
  88
  89        if (WARN_ON(feature >= MAX_FEATURE_BITS))
  90                return;
  91
  92        clear_feature(c, feature);
  93
  94        /* Collect all features to disable, handling dependencies */
  95        memset(disable, 0, sizeof(disable));
  96        __set_bit(feature, disable);
  97
  98        /* Loop until we get a stable state. */
  99        do {
 100                changed = false;
 101                for (d = cpuid_deps; d->feature; d++) {
 102                        if (!test_bit(d->depends, disable))
 103                                continue;
 104                        if (__test_and_set_bit(d->feature, disable))
 105                                continue;
 106
 107                        changed = true;
 108                        clear_feature(c, d->feature);
 109                }
 110        } while (changed);
 111}
 112
 113void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
 114{
 115        do_clear_cpu_cap(c, feature);
 116}
 117
 118void setup_clear_cpu_cap(unsigned int feature)
 119{
 120        do_clear_cpu_cap(NULL, feature);
 121}
 122