| From 6b5ae80a4592cf1e294568c76fd88c8c8f00eb67 Mon Sep 17 00:00:00 2001 |
| From: Vitaly Kuznetsov <vkuznets@redhat.com> |
| Date: Thu, 20 Feb 2020 18:22:05 +0100 |
| Subject: [PATCH] KVM: nVMX: handle nested posted interrupts when apicv is |
| disabled for L1 |
| |
| commit 91a5f413af596ad01097e59bf487eb07cb3f1331 upstream. |
| |
| Even when APICv is disabled for L1 it can (and, actually, is) still |
| available for L2, this means we need to always call |
| vmx_deliver_nested_posted_interrupt() when attempting an interrupt |
| delivery. |
| |
| Suggested-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h |
| index f20a12fc8aec..2a3a84f859e1 100644 |
| --- a/arch/x86/include/asm/kvm_host.h |
| +++ b/arch/x86/include/asm/kvm_host.h |
| @@ -1095,7 +1095,7 @@ struct kvm_x86_ops { |
| 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, hpa_t hpa); |
| - void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); |
| + int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); |
| int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); |
| int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); |
| int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr); |
| diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c |
| index cbec9e67735e..9e99c019b959 100644 |
| --- a/arch/x86/kvm/lapic.c |
| +++ b/arch/x86/kvm/lapic.c |
| @@ -1060,11 +1060,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, |
| apic_clear_vector(vector, apic->regs + APIC_TMR); |
| } |
| |
| - if (vcpu->arch.apicv_active) |
| - kvm_x86_ops->deliver_posted_interrupt(vcpu, vector); |
| - else { |
| + if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) { |
| kvm_lapic_set_irr(vector, apic); |
| - |
| kvm_make_request(KVM_REQ_EVENT, vcpu); |
| kvm_vcpu_kick(vcpu); |
| } |
| diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c |
| index 51145f5d5433..a923f32c7f31 100644 |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -5171,8 +5171,11 @@ static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap) |
| return; |
| } |
| |
| -static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec) |
| +static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec) |
| { |
| + if (!vcpu->arch.apicv_active) |
| + return -1; |
| + |
| kvm_lapic_set_irr(vec, vcpu->arch.apic); |
| smp_mb__after_atomic(); |
| |
| @@ -5181,6 +5184,8 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec) |
| kvm_cpu_get_apicid(vcpu->cpu)); |
| else |
| kvm_vcpu_wake_up(vcpu); |
| + |
| + return 0; |
| } |
| |
| static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu) |
| diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c |
| index 4c414f5213e5..053235096c51 100644 |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -3707,24 +3707,29 @@ static int vmx_deliver_nested_posted_interrupt(struct kvm_vcpu *vcpu, |
| * 2. If target vcpu isn't running(root mode), kick it to pick up the |
| * interrupt from PIR in next vmentry. |
| */ |
| -static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector) |
| +static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector) |
| { |
| struct vcpu_vmx *vmx = to_vmx(vcpu); |
| int r; |
| |
| r = vmx_deliver_nested_posted_interrupt(vcpu, vector); |
| if (!r) |
| - return; |
| + return 0; |
| + |
| + if (!vcpu->arch.apicv_active) |
| + return -1; |
| |
| if (pi_test_and_set_pir(vector, &vmx->pi_desc)) |
| - return; |
| + return 0; |
| |
| /* If a previous notification has sent the IPI, nothing to do. */ |
| if (pi_test_and_set_on(&vmx->pi_desc)) |
| - return; |
| + return 0; |
| |
| if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false)) |
| kvm_vcpu_kick(vcpu); |
| + |
| + return 0; |
| } |
| |
| /* |
| -- |
| 2.7.4 |
| |