mirror of
https://github.com/torvalds/linux.git
synced 2026-10-24 16:55:02 +02:00
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:
parent
518aa9948e
commit
19c5d90800
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user