Back to home page

OSCL-LXR

 
 

    


0001 /* Declare dependencies between CPUIDs */
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  * Table of CPUID features that depend on others.
0014  *
0015  * This only includes dependencies that can be usefully disabled, not
0016  * features part of the base set (like FPU).
0017  *
0018  * Note this all is not __init / __initdata because it can be
0019  * called from cpu hotplug. It shouldn't do anything in this case,
0020  * but it's difficult to tell that to the init reference checker.
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      * Note: This could use the non atomic __*_bit() variants, but the
0088      * rest of the cpufeature code uses atomics as well, so keep it for
0089      * consistency. Cleanup all of it separately.
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 /* Take the capabilities and the BUG bits into account */
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     /* Collect all features to disable, handling dependencies */
0114     memset(disable, 0, sizeof(disable));
0115     __set_bit(feature, disable);
0116 
0117     /* Loop until we get a stable state. */
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 }