]> www.infradead.org Git - users/hch/misc.git/commitdiff
KVM: nVMX: Process events on nested VM-Exit if injectable IRQ or NMI is pending
authorSean Christopherson <seanjc@google.com>
Mon, 24 Feb 2025 23:55:37 +0000 (15:55 -0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 26 Feb 2025 09:17:32 +0000 (04:17 -0500)
Process pending events on nested VM-Exit if the vCPU has an injectable IRQ
or NMI, as the event may have become pending while L2 was active, i.e. may
not be tracked in the context of vmcs01.  E.g. if L1 has passed its APIC
through to L2 and an IRQ arrives while L2 is active, then KVM needs to
request an IRQ window prior to running L1, otherwise delivery of the IRQ
will be delayed until KVM happens to process events for some other reason.

The missed failure is detected by vmx_apic_passthrough_tpr_threshold_test
in KVM-Unit-Tests, but has effectively been masked due to a flaw in KVM's
PIC emulation that causes KVM to make spurious KVM_REQ_EVENT requests (and
apparently no one ever ran the test with split IRQ chips).

Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20250224235542.2562848-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/nested.c

index 8a7af02d466e9ff738c255533c09e1d34cb7c452..ed8a3cb5396127aebde5cee5172a023f0d7bc983 100644 (file)
@@ -5084,6 +5084,17 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
 
                load_vmcs12_host_state(vcpu, vmcs12);
 
+               /*
+                * Process events if an injectable IRQ or NMI is pending, even
+                * if the event is blocked (RFLAGS.IF is cleared on VM-Exit).
+                * If an event became pending while L2 was active, KVM needs to
+                * either inject the event or request an IRQ/NMI window.  SMIs
+                * don't need to be processed as SMM is mutually exclusive with
+                * non-root mode.  INIT/SIPI don't need to be checked as INIT
+                * is blocked post-VMXON, and SIPIs are ignored.
+                */
+               if (kvm_cpu_has_injectable_intr(vcpu) || vcpu->arch.nmi_pending)
+                       kvm_make_request(KVM_REQ_EVENT, vcpu);
                return;
        }