Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/cpu/cpuid-deps.c
26493 views
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_APX, X86_FEATURE_XSAVE },
32
{ X86_FEATURE_CMOV, X86_FEATURE_FXSR },
33
{ X86_FEATURE_MMX, X86_FEATURE_FXSR },
34
{ X86_FEATURE_MMXEXT, X86_FEATURE_MMX },
35
{ X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
36
{ X86_FEATURE_XSAVE, X86_FEATURE_FXSR },
37
{ X86_FEATURE_XMM, X86_FEATURE_FXSR },
38
{ X86_FEATURE_XMM2, X86_FEATURE_XMM },
39
{ X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
40
{ X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
41
{ X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
42
{ X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
43
{ X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
44
{ X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
45
{ X86_FEATURE_F16C, X86_FEATURE_XMM2, },
46
{ X86_FEATURE_AES, X86_FEATURE_XMM2 },
47
{ X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
48
{ X86_FEATURE_GFNI, X86_FEATURE_XMM2 },
49
{ X86_FEATURE_AVX_VNNI, X86_FEATURE_AVX },
50
{ X86_FEATURE_FMA, X86_FEATURE_AVX },
51
{ X86_FEATURE_VAES, X86_FEATURE_AVX },
52
{ X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX },
53
{ X86_FEATURE_AVX2, X86_FEATURE_AVX, },
54
{ X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
55
{ X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
56
{ X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
57
{ X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
58
{ X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
59
{ X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
60
{ X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
61
{ X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
62
{ X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
63
{ X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
64
{ X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
65
{ X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
66
{ X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
67
{ X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
68
{ X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
69
{ X86_FEATURE_AVX512_VP2INTERSECT, X86_FEATURE_AVX512VL },
70
{ X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC },
71
{ X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
72
{ X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
73
{ X86_FEATURE_BMEC, X86_FEATURE_CQM_MBM_TOTAL },
74
{ X86_FEATURE_BMEC, X86_FEATURE_CQM_MBM_LOCAL },
75
{ X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL },
76
{ X86_FEATURE_AVX512_FP16, X86_FEATURE_AVX512BW },
77
{ X86_FEATURE_ENQCMD, X86_FEATURE_XSAVES },
78
{ X86_FEATURE_PER_THREAD_MBA, X86_FEATURE_MBA },
79
{ X86_FEATURE_SGX_LC, X86_FEATURE_SGX },
80
{ X86_FEATURE_SGX1, X86_FEATURE_SGX },
81
{ X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
82
{ X86_FEATURE_SGX_EDECCSSA, X86_FEATURE_SGX1 },
83
{ X86_FEATURE_XFD, X86_FEATURE_XSAVES },
84
{ X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
85
{ X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },
86
{ X86_FEATURE_AMX_FP16, X86_FEATURE_AMX_TILE },
87
{ X86_FEATURE_AMX_BF16, X86_FEATURE_AMX_TILE },
88
{ X86_FEATURE_AMX_INT8, X86_FEATURE_AMX_TILE },
89
{ X86_FEATURE_SHSTK, X86_FEATURE_XSAVES },
90
{ X86_FEATURE_FRED, X86_FEATURE_LKGS },
91
{ X86_FEATURE_SPEC_CTRL_SSBD, X86_FEATURE_SPEC_CTRL },
92
{}
93
};
94
95
static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
96
{
97
/*
98
* Note: This could use the non atomic __*_bit() variants, but the
99
* rest of the cpufeature code uses atomics as well, so keep it for
100
* consistency. Cleanup all of it separately.
101
*/
102
if (!c) {
103
clear_cpu_cap(&boot_cpu_data, feature);
104
set_bit(feature, (unsigned long *)cpu_caps_cleared);
105
} else {
106
clear_bit(feature, (unsigned long *)c->x86_capability);
107
}
108
}
109
110
/* Take the capabilities and the BUG bits into account */
111
#define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
112
113
static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
114
{
115
DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
116
const struct cpuid_dep *d;
117
bool changed;
118
119
if (WARN_ON(feature >= MAX_FEATURE_BITS))
120
return;
121
122
if (boot_cpu_has(feature))
123
WARN_ON(alternatives_patched);
124
125
clear_feature(c, feature);
126
127
/* Collect all features to disable, handling dependencies */
128
memset(disable, 0, sizeof(disable));
129
__set_bit(feature, disable);
130
131
/* Loop until we get a stable state. */
132
do {
133
changed = false;
134
for (d = cpuid_deps; d->feature; d++) {
135
if (!test_bit(d->depends, disable))
136
continue;
137
if (__test_and_set_bit(d->feature, disable))
138
continue;
139
140
changed = true;
141
clear_feature(c, d->feature);
142
}
143
} while (changed);
144
}
145
146
void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
147
{
148
do_clear_cpu_cap(c, feature);
149
}
150
151
void setup_clear_cpu_cap(unsigned int feature)
152
{
153
do_clear_cpu_cap(NULL, feature);
154
}
155
156
/*
157
* Return the feature "name" if available, otherwise return
158
* the X86_FEATURE_* numerals to make it easier to identify
159
* the feature.
160
*/
161
static const char *x86_feature_name(unsigned int feature, char *buf)
162
{
163
if (x86_cap_flags[feature])
164
return x86_cap_flags[feature];
165
166
snprintf(buf, 16, "%d*32+%2d", feature / 32, feature % 32);
167
168
return buf;
169
}
170
171
void check_cpufeature_deps(struct cpuinfo_x86 *c)
172
{
173
char feature_buf[16], depends_buf[16];
174
const struct cpuid_dep *d;
175
176
for (d = cpuid_deps; d->feature; d++) {
177
if (cpu_has(c, d->feature) && !cpu_has(c, d->depends)) {
178
/*
179
* Only warn about the first unmet dependency on the
180
* first CPU where it is encountered to avoid spamming
181
* the kernel log.
182
*/
183
pr_warn_once("x86 CPU feature dependency check failure: CPU%d has '%s' enabled but '%s' disabled. Kernel might be fine, but no guarantees.\n",
184
smp_processor_id(),
185
x86_feature_name(d->feature, feature_buf),
186
x86_feature_name(d->depends, depends_buf));
187
}
188
}
189
}
190
191