If the CPU declares AVX or AVX-512 support, verify that the
corresponding xstate bits are also set.  If not, warn and clear them.

This eliminates the perceived need for AVX and AVX-512 optimized code in
the kernel to call cpu_has_xfeatures().  That has never been universally
done, which strongly suggests that it has never really been needed in
practice, but this should remove any remaining doubt.

Signed-off-by: Eric Biggers <[email protected]>
---
 arch/x86/kernel/fpu/xstate.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index a7b6524a9dea2..904ff933c0d88 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -799,6 +799,23 @@ static u64 __init guest_default_mask(void)
        return ~(u64)XFEATURE_MASK_USER_DYNAMIC;
 }
 
+/* Clear any X86_FEATURE_* used by the kernel whose xfeatures are missing. */
+static void __init clear_cpu_caps_with_missing_xfeatures(u64 xfeatures)
+{
+       u64 mask;
+
+       mask = XFEATURE_MASK_FPSSE | XFEATURE_MASK_YMM;
+       if (boot_cpu_has(X86_FEATURE_AVX) && (xfeatures & mask) != mask) {
+               pr_err("x86/fpu: Disabling AVX support due to missing xstate 
features\n");
+               setup_clear_cpu_cap(X86_FEATURE_AVX);
+       }
+       mask = XFEATURE_MASK_FPSSE | XFEATURE_MASK_YMM | XFEATURE_MASK_AVX512;
+       if (boot_cpu_has(X86_FEATURE_AVX512F) && (xfeatures & mask) != mask) {
+               pr_err("x86/fpu: Disabling AVX-512 support due to missing 
xstate features\n");
+               setup_clear_cpu_cap(X86_FEATURE_AVX512F);
+       }
+}
+
 /*
  * Enable and initialize the xsave feature.
  * Called once per system bootup.
@@ -812,12 +829,14 @@ void __init fpu__init_system_xstate(unsigned int 
legacy_size)
 
        if (!boot_cpu_has(X86_FEATURE_FPU)) {
                pr_info("x86/fpu: No FPU detected\n");
+               clear_cpu_caps_with_missing_xfeatures(0);
                return;
        }
 
        if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
                pr_info("x86/fpu: x87 FPU will use %s\n",
                        boot_cpu_has(X86_FEATURE_FXSR) ? "FXSAVE" : "FSAVE");
+               clear_cpu_caps_with_missing_xfeatures(0);
                return;
        }
 
@@ -855,6 +874,8 @@ void __init fpu__init_system_xstate(unsigned int 
legacy_size)
                goto out_disable;
        }
 
+       clear_cpu_caps_with_missing_xfeatures(fpu_kernel_cfg.max_features);
+
        fpu_kernel_cfg.independent_features = fpu_kernel_cfg.max_features &
                                              XFEATURE_MASK_INDEPENDENT;
 
-- 
2.55.0


Reply via email to