lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 083/207] KVM: x86: check PIR even for vCPUs with disabled APICv
    Date
    From: Paolo Bonzini <pbonzini@redhat.com>

    commit 37c4dbf337c5c2cdb24365ffae6ed70ac1e74d7a upstream.

    The IRTE for an assigned device can trigger a POSTED_INTR_VECTOR even
    if APICv is disabled on the vCPU that receives it. In that case, the
    interrupt will just cause a vmexit and leave the ON bit set together
    with the PIR bit corresponding to the interrupt.

    Right now, the interrupt would not be delivered until APICv is re-enabled.
    However, fixing this is just a matter of always doing the PIR->IRR
    synchronization, even if the vCPU has temporarily disabled APICv.

    This is not a problem for performance, or if anything it is an
    improvement. First, in the common case where vcpu->arch.apicv_active is
    true, one fewer check has to be performed. Second, static_call_cond will
    elide the function call if APICv is not present or disabled. Finally,
    in the case for AMD hardware we can remove the sync_pir_to_irr callback:
    it is only needed for apic_has_interrupt_for_ppr, and that function
    already has a fallback for !APICv.

    Cc: stable@vger.kernel.org
    Co-developed-by: Sean Christopherson <seanjc@google.com>
    Signed-off-by: Sean Christopherson <seanjc@google.com>
    Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
    Reviewed-by: David Matlack <dmatlack@google.com>
    Message-Id: <20211123004311.2954158-4-pbonzini@redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/x86/kvm/lapic.c | 2 +-
    arch/x86/kvm/svm/svm.c | 1 -
    arch/x86/kvm/x86.c | 18 +++++++++---------
    3 files changed, 10 insertions(+), 11 deletions(-)

    --- a/arch/x86/kvm/lapic.c
    +++ b/arch/x86/kvm/lapic.c
    @@ -707,7 +707,7 @@ static void pv_eoi_clr_pending(struct kv
    static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr)
    {
    int highest_irr;
    - if (apic->vcpu->arch.apicv_active)
    + if (kvm_x86_ops.sync_pir_to_irr)
    highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu);
    else
    highest_irr = apic_find_highest_irr(apic);
    --- a/arch/x86/kvm/svm/svm.c
    +++ b/arch/x86/kvm/svm/svm.c
    @@ -4592,7 +4592,6 @@ static struct kvm_x86_ops svm_x86_ops __
    .load_eoi_exitmap = svm_load_eoi_exitmap,
    .hwapic_irr_update = svm_hwapic_irr_update,
    .hwapic_isr_update = svm_hwapic_isr_update,
    - .sync_pir_to_irr = kvm_lapic_find_highest_irr,
    .apicv_post_state_restore = avic_post_state_restore,

    .set_tss_addr = svm_set_tss_addr,
    --- a/arch/x86/kvm/x86.c
    +++ b/arch/x86/kvm/x86.c
    @@ -4405,8 +4405,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
    static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
    struct kvm_lapic_state *s)
    {
    - if (vcpu->arch.apicv_active)
    - static_call(kvm_x86_sync_pir_to_irr)(vcpu);
    + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);

    return kvm_apic_get_state(vcpu, s);
    }
    @@ -9433,8 +9432,7 @@ static void vcpu_scan_ioapic(struct kvm_
    if (irqchip_split(vcpu->kvm))
    kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors);
    else {
    - if (vcpu->arch.apicv_active)
    - static_call(kvm_x86_sync_pir_to_irr)(vcpu);
    + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);
    if (ioapic_in_kernel(vcpu->kvm))
    kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors);
    }
    @@ -9704,10 +9702,12 @@ static int vcpu_enter_guest(struct kvm_v

    /*
    * This handles the case where a posted interrupt was
    - * notified with kvm_vcpu_kick.
    + * notified with kvm_vcpu_kick. Assigned devices can
    + * use the POSTED_INTR_VECTOR even if APICv is disabled,
    + * so do it even if APICv is disabled on this vCPU.
    */
    - if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active)
    - static_call(kvm_x86_sync_pir_to_irr)(vcpu);
    + if (kvm_lapic_enabled(vcpu))
    + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);

    if (kvm_vcpu_exit_request(vcpu)) {
    vcpu->mode = OUTSIDE_GUEST_MODE;
    @@ -9743,8 +9743,8 @@ static int vcpu_enter_guest(struct kvm_v
    if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST))
    break;

    - if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active)
    - static_call(kvm_x86_sync_pir_to_irr)(vcpu);
    + if (kvm_lapic_enabled(vcpu))
    + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu);

    if (unlikely(kvm_vcpu_exit_request(vcpu))) {
    exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED;

    \
     
     \ /
      Last update: 2021-12-06 17:11    [W:2.828 / U:0.304 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site