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 : 33 : 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 [ + + ]: 33 : if (!c) {
83 : 11 : clear_cpu_cap(&boot_cpu_data, feature);
84 : 11 : set_bit(feature, (unsigned long *)cpu_caps_cleared);
85 : : } else {
86 : 22 : clear_bit(feature, (unsigned long *)c->x86_capability);
87 : : }
88 : 33 : }
89 : :
90 : : /* Take the capabilities and the BUG bits into account */
91 : : #define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
92 : :
93 : 33 : static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
94 : : {
95 : 33 : DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
96 : 33 : const struct cpuid_dep *d;
97 : 33 : bool changed;
98 : :
99 [ - + - + ]: 33 : if (WARN_ON(feature >= MAX_FEATURE_BITS))
100 : 0 : return;
101 : :
102 : 33 : clear_feature(c, feature);
103 : :
104 : : /* Collect all features to disable, handling dependencies */
105 : 33 : memset(disable, 0, sizeof(disable));
106 : 33 : __set_bit(feature, disable);
107 : :
108 : : /* Loop until we get a stable state. */
109 : 33 : do {
110 : 33 : changed = false;
111 [ + + ]: 1650 : for (d = cpuid_deps; d->feature; d++) {
112 [ + - ]: 1617 : if (!test_bit(d->depends, disable))
113 : 1617 : 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 [ - + ]: 33 : } while (changed);
121 : : }
122 : :
123 : 22 : void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
124 : : {
125 : 22 : do_clear_cpu_cap(c, feature);
126 : 11 : }
127 : :
128 : 11 : void setup_clear_cpu_cap(unsigned int feature)
129 : : {
130 : 11 : do_clear_cpu_cap(NULL, feature);
131 : 11 : }
|