Add kvm_cpu_cap_check_and_init_mf() to initialize KVM-only CPUID leafs whose allowed feature bits needs to be intersected with the raw host CPUID value for CPUID paranoid verification. Use it instead of kvm_cpu_cap_init() to avoid adding new X86 feature bit definitions in the common x86 header. Move raw_cpuid_get() to cpuid.h since kvm_cpu_cap_check_and_init_mf() will be called in vendor module. Signed-off-by: Binbin Wu --- arch/x86/kvm/cpuid.c | 23 ----------------------- arch/x86/kvm/cpuid.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 78d8f89d6079..3bd9608770a9 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -672,29 +672,6 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, return 0; } -static __always_inline u32 raw_cpuid_get(struct cpuid_reg cpuid) -{ - struct kvm_cpuid_entry2 entry; - u32 base; - - /* - * KVM only supports features defined by Intel (0x0), AMD (0x80000000), - * and Centaur (0xc0000000). WARN if a feature for new vendor base is - * defined, as this and other code would need to be updated. - */ - base = cpuid.function & 0xffff0000; - if (WARN_ON_ONCE(base && base != 0x80000000 && base != 0xc0000000)) - return 0; - - if (cpuid_eax(base) < cpuid.function) - return 0; - - cpuid_count(cpuid.function, cpuid.index, - &entry.eax, &entry.ebx, &entry.ecx, &entry.edx); - - return *__cpuid_entry_get_reg(&entry, cpuid.reg); -} - /* * For kernel-defined leafs, mask KVM's supported feature set with the kernel's * capabilities as well as raw CPUID. For KVM-defined leafs, consult only raw diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index ea8ff5210e4a..0b90344a8b98 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -259,6 +259,29 @@ static __always_inline void kvm_cpu_cap_check_and_set(unsigned int x86_feature, kvm_cpu_cap_set(x86_feature, overlay_mask); } +static __always_inline u32 raw_cpuid_get(struct cpuid_reg cpuid) +{ + struct kvm_cpuid_entry2 entry; + u32 base; + + /* + * KVM only supports features defined by Intel (0x0), AMD (0x80000000), + * and Centaur (0xc0000000). WARN if a feature for new vendor base is + * defined, as this and other code would need to be updated. + */ + base = cpuid.function & 0xffff0000; + if (WARN_ON_ONCE(base && base != 0x80000000 && base != 0xc0000000)) + return 0; + + if (cpuid_eax(base) < cpuid.function) + return 0; + + cpuid_count(cpuid.function, cpuid.index, + &entry.eax, &entry.ebx, &entry.ecx, &entry.edx); + + return *__cpuid_entry_get_reg(&entry, cpuid.reg); +} + static __always_inline void kvm_cpu_cap_init_mf(u32 leaf, u32 features, u32 overlay_mask) { WARN_ON_ONCE(!kvm_is_configuring_cpu_caps); @@ -270,6 +293,16 @@ static __always_inline void kvm_cpu_cap_init_mf(u32 leaf, u32 features, u32 over } } +static __always_inline void kvm_cpu_cap_check_and_init_mf(u32 leaf, u32 features, u32 overlay_mask) +{ + reverse_cpuid_check(leaf); + /* This function is used for kvm only cpuid leafs. */ + BUILD_BUG_ON(leaf < NCAPINTS); + features &= raw_cpuid_get(reverse_cpuid[leaf]); + + kvm_cpu_cap_init_mf(leaf, features, overlay_mask); +} + static __always_inline bool guest_pv_has(struct kvm_vcpu *vcpu, unsigned int kvm_feature) { -- 2.46.0