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