0001
0002 #include <linux/kernel.h>
0003 #include <linux/init.h>
0004 #include <linux/module.h>
0005 #include <asm/cpufeature.h>
0006
0007 struct cpuid_dep {
0008 unsigned int feature;
0009 unsigned int depends;
0010 };
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 static const struct cpuid_dep cpuid_deps[] = {
0023 { X86_FEATURE_FXSR, X86_FEATURE_FPU },
0024 { X86_FEATURE_XSAVEOPT, X86_FEATURE_XSAVE },
0025 { X86_FEATURE_XSAVEC, X86_FEATURE_XSAVE },
0026 { X86_FEATURE_XSAVES, X86_FEATURE_XSAVE },
0027 { X86_FEATURE_AVX, X86_FEATURE_XSAVE },
0028 { X86_FEATURE_PKU, X86_FEATURE_XSAVE },
0029 { X86_FEATURE_MPX, X86_FEATURE_XSAVE },
0030 { X86_FEATURE_XGETBV1, X86_FEATURE_XSAVE },
0031 { X86_FEATURE_CMOV, X86_FEATURE_FXSR },
0032 { X86_FEATURE_MMX, X86_FEATURE_FXSR },
0033 { X86_FEATURE_MMXEXT, X86_FEATURE_MMX },
0034 { X86_FEATURE_FXSR_OPT, X86_FEATURE_FXSR },
0035 { X86_FEATURE_XSAVE, X86_FEATURE_FXSR },
0036 { X86_FEATURE_XMM, X86_FEATURE_FXSR },
0037 { X86_FEATURE_XMM2, X86_FEATURE_XMM },
0038 { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
0039 { X86_FEATURE_XMM4_1, X86_FEATURE_XMM2 },
0040 { X86_FEATURE_XMM4_2, X86_FEATURE_XMM2 },
0041 { X86_FEATURE_XMM3, X86_FEATURE_XMM2 },
0042 { X86_FEATURE_PCLMULQDQ, X86_FEATURE_XMM2 },
0043 { X86_FEATURE_SSSE3, X86_FEATURE_XMM2, },
0044 { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
0045 { X86_FEATURE_AES, X86_FEATURE_XMM2 },
0046 { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
0047 { X86_FEATURE_FMA, X86_FEATURE_AVX },
0048 { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
0049 { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
0050 { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
0051 { X86_FEATURE_AVX512PF, X86_FEATURE_AVX512F },
0052 { X86_FEATURE_AVX512ER, X86_FEATURE_AVX512F },
0053 { X86_FEATURE_AVX512CD, X86_FEATURE_AVX512F },
0054 { X86_FEATURE_AVX512DQ, X86_FEATURE_AVX512F },
0055 { X86_FEATURE_AVX512BW, X86_FEATURE_AVX512F },
0056 { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
0057 { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
0058 { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
0059 { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
0060 { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
0061 { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
0062 { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
0063 { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
0064 { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
0065 { X86_FEATURE_AVX512_4FMAPS, X86_FEATURE_AVX512F },
0066 { X86_FEATURE_AVX512_VPOPCNTDQ, X86_FEATURE_AVX512F },
0067 { X86_FEATURE_AVX512_VP2INTERSECT, X86_FEATURE_AVX512VL },
0068 { X86_FEATURE_CQM_OCCUP_LLC, X86_FEATURE_CQM_LLC },
0069 { X86_FEATURE_CQM_MBM_TOTAL, X86_FEATURE_CQM_LLC },
0070 { X86_FEATURE_CQM_MBM_LOCAL, X86_FEATURE_CQM_LLC },
0071 { X86_FEATURE_AVX512_BF16, X86_FEATURE_AVX512VL },
0072 { X86_FEATURE_AVX512_FP16, X86_FEATURE_AVX512BW },
0073 { X86_FEATURE_ENQCMD, X86_FEATURE_XSAVES },
0074 { X86_FEATURE_PER_THREAD_MBA, X86_FEATURE_MBA },
0075 { X86_FEATURE_SGX_LC, X86_FEATURE_SGX },
0076 { X86_FEATURE_SGX1, X86_FEATURE_SGX },
0077 { X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
0078 { X86_FEATURE_XFD, X86_FEATURE_XSAVES },
0079 { X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
0080 { X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },
0081 {}
0082 };
0083
0084 static inline void clear_feature(struct cpuinfo_x86 *c, unsigned int feature)
0085 {
0086
0087
0088
0089
0090
0091 if (!c) {
0092 clear_cpu_cap(&boot_cpu_data, feature);
0093 set_bit(feature, (unsigned long *)cpu_caps_cleared);
0094 } else {
0095 clear_bit(feature, (unsigned long *)c->x86_capability);
0096 }
0097 }
0098
0099
0100 #define MAX_FEATURE_BITS ((NCAPINTS + NBUGINTS) * sizeof(u32) * 8)
0101
0102 static void do_clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
0103 {
0104 DECLARE_BITMAP(disable, MAX_FEATURE_BITS);
0105 const struct cpuid_dep *d;
0106 bool changed;
0107
0108 if (WARN_ON(feature >= MAX_FEATURE_BITS))
0109 return;
0110
0111 clear_feature(c, feature);
0112
0113
0114 memset(disable, 0, sizeof(disable));
0115 __set_bit(feature, disable);
0116
0117
0118 do {
0119 changed = false;
0120 for (d = cpuid_deps; d->feature; d++) {
0121 if (!test_bit(d->depends, disable))
0122 continue;
0123 if (__test_and_set_bit(d->feature, disable))
0124 continue;
0125
0126 changed = true;
0127 clear_feature(c, d->feature);
0128 }
0129 } while (changed);
0130 }
0131
0132 void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int feature)
0133 {
0134 do_clear_cpu_cap(c, feature);
0135 }
0136
0137 void setup_clear_cpu_cap(unsigned int feature)
0138 {
0139 do_clear_cpu_cap(NULL, feature);
0140 }