KVM: SVM: Emulate SYSENTER RIP/RSP behavior for all Intel compat vCPUs
authorSean Christopherson <seanjc@google.com>
Fri, 5 Apr 2024 23:56:00 +0000 (16:56 -0700)
committerSean Christopherson <seanjc@google.com>
Mon, 10 Jun 2024 21:29:38 +0000 (14:29 -0700)
Emulate bits 63:32 of the SYSENTER_R{I,S}P MSRs for all vCPUs that are
compatible with Intel's architecture, not just strictly vCPUs that have
vendor==Intel.  The behavior of bits 63:32 is architecturally defined in
the SDM, i.e. not some uarch specific quirk of Intel CPUs.

Link: https://lore.kernel.org/r/20240405235603.1173076-8-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/cpuid.h
arch/x86/kvm/svm/svm.c

index 23dbb9eb277c7465f19bc5af137b79d5a2b894d1..03d015e9ce33ed77aceab334e3399793e84e7c34 100644 (file)
@@ -112,14 +112,6 @@ static inline bool guest_cpuid_is_amd_or_hygon(struct kvm_vcpu *vcpu)
                is_guest_vendor_hygon(best->ebx, best->ecx, best->edx));
 }
 
-static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
-{
-       struct kvm_cpuid_entry2 *best;
-
-       best = kvm_find_cpuid_entry(vcpu, 0);
-       return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
-}
-
 static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.is_amd_compatible;
index c8dc25886c16581c2e89e94b685fa6c95ad4fc7a..d9741ae322c4c500408f72d90d99debd824808c6 100644 (file)
@@ -1196,7 +1196,7 @@ static inline void init_vmcb_after_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
-       if (guest_cpuid_is_intel(vcpu)) {
+       if (guest_cpuid_is_intel_compatible(vcpu)) {
                /*
                 * We must intercept SYSENTER_EIP and SYSENTER_ESP
                 * accesses because the processor only stores 32 bits.
@@ -2855,12 +2855,12 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                break;
        case MSR_IA32_SYSENTER_EIP:
                msr_info->data = (u32)svm->vmcb01.ptr->save.sysenter_eip;
-               if (guest_cpuid_is_intel(vcpu))
+               if (guest_cpuid_is_intel_compatible(vcpu))
                        msr_info->data |= (u64)svm->sysenter_eip_hi << 32;
                break;
        case MSR_IA32_SYSENTER_ESP:
                msr_info->data = svm->vmcb01.ptr->save.sysenter_esp;
-               if (guest_cpuid_is_intel(vcpu))
+               if (guest_cpuid_is_intel_compatible(vcpu))
                        msr_info->data |= (u64)svm->sysenter_esp_hi << 32;
                break;
        case MSR_TSC_AUX:
@@ -3083,11 +3083,11 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
                 * 32 bit part of these msrs to support Intel's
                 * implementation of SYSENTER/SYSEXIT.
                 */
-               svm->sysenter_eip_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0;
+               svm->sysenter_eip_hi = guest_cpuid_is_intel_compatible(vcpu) ? (data >> 32) : 0;
                break;
        case MSR_IA32_SYSENTER_ESP:
                svm->vmcb01.ptr->save.sysenter_esp = (u32)data;
-               svm->sysenter_esp_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0;
+               svm->sysenter_esp_hi = guest_cpuid_is_intel_compatible(vcpu) ? (data >> 32) : 0;
                break;
        case MSR_TSC_AUX:
                /*
@@ -4337,11 +4337,11 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_LBRV);
 
        /*
-        * Intercept VMLOAD if the vCPU mode is Intel in order to emulate that
+        * Intercept VMLOAD if the vCPU model is Intel in order to emulate that
         * VMLOAD drops bits 63:32 of SYSENTER (ignoring the fact that exposing
         * SVM on Intel is bonkers and extremely unlikely to work).
         */
-       if (!guest_cpuid_is_intel(vcpu))
+       if (!guest_cpuid_is_intel_compatible(vcpu))
                kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD);
 
        kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_PAUSEFILTER);