When EOI virtualization is performed on VMX, kvm_apic_set_eoi_accelerated() is called upon EXIT_REASON_EOI_INDUCED but unlike its non-accelerated apic_set_eoi() sibling, Hyper-V SINT vectors are left unhandled. Send EOI to Hyper-V SINT vectors when handling acclerated EOI-induced VM-Exits. KVM Hyper-V needs to handle the SINT EOI irrespective of whether the EOI is acclerated or not. Rename kvm_apic_set_eoi_accelerated() to kvm_apic_set_eoi() and let the non-accelerated helper call the "acclerated" version. That will document the delta between the non-accelerated path and the accelerated path. In addition, guarantee to trace even if there's no valid vector to EOI in the non-accelerated path in order to keep the semantics of the function intact. Fixes: 5c919412fe61 ("kvm/x86: Hyper-V synthetic interrupt controller") Cc: <stable@xxxxxxxxxxxxxxx> Tested-by: Wang Guangju <wangguangju@xxxxxxxxx> Suggested-by: Sean Christopherson <seanjc@xxxxxxxxxx> Suggested-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> Co-developed-by: Li Rongqing <lirongqing@xxxxxxxxx> Signed-off-by: Wang Guangju <wangguangju@xxxxxxxxx> --- v1 -> v2: Updated the commit message and implement a new inline function of apic_set_eoi_vector() v2 -> v3: Updated the subject and commit message, drop func apic_set_eoi_vector() and rename kvm_apic_set_eoi_accelerated() to kvm_apic_set_eoi() arch/x86/kvm/lapic.c | 45 ++++++++++++++++++++++----------------------- arch/x86/kvm/lapic.h | 2 +- arch/x86/kvm/vmx/vmx.c | 3 ++- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index f03facc..b2e72ab 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1269,46 +1269,45 @@ static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector) kvm_ioapic_update_eoi(apic->vcpu, vector, trigger_mode); } +/* + * Send EOI for a valid vector. The caller, or hardware when this is invoked + * after an accelerated EOI VM-Exit, is responsible for updating the vISR and + * vPPR. + */ +void kvm_apic_set_eoi(struct kvm_lapic *apic, int vector) +{ + trace_kvm_eoi(apic, vector); + + if (to_hv_vcpu(apic->vcpu) && + test_bit(vector, to_hv_synic(apic->vcpu)->vec_bitmap)) + kvm_hv_synic_send_eoi(apic->vcpu, vector); + + kvm_ioapic_send_eoi(apic, vector); + kvm_make_request(KVM_REQ_EVENT, apic->vcpu); +} +EXPORT_SYMBOL_GPL(kvm_apic_set_eoi); + static int apic_set_eoi(struct kvm_lapic *apic) { int vector = apic_find_highest_isr(apic); - trace_kvm_eoi(apic, vector); - /* * Not every write EOI will has corresponding ISR, * one example is when Kernel check timer on setup_IO_APIC */ - if (vector == -1) + if (vector == -1) { + trace_kvm_eoi(apic, vector); return vector; + } apic_clear_isr(vector, apic); apic_update_ppr(apic); - if (to_hv_vcpu(apic->vcpu) && - test_bit(vector, to_hv_synic(apic->vcpu)->vec_bitmap)) - kvm_hv_synic_send_eoi(apic->vcpu, vector); + kvm_apic_set_eoi(apic, vector); - kvm_ioapic_send_eoi(apic, vector); - kvm_make_request(KVM_REQ_EVENT, apic->vcpu); return vector; } -/* - * this interface assumes a trap-like exit, which has already finished - * desired side effect including vISR and vPPR update. - */ -void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector) -{ - struct kvm_lapic *apic = vcpu->arch.apic; - - trace_kvm_eoi(apic, vector); - - kvm_ioapic_send_eoi(apic, vector); - kvm_make_request(KVM_REQ_EVENT, apic->vcpu); -} -EXPORT_SYMBOL_GPL(kvm_apic_set_eoi_accelerated); - void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high) { struct kvm_lapic_irq irq; diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 762bf61..48260fa 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -126,7 +126,7 @@ u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu); void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset); -void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector); +void kvm_apic_set_eoi(struct kvm_lapic *apic, int vector); int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 9258468..f8b9eb1 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5519,9 +5519,10 @@ static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu) { unsigned long exit_qualification = vmx_get_exit_qual(vcpu); int vector = exit_qualification & 0xff; + struct kvm_lapic *apic = vcpu->arch.apic; /* EOI-induced VM exit is trap-like and thus no need to adjust IP */ - kvm_apic_set_eoi_accelerated(vcpu, vector); + kvm_apic_set_eoi(apic, vector); return 1; } -- 2.9.4