um: Check for missing AVX and AVX-512 xstate bits

If the CPU declares AVX or AVX-512 support, verify that all the
corresponding bits are set in the XCR0 register.  If any are missing,
warn and don't set the corresponding X86_FEATURE_* flags.

This eliminates the perceived need for UML-supporting AVX and AVX-512
optimized code in the kernel (that is, lib/raid/ currently) to start
checking the XCR0 bits in addition to X86_FEATURE_AVX*.

This aligns UML with the vast majority of userspace programs, which
check the XCR0 bits before considering AVX and AVX-512 to be supported,
as per the procedure documented in Intel's CPU manual.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260901145740.42337-3-ebiggers@kernel.org
This commit is contained in:
Eric Biggers 2026-09-01 07:57:34 -07:00 committed by Borislav Petkov (AMD)
parent 518aa9948e
commit 19c5d90800

View File

@ -264,12 +264,88 @@ unsigned long brk_start;
#define MIN_VMALLOC (32 * 1024 * 1024)
static u64 __init read_xcr0(void)
{
u32 a, b, c, d;
asm volatile("cpuid"
: "=a"(a), "=b"(b), "=c"(c), "=d"(d)
: "a"(0), "c"(0));
if (a >= 1) { /* max_leaf >= 1 */
asm volatile("cpuid"
: "=a"(a), "=b"(b), "=c"(c), "=d"(d)
: "a"(1), "c"(0));
if (c & (1 << 27)) { /* XSAVE enabled by OS */
asm volatile("xgetbv" : "=d"(d), "=a"(a) : "c"(0));
return ((u64)d << 32) | a;
}
}
return 0;
}
static void __init validate_and_set_cpu_cap(int cap, u64 xcr0)
{
/*
* Check for missing xstate features right away, so that there's no
* perceived need for all optimized code in the kernel to do so.
*/
switch (cap) {
case X86_FEATURE_AVX:
case X86_FEATURE_AVX2:
case X86_FEATURE_AVX_VNNI:
case X86_FEATURE_FMA:
case X86_FEATURE_VAES:
case X86_FEATURE_VPCLMULQDQ:
if ((xcr0 & 0x7) != 0x7) {
static bool warned;
if (!warned) {
os_warn("Disabling AVX support due to missing xstate features\n");
warned = true;
}
return;
}
break;
case X86_FEATURE_AVX512F:
case X86_FEATURE_AVX512BW:
case X86_FEATURE_AVX512CD:
case X86_FEATURE_AVX512DQ:
case X86_FEATURE_AVX512ER:
case X86_FEATURE_AVX512IFMA:
case X86_FEATURE_AVX512PF:
case X86_FEATURE_AVX512VBMI:
case X86_FEATURE_AVX512VL:
case X86_FEATURE_AVX512_4FMAPS:
case X86_FEATURE_AVX512_4VNNIW:
case X86_FEATURE_AVX512_BF16:
case X86_FEATURE_AVX512_BITALG:
case X86_FEATURE_AVX512_FP16:
case X86_FEATURE_AVX512_VBMI2:
case X86_FEATURE_AVX512_VNNI:
case X86_FEATURE_AVX512_VP2INTERSECT:
case X86_FEATURE_AVX512_VPOPCNTDQ:
if ((xcr0 & 0xe7) != 0xe7) {
static bool warned;
if (!warned) {
os_warn("Disabling AVX-512 support due to missing xstate features\n");
warned = true;
}
return;
}
break;
}
set_cpu_cap(&boot_cpu_data, cap);
}
static void __init parse_host_cpu_flags(char *line)
{
u64 xcr0 = read_xcr0();
int i;
for (i = 0; i < 32*NCAPINTS; i++) {
if ((x86_cap_flags[i] != NULL) && strstr(line, x86_cap_flags[i]))
set_cpu_cap(&boot_cpu_data, i);
validate_and_set_cpu_cap(i, xcr0);
}
}