Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/x86/include/asm/cpufeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@
#define X86_FEATURE_AMX_FP16 (12*32+21) /* AMX fp16 Support */
#define X86_FEATURE_AVX_IFMA (12*32+23) /* Support for VPMADD52[H,L]UQ */
#define X86_FEATURE_LAM (12*32+26) /* "lam" Linear Address Masking */
#define X86_FEATURE_MOVRS (12*32+31) /* MOVRS instructions */

/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
#define X86_FEATURE_AMD_IBPB_RET (13*32+30) /* "" IBPB clears return address predictor */
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ static __always_inline bool cpuid_function_is_indexed(u32 function)
case 0x1d:
case 0x1e:
case 0x1f:
case 0x24:
case 0x8000001d:
return true;
}
Expand Down
20 changes: 20 additions & 0 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,26 @@ struct kvm_queued_exception {
bool has_payload;
};

/*
* Hardware-defined CPUID leafs that are either scattered by the kernel or are
* unknown to the kernel, but need to be directly used by KVM. Note, these
* word values conflict with the kernel's "bug" caps, but KVM doesn't use those.
*/
enum kvm_only_cpuid_leafs {
CPUID_12_EAX = NCAPINTS,
CPUID_7_1_EDX,
CPUID_8000_0007_EDX,
CPUID_8000_0022_EAX,
CPUID_7_2_EDX,
CPUID_8000_0021_ECX,
CPUID_24_0_EBX,
CPUID_1E_1_EAX,
CPUID_24_1_ECX,
NR_KVM_CPU_CAPS,

NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS,
};

struct kvm_vcpu_arch {
/*
* rip and regs accesses must go through
Expand Down
68 changes: 65 additions & 3 deletions arch/x86/kvm/cpuid.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,12 +691,12 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_mask(CPUID_7_1_EAX,
F(AVX_VNNI) | F(AVX512_BF16) | F(CMPCCXADD) |
F(FZRM) | F(FSRS) | F(FSRC) |
F(AMX_FP16) | F(AVX_IFMA)
F(AMX_FP16) | F(AVX_IFMA) | F(MOVRS)
);

kvm_cpu_cap_init_kvm_defined(CPUID_7_1_EDX,
F(AVX_VNNI_INT8) | F(AVX_NE_CONVERT) | F(PREFETCHITI) |
F(AMX_COMPLEX)
F(AMX_COMPLEX) | F(AVX10)
);

kvm_cpu_cap_init_kvm_defined(CPUID_7_2_EDX,
Expand All @@ -720,6 +720,20 @@ void kvm_set_cpu_caps(void)
F(TOPOEXT) | 0 /* PERFCTR_CORE */
);

kvm_cpu_cap_init_kvm_defined(CPUID_1E_1_EAX,
F(AMX_INT8_ALIAS) | F(AMX_BF16_ALIAS) | F(AMX_COMPLEX_ALIAS) |
F(AMX_FP16_ALIAS) | F(AMX_FP8) | F(AMX_TF32) | F(AMX_AVX512) |
F(AMX_MOVRS)
);

kvm_cpu_cap_init_kvm_defined(CPUID_24_0_EBX,
F(AVX10_128) | F(AVX10_256) | F(AVX10_512)
);

kvm_cpu_cap_init_kvm_defined(CPUID_24_1_ECX,
F(AVX10_VNNI_INT)
);

kvm_cpu_cap_mask(CPUID_8000_0001_EDX,
F(FPU) | F(VME) | F(DE) | F(PSE) |
F(TSC) | F(MSR) | F(PAE) | F(MCE) |
Expand Down Expand Up @@ -949,7 +963,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
switch (function) {
case 0:
/* Limited to the highest leaf implemented in KVM. */
entry->eax = min(entry->eax, 0x1fU);
entry->eax = min(entry->eax, 0x24U);
break;
case 1:
cpuid_entry_override(entry, CPUID_1_EDX);
Expand Down Expand Up @@ -1171,7 +1185,55 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
break;
}

max_idx = entry->eax = min(entry->eax, 1u);

/* KVM only supports up to 0x1e.0x1, capped above via min(). */
if (max_idx >= 1) {
entry = do_host_cpuid(array, function, 1);
if (!entry)
goto out;

cpuid_entry_override(entry, CPUID_1E_1_EAX);
entry->ebx = 0;
entry->ecx = 0;
entry->edx = 0;
}
break;
case 0x24: {
u8 avx10_version;

if (!kvm_cpu_cap_has(X86_FEATURE_AVX10)) {
entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
break;
}

max_idx = entry->eax = min(entry->eax, 1u);
/*
* The AVX10 version is encoded in EBX[7:0]. Note, the version
* is guaranteed to be >=1 if AVX10 is supported. Note #2, the
* version needs to be captured before overriding EBX features!
*/
avx10_version = min_t(u8, entry->ebx & 0xff, 2);
cpuid_entry_override(entry, CPUID_24_0_EBX);
entry->ebx |= avx10_version;

entry->ecx = 0;
entry->edx = 0;

/* KVM only supports up to 0x24.0x1, capped above via min(). */
if (max_idx >= 1) {
entry = do_host_cpuid(array, function, 1);
if (!entry)
goto out;

cpuid_entry_override(entry, CPUID_24_1_ECX);
entry->eax = 0;
entry->ebx = 0;
entry->edx = 0;
}
break;
}
case KVM_CPUID_SIGNATURE: {
const u32 *sigptr = (const u32 *)KVM_SIGNATURE;
entry->eax = KVM_CPUID_FEATURES;
Expand Down
43 changes: 26 additions & 17 deletions arch/x86/kvm/reverse_cpuid.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,6 @@
#include <asm/cpufeature.h>
#include <asm/cpufeatures.h>

/*
* Hardware-defined CPUID leafs that are either scattered by the kernel or are
* unknown to the kernel, but need to be directly used by KVM. Note, these
* word values conflict with the kernel's "bug" caps, but KVM doesn't use those.
*/
enum kvm_only_cpuid_leafs {
CPUID_12_EAX = NCAPINTS,
CPUID_7_1_EDX,
CPUID_8000_0007_EDX,
CPUID_8000_0022_EAX,
CPUID_7_2_EDX,
CPUID_8000_0021_ECX,
NR_KVM_CPU_CAPS,

NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS,
};

/*
* Define a KVM-only feature flag.
*
Expand All @@ -47,6 +30,7 @@ enum kvm_only_cpuid_leafs {
#define X86_FEATURE_AVX_NE_CONVERT KVM_X86_FEATURE(CPUID_7_1_EDX, 5)
#define X86_FEATURE_AMX_COMPLEX KVM_X86_FEATURE(CPUID_7_1_EDX, 8)
#define X86_FEATURE_PREFETCHITI KVM_X86_FEATURE(CPUID_7_1_EDX, 14)
#define X86_FEATURE_AVX10 KVM_X86_FEATURE(CPUID_7_1_EDX, 19)

/* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */
#define X86_FEATURE_INTEL_PSFD KVM_X86_FEATURE(CPUID_7_2_EDX, 0)
Expand All @@ -56,6 +40,28 @@ enum kvm_only_cpuid_leafs {
#define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
#define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5)

/*
* Intel-defined sub-features, CPUID level 0x0000001E:1 (EAX). Note, several
* of the bits are aliases to features of the same name that are enumerated via
* various CPUID.0x7 sub-leafs.
*/
#define X86_FEATURE_AMX_INT8_ALIAS KVM_X86_FEATURE(CPUID_1E_1_EAX, 0)
#define X86_FEATURE_AMX_BF16_ALIAS KVM_X86_FEATURE(CPUID_1E_1_EAX, 1)
#define X86_FEATURE_AMX_COMPLEX_ALIAS KVM_X86_FEATURE(CPUID_1E_1_EAX, 2)
#define X86_FEATURE_AMX_FP16_ALIAS KVM_X86_FEATURE(CPUID_1E_1_EAX, 3)
#define X86_FEATURE_AMX_FP8 KVM_X86_FEATURE(CPUID_1E_1_EAX, 4)
#define X86_FEATURE_AMX_TF32 KVM_X86_FEATURE(CPUID_1E_1_EAX, 6)
#define X86_FEATURE_AMX_AVX512 KVM_X86_FEATURE(CPUID_1E_1_EAX, 7)
#define X86_FEATURE_AMX_MOVRS KVM_X86_FEATURE(CPUID_1E_1_EAX, 8)

/* Intel-defined sub-features, CPUID level 0x00000024:0 (EBX) */
#define X86_FEATURE_AVX10_128 KVM_X86_FEATURE(CPUID_24_0_EBX, 16)
#define X86_FEATURE_AVX10_256 KVM_X86_FEATURE(CPUID_24_0_EBX, 17)
#define X86_FEATURE_AVX10_512 KVM_X86_FEATURE(CPUID_24_0_EBX, 18)

/* Intel-defined sub-features, CPUID level 0x00000024:1 (ECX) */
#define X86_FEATURE_AVX10_VNNI_INT KVM_X86_FEATURE(CPUID_24_1_ECX, 2)

/* CPUID level 0x80000007 (EDX). */
#define KVM_X86_FEATURE_CONSTANT_TSC KVM_X86_FEATURE(CPUID_8000_0007_EDX, 8)

Expand Down Expand Up @@ -96,6 +102,9 @@ static const struct cpuid_reg reverse_cpuid[] = {
[CPUID_8000_0022_EAX] = {0x80000022, 0, CPUID_EAX},
[CPUID_7_2_EDX] = { 7, 2, CPUID_EDX},
[CPUID_8000_0021_ECX] = {0x80000021, 0, CPUID_ECX},
[CPUID_24_0_EBX] = { 0x24, 0, CPUID_EBX},
[CPUID_1E_1_EAX] = { 0x1e, 1, CPUID_EAX},
[CPUID_24_1_ECX] = { 0x24, 1, CPUID_ECX},
};

/*
Expand Down
1 change: 1 addition & 0 deletions tools/arch/x86/include/asm/cpufeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
#define X86_FEATURE_AMX_FP16 (12*32+21) /* "" AMX fp16 Support */
#define X86_FEATURE_AVX_IFMA (12*32+23) /* "" Support for VPMADD52[H,L]UQ */
#define X86_FEATURE_LAM (12*32+26) /* Linear Address Masking */
#define X86_FEATURE_MOVRS (12*32+31) /* MOVRS instructions */

/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
Expand Down