On Fri, 2024-05-17 at 10:38 -0700, Sean Christopherson wrote: > Add a macro for use in kvm_set_cpu_caps() to automagically initialize > features that KVM wants to support based solely on the CPU's capabilities, > e.g. KVM advertises LA57 support if it's available in hardware, even if > the host kernel isn't utilizing 57-bit virtual addresses. > > Take advantage of the fact that kvm_cpu_cap_mask() adjusts kvm_cpu_caps > based on raw CPUID, i.e. will clear features bits that aren't supported in > hardware, and simply force-set the capability before applying the mask. > > Abusing kvm_cpu_cap_set() is a borderline evil shenanigan, but doing so > avoid extra CPUID lookups, and a future commit will harden the entire > family of *F() macros to assert (at compile time) that every feature being > allowed is part of the capability word being processed, i.e. using a macro > will bring more advantages in the future. Could you explain what do you mean by "extra CPUID lookups"? > > Avoiding CPUID also fixes a largely benign bug where KVM could incorrectly > report LA57 support on Intel CPUs whose max supported CPUID is less than 7, > i.e. if the max supported leaf (<7) happened to have bit 16 set. In > practice, barring a funky virtual machine setup, the bug is benign as all > known CPUs that support VMX also support leaf 7. > > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/x86/kvm/cpuid.c | 17 +++++++++++++---- > 1 file changed, 13 insertions(+), 4 deletions(-) > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c > index 77625a5477b1..a802c09b50ab 100644 > --- a/arch/x86/kvm/cpuid.c > +++ b/arch/x86/kvm/cpuid.c > @@ -70,6 +70,18 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted) > (boot_cpu_has(X86_FEATURE_##name) ? F(name) : 0); \ > }) > > +/* > + * Raw Feature - For features that KVM supports based purely on raw host CPUID, > + * i.e. that KVM virtualizes even if the host kernel doesn't use the feature. > + * Simply force set the feature in KVM's capabilities, raw CPUID support will > + * be factored in by kvm_cpu_cap_mask(). > + */ > +#define RAW_F(name) \ > +({ \ > + kvm_cpu_cap_set(X86_FEATURE_##name); \ > + F(name); \ > +}) > + > /* > * Magic value used by KVM when querying userspace-provided CPUID entries and > * doesn't care about the CPIUD index because the index of the function in > @@ -682,15 +694,12 @@ void kvm_set_cpu_caps(void) > F(AVX512VL)); > > kvm_cpu_cap_mask(CPUID_7_ECX, > - F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | > + F(AVX512VBMI) | RAW_F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) | > F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) | > F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) | > F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/ | > F(SGX_LC) | F(BUS_LOCK_DETECT) > ); > - /* Set LA57 based on hardware capability. */ > - if (cpuid_ecx(7) & F(LA57)) > - kvm_cpu_cap_set(X86_FEATURE_LA57); > > /* > * PKU not yet implemented for shadow paging and requires OSPKE Putting a function call into a macro which evaluates into a bitmask is somewhat misleading, but let it be... IMHO in long term, it might be better to rip the whole huge 'or'ed mess, and replace it with a list of statements, along with comments for all unusual cases. Reviewed-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> Best regards, Maxim Levitsky