KVM: nVMX: Fold requested virtual interrupt check into has_nested_events()
authorSean Christopherson <seanjc@google.com>
Fri, 7 Jun 2024 17:26:08 +0000 (10:26 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 28 Jun 2024 15:59:06 +0000 (08:59 -0700)
Check for a Requested Virtual Interrupt, i.e. a virtual interrupt that is
pending delivery, in vmx_has_nested_events() and drop the one-off
kvm_x86_ops.guest_apic_has_interrupt() hook.

In addition to dropping a superfluous hook, this fixes a bug where KVM
would incorrectly treat virtual interrupts _for L2_ as always enabled due
to kvm_arch_interrupt_allowed(), by way of vmx_interrupt_blocked(),
treating IRQs as enabled if L2 is active and vmcs12 is configured to exit
on IRQs, i.e. KVM would treat a virtual interrupt for L2 as a valid wake
event based on L1's IRQ blocking status.

Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240607172609.3205077-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm-x86-ops.h
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/vmx/main.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/x86_ops.h
arch/x86/kvm/x86.c

index 566d19b024836519c0ef54f6ecf025775c8eadcd..f91d413d7de1b25f496ef92f871f904265840a89 100644 (file)
@@ -85,7 +85,6 @@ KVM_X86_OP_OPTIONAL(update_cr8_intercept)
 KVM_X86_OP(refresh_apicv_exec_ctrl)
 KVM_X86_OP_OPTIONAL(hwapic_irr_update)
 KVM_X86_OP_OPTIONAL(hwapic_isr_update)
-KVM_X86_OP_OPTIONAL_RET0(guest_apic_has_interrupt)
 KVM_X86_OP_OPTIONAL(load_eoi_exitmap)
 KVM_X86_OP_OPTIONAL(set_virtual_apic_mode)
 KVM_X86_OP_OPTIONAL(set_apic_access_page_addr)
index b3b796f06801042a74da5ed55c10203ba8500998..2715c1d6a4dbac1c3913983cb87b58968843f1d6 100644 (file)
@@ -1715,7 +1715,6 @@ struct kvm_x86_ops {
        void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
        void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
        void (*hwapic_isr_update)(int isr);
-       bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
        void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
        void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
        void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu);
index d4ed681785fd649d0dcbcfa4a2c1064546a4dca1..547fca3709febdfaf2d676a4daaf2d28288a55b0 100644 (file)
@@ -97,7 +97,6 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
        .required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS,
        .hwapic_irr_update = vmx_hwapic_irr_update,
        .hwapic_isr_update = vmx_hwapic_isr_update,
-       .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
        .sync_pir_to_irr = vmx_sync_pir_to_irr,
        .deliver_interrupt = vmx_deliver_interrupt,
        .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt,
index 732340ff3300ab2140417cfc32a429e1e6f528c5..7c57d6524f7543e67430739d58113966f2e8e4d9 100644 (file)
@@ -4060,6 +4060,10 @@ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
 
        vppr = *((u32 *)(vapic + APIC_PROCPRI));
 
+       max_irr = vmx_get_rvi();
+       if ((max_irr & 0xf0) > (vppr & 0xf0))
+               return true;
+
        if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
            pi_test_on(vmx->nested.pi_desc)) {
                max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
index 7efb52328e5de39055161cf2914a830181d37d92..8ccdba6360aac13b46c8fe7253cdeb6ef0a2ee02 100644 (file)
@@ -4105,26 +4105,6 @@ void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu)
        }
 }
 
-bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       void *vapic_page;
-       u32 vppr;
-       int rvi;
-
-       if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
-               !nested_cpu_has_vid(get_vmcs12(vcpu)) ||
-               WARN_ON_ONCE(!vmx->nested.virtual_apic_map.gfn))
-               return false;
-
-       rvi = vmx_get_rvi();
-
-       vapic_page = vmx->nested.virtual_apic_map.hva;
-       vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
-
-       return ((rvi & 0xf0) > (vppr & 0xf0));
-}
-
 void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
index 502704596c8324b9b909ceb7cb3432ec94c7642c..d404227c164d60c45782aba63d0b051ad0f1db79 100644 (file)
@@ -49,7 +49,6 @@ void vmx_apicv_pre_state_restore(struct kvm_vcpu *vcpu);
 bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason);
 void vmx_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr);
 void vmx_hwapic_isr_update(int max_isr);
-bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu);
 int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu);
 void vmx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
                           int trig_mode, int vector);
index 8cce76b93d83064f8cb5f9cc6551766343e553d3..cacca83b06aace92f15889891f3033493637f680 100644 (file)
@@ -13108,12 +13108,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                kvm_arch_free_memslot(kvm, old);
 }
 
-static inline bool kvm_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
-{
-       return (is_guest_mode(vcpu) &&
-               static_call(kvm_x86_guest_apic_has_interrupt)(vcpu));
-}
-
 static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
 {
        if (!list_empty_careful(&vcpu->async_pf.done))
@@ -13147,9 +13141,7 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
        if (kvm_test_request(KVM_REQ_UPDATE_PROTECTED_GUEST_STATE, vcpu))
                return true;
 
-       if (kvm_arch_interrupt_allowed(vcpu) &&
-           (kvm_cpu_has_interrupt(vcpu) ||
-           kvm_guest_apic_has_interrupt(vcpu)))
+       if (kvm_arch_interrupt_allowed(vcpu) && kvm_cpu_has_interrupt(vcpu))
                return true;
 
        if (kvm_hv_has_stimer_pending(vcpu))