Message ID | 20191009004142.225377-4-aaronlewis@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/6] KVM: VMX: Remove unneeded check for X86_FEATURE_XSAVE | expand |
On Tue, Oct 08, 2019 at 05:41:40PM -0700, Aaron Lewis wrote: > Add the function guest_cpuid_set() to allow a bit in the guest cpuid to > be set. This is complementary to the guest_cpuid_clear() function. > > Also, set the XSAVES bit in the guest cpuid if the host has the same bit > set and guest has XSAVE bit set. This is to ensure that XSAVES will be > enumerated in the guest CPUID if XSAVES can be used in the guest. > > Reviewed-by: Jim Mattson <jmattson@google.com> > Signed-off-by: Aaron Lewis <aaronlewis@google.com> > --- > arch/x86/kvm/cpuid.h | 9 +++++++++ > arch/x86/kvm/svm.c | 4 ++++ > 2 files changed, 13 insertions(+) > > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h > index d78a61408243..420ceea02fd1 100644 > --- a/arch/x86/kvm/cpuid.h > +++ b/arch/x86/kvm/cpuid.h > @@ -113,6 +113,15 @@ static __always_inline void guest_cpuid_clear(struct kvm_vcpu *vcpu, unsigned x8 > *reg &= ~bit(x86_feature); > } > > +static __always_inline void guest_cpuid_set(struct kvm_vcpu *vcpu, unsigned x86_feature) > +{ > + int *reg; > + > + reg = guest_cpuid_get_register(vcpu, x86_feature); > + if (reg) > + *reg |= ~bit(x86_feature); > +} > + Sounds like it's to set the bit, is it: *reg |= bit(x86_feature)? > static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu) > { > struct kvm_cpuid_entry2 *best; > diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c > index 65223827c675..2522a467bbc0 100644 > --- a/arch/x86/kvm/svm.c > +++ b/arch/x86/kvm/svm.c > @@ -5887,6 +5887,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) > { > struct vcpu_svm *svm = to_svm(vcpu); > > + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && > + boot_cpu_has(X86_FEATURE_XSAVES)) > + guest_cpuid_set(vcpu, X86_FEATURE_XSAVES); > + > /* Update nrips enabled cache */ > svm->nrips_enabled = !!guest_cpuid_has(&svm->vcpu, X86_FEATURE_NRIPS); > > -- > 2.23.0.581.g78d2f28ef7-goog
On 09/10/19 03:42, Yang Weijiang wrote: > + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && > + boot_cpu_has(X86_FEATURE_XSAVES)) > + guest_cpuid_set(vcpu, X86_FEATURE_XSAVES); > + This is incorrect, as it would cause a change in the guest ABI when migrating from an XSAVES-enabled processor to one that doesn't have it. As long as IA32_XSS is 0, XSAVES is indistinguishable from XSAVEC, so it's okay if the guest "tries" to run it despite the bit being clear in CPUID. Paolo
On Tue, Oct 8, 2019 at 11:32 PM Paolo Bonzini <pbonzini@redhat.com> wrote: > > On 09/10/19 03:42, Yang Weijiang wrote: > > + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && > > + boot_cpu_has(X86_FEATURE_XSAVES)) > > + guest_cpuid_set(vcpu, X86_FEATURE_XSAVES); > > + > > This is incorrect, as it would cause a change in the guest ABI when > migrating from an XSAVES-enabled processor to one that doesn't have it. > > As long as IA32_XSS is 0, XSAVES is indistinguishable from XSAVEC, so > it's okay if the guest "tries" to run it despite the bit being clear in > CPUID. My bad. When Aaron and I were discussing this, I expressed concern about guest behavior on a future day when (a) AMD supports a non-zero IA32_XSS, and (b) Linux supports an intercepting non-zero IA32_XSS. One could argue that if XSAVES isn't enumerated, the guest gets what it deserves for trying it anyway. Or, one could argue that the decision to swap guest/host IA32_XSS values on VM-entry/VM-exit shouldn't be predicated on whether or not the guest CPUID enumerates XSAVES. I'm going to suggest the latter. How would you feel about having {vmx,svm}_cpuid_update set a boolean in kvm_vcpu_arch that indicates whether or not the guest can execute XSAVES, regardless of what is enumerated in the guest CPUID? The wrmsr(IA32_XSS) in the VM-entry/VM-exit path would then query that boolean rather than guest_cpuid_has(XSAVES).
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index d78a61408243..420ceea02fd1 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -113,6 +113,15 @@ static __always_inline void guest_cpuid_clear(struct kvm_vcpu *vcpu, unsigned x8 *reg &= ~bit(x86_feature); } +static __always_inline void guest_cpuid_set(struct kvm_vcpu *vcpu, unsigned x86_feature) +{ + int *reg; + + reg = guest_cpuid_get_register(vcpu, x86_feature); + if (reg) + *reg |= ~bit(x86_feature); +} + static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 65223827c675..2522a467bbc0 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -5887,6 +5887,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && + boot_cpu_has(X86_FEATURE_XSAVES)) + guest_cpuid_set(vcpu, X86_FEATURE_XSAVES); + /* Update nrips enabled cache */ svm->nrips_enabled = !!guest_cpuid_has(&svm->vcpu, X86_FEATURE_NRIPS);