]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: VMX: Pass XFD_ERR as pseudo-payload when injecting #NM
authorSean Christopherson <seanjc@google.com>
Tue, 1 Oct 2024 05:00:57 +0000 (22:00 -0700)
committerSean Christopherson <seanjc@google.com>
Tue, 25 Feb 2025 17:35:44 +0000 (09:35 -0800)
Pass XFD_ERR via KVM's exception payload mechanism when injecting an #NM
after interception so that XFD_ERR can be propagated to FRED's event_data
field without needing a dedicated field (which would need to be migrated).

For non-FRED vCPUs, this is a glorified NOP as
kvm_deliver_exception_payload() will simply do nothing (which is desirable
and correct).

Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Tested-by: Shan Kang <shan.kang@intel.com>
Link: https://lore.kernel.org/r/20241001050110.3643764-15-xin@zytor.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/vmx/vmx.c

index 24fcab183c1847dc65253adb3149f7f276e5cedb..ec4527e7fdf9c6313e4a06d52fb27935506e3c6e 100644 (file)
@@ -5215,6 +5215,12 @@ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
               (kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
 }
 
+static bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.guest_fpu.fpstate->xfd &&
+              !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
+}
+
 static int handle_exception_nmi(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -5241,7 +5247,8 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
         * point.
         */
        if (is_nm_fault(intr_info)) {
-               kvm_queue_exception(vcpu, NM_VECTOR);
+               kvm_queue_exception_p(vcpu, NM_VECTOR,
+                                     is_xfd_nm_fault(vcpu) ? vcpu->arch.guest_fpu.xfd_err : 0);
                return 1;
        }
 
@@ -6997,14 +7004,13 @@ static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
         *
         * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
         * interception may have been caused by L1 interception.  Per the SDM,
-        * XFD_ERR is not modified if CR0.TS=1.
+        * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
         *
         * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
         * unlike CR2 and DR6, the value is not a payload that is attached to
         * the #NM exception.
         */
-       if (vcpu->arch.guest_fpu.fpstate->xfd &&
-           !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS))
+       if (is_xfd_nm_fault(vcpu))
                rdmsrl(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
 }