From 0c347e607a19f320f2fc52d921e1fcde731c7188 Mon Sep 17 00:00:00 2001 From: "Li, Fei1" Date: Thu, 21 Mar 2019 00:54:02 +0800 Subject: [PATCH] hv: vlapic: wrap APICv check pending delivery interrupt When in fully APICv mode, we enable VID. All pending delivery interrupts will inject to VM before VM entry. So there is no pending delivery interrupt. However, if VID is not enabled, we can only inject pending delivery interrupt one by one. So we always need to do this check. Tracked-On: #1842 Signed-off-by: Li, Fei1 --- .../hld/hv-virt-interrupt.rst | 3 -- hypervisor/arch/x86/guest/virq.c | 27 +----------------- hypervisor/arch/x86/guest/vlapic.c | 28 ++++++++++++++++++- hypervisor/arch/x86/guest/vlapic_priv.h | 1 + hypervisor/include/arch/x86/guest/vlapic.h | 17 +---------- 5 files changed, 30 insertions(+), 46 deletions(-) diff --git a/doc/developer-guides/hld/hv-virt-interrupt.rst b/doc/developer-guides/hld/hv-virt-interrupt.rst index 8dc3638ff..bbb3b25e3 100644 --- a/doc/developer-guides/hld/hv-virt-interrupt.rst +++ b/doc/developer-guides/hld/hv-virt-interrupt.rst @@ -94,9 +94,6 @@ an interrupt, for example: These APIs will finish by making a request for *ACRN_REQUEST_EVENT.* -.. doxygenfunction:: vlapic_find_deliverable_intr - :project: Project ACRN - .. doxygenfunction:: vlapic_set_local_intr :project: Project ACRN diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 31c505807..0ff4dbf66 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -104,31 +104,6 @@ static bool is_guest_irq_enabled(struct acrn_vcpu *vcpu) return status; } -/* - * This function is only for case that APICv/VID is not supported. - */ -static bool vcpu_pending_request(struct acrn_vcpu *vcpu) -{ - struct acrn_vlapic *vlapic; - uint32_t vector = 0U; - bool pending = false; - - if (!is_apicv_advanced_feature_supported()) { - /* Query vLapic to get vector to inject */ - vlapic = vcpu_vlapic(vcpu); - - /* check and raise request if we have a deliverable irq in LAPIC IRR */ - if (vlapic_find_deliverable_intr(vlapic, &vector)) { - /* we have pending IRR */ - vcpu_make_request(vcpu, ACRN_REQUEST_EVENT); - } - - pending = vcpu->arch.pending_req != 0UL; - } - - return pending; -} - void vcpu_make_request(struct acrn_vcpu *vcpu, uint16_t eventid) { bitmap_set_lock(eventid, &vcpu->arch.pending_req); @@ -480,7 +455,7 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) */ if (arch->irq_window_enabled != 1U) { if (bitmap_test(ACRN_REQUEST_EXTINT, pending_req_bits) || - vcpu_pending_request(vcpu)) { + vlapic_has_pending_delivery_intr(vcpu)) { tmp = exec_vmread32(VMX_PROC_VM_EXEC_CONTROLS); tmp |= VMX_PROCBASED_CTLS_IRQ_WIN; exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS, tmp); diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index 501ed8eb1..7ed5b2e97 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1351,7 +1351,7 @@ static inline uint32_t vlapic_find_highest_irr(const struct acrn_vlapic *vlapic) * result of calling this function. * This function is only for case that APICv/VID is NOT supported. */ -bool vlapic_find_deliverable_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr) +static bool vlapic_find_deliverable_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr) { const struct lapic_regs *lapic = &(vlapic->apic_page); uint32_t vec; @@ -2311,6 +2311,30 @@ bool vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool return apicv_ops->inject_intr(vlapic, guest_irq_enabled, injected); } +static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) +{ + uint32_t vector; + struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu); + + /* check and raise request if we have a deliverable irq in LAPIC IRR */ + if (vlapic_find_deliverable_intr(vlapic, &vector)) { + /* we have pending IRR */ + vcpu_make_request(vcpu, ACRN_REQUEST_EVENT); + } + + return vcpu->arch.pending_req != 0UL; +} + +static bool apicv_advanced_has_pending_delivery_intr(__unused struct acrn_vcpu *vcpu) +{ + return false; +} + +bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) +{ + return apicv_ops->has_pending_delivery_intr(vcpu); +} + int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu) { int32_t err = 0; @@ -2503,11 +2527,13 @@ int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu) static const struct acrn_apicv_ops apicv_basic_ops = { .accept_intr = apicv_basic_accept_intr, .inject_intr = apicv_basic_inject_intr, + .has_pending_delivery_intr = apicv_basic_has_pending_delivery_intr, }; static const struct acrn_apicv_ops apicv_advanced_ops = { .accept_intr = apicv_advanced_accept_intr, .inject_intr = apicv_advanced_inject_intr, + .has_pending_delivery_intr = apicv_advanced_has_pending_delivery_intr, }; /* diff --git a/hypervisor/arch/x86/guest/vlapic_priv.h b/hypervisor/arch/x86/guest/vlapic_priv.h index e50e2c028..c3bd1708d 100644 --- a/hypervisor/arch/x86/guest/vlapic_priv.h +++ b/hypervisor/arch/x86/guest/vlapic_priv.h @@ -85,6 +85,7 @@ struct acrn_apicv_ops { void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level); bool (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); + bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu); }; #endif /* VLAPIC_PRIV_H */ diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index 246c06f5b..44e611eb4 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -119,23 +119,8 @@ void vlapic_set_apicv_ops(void); * @{ */ - -/** - * @brief Find a deliverable virtual interrupts for vLAPIC in irr. - * - * @param[in] vlapic Pointer to target vLAPIC data structure - * @param[inout] vecptr Pointer to vector buffer and will be filled - * with eligible vector if any. - * - * @retval false There is no deliverable pending vector. - * @retval true There is deliverable vector. - * - * @remark The vector does not automatically transition to the ISR as a - * result of calling this function. - */ -bool vlapic_find_deliverable_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr); - bool vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); +bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu); /** * @brief Get physical address to PIR description.