From e3f2f98c66dabe1b1db9e63a96ee06b25dc7c213 Mon Sep 17 00:00:00 2001 From: Li Fei1 Date: Wed, 8 Apr 2020 09:10:38 +0800 Subject: [PATCH] hv: virq: refine pending event inject sequence Inject pending exception prior pending interrupt to complete the previous instruction. Tracked-On: #1842 Signed-off-by: Li Fei1 Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/virq.c | 58 ++++++---------------- hypervisor/arch/x86/guest/vlapic.c | 20 +++----- hypervisor/include/arch/x86/guest/vlapic.h | 4 +- 3 files changed, 25 insertions(+), 57 deletions(-) diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 97071b222..251bc8147 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -231,9 +231,15 @@ int32_t vcpu_queue_exception(struct acrn_vcpu *vcpu, uint32_t vector_arg, uint32 return ret; } -static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector) +/* + * @pre vcpu->arch.exception_info.exception < 0x20U + */ +static bool vcpu_inject_exception(struct acrn_vcpu *vcpu) { + bool injected = false; + if (bitmap_test_and_clear_lock(ACRN_REQUEST_EXCP, &vcpu->arch.pending_req)) { + uint32_t vector = vcpu->arch.exception_info.exception; if ((exception_type[vector] & EXCEPTION_ERROR_CODE_VALID) != 0U) { exec_vmwrite32(VMX_ENTRY_EXCEPTION_ERROR_CODE, @@ -255,31 +261,8 @@ static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector) if (get_exception_type(vector) == EXCEPTION_FAULT) { vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_RF); } - } -} -static bool vcpu_inject_hi_exception(struct acrn_vcpu *vcpu) -{ - bool injected = false; - uint32_t vector = vcpu->arch.exception_info.exception; - - if ((vector == IDT_MC) || (vector == IDT_BP) || (vector == IDT_DB)) { - vcpu_inject_exception(vcpu, vector); - injected = true; - } - - return injected; -} - -static bool vcpu_inject_lo_exception(struct acrn_vcpu *vcpu) -{ - uint32_t vector = vcpu->arch.exception_info.exception; - bool injected = false; - - /* high priority exception already be injected */ - if (vector <= NR_MAX_VECTOR) { - vcpu_inject_exception(vcpu, vector); - injected = true; + injected = true; } return injected; @@ -371,7 +354,7 @@ int32_t external_interrupt_vmexit_handler(struct acrn_vcpu *vcpu) return ret; } -static inline bool acrn_inject_pending_intr(struct acrn_vcpu *vcpu, +static inline void acrn_inject_pending_intr(struct acrn_vcpu *vcpu, uint64_t *pending_req_bits, bool injected); int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) @@ -407,9 +390,10 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) vcpu_set_vmcs_eoi_exit(vcpu); } - /* SDM Vol 3 - table 6-2, inject high priority exception before - * maskable hardware interrupt */ - injected = vcpu_inject_hi_exception(vcpu); + /* + * Inject pending exception prior pending interrupt to complete the previous instruction. + */ + injected = vcpu_inject_exception(vcpu); if (!injected) { /* inject NMI before maskable hardware interrupt */ @@ -439,11 +423,7 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) } } - if (!acrn_inject_pending_intr(vcpu, pending_req_bits, injected)) { - /* if there is no eligible vector before this point */ - /* SDM Vol3 table 6-2, inject lowpri exception */ - (void)vcpu_inject_lo_exception(vcpu); - } + acrn_inject_pending_intr(vcpu, pending_req_bits, injected); /* * If "virtual-interrupt delivered" is enabled, CPU will evaluate @@ -478,11 +458,7 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) return ret; } -/* - * @retval true 1 when INT is injected to guest. - * @retval false when there is no eligible pending vector. - */ -static inline bool acrn_inject_pending_intr(struct acrn_vcpu *vcpu, +static inline void acrn_inject_pending_intr(struct acrn_vcpu *vcpu, uint64_t *pending_req_bits, bool injected) { bool ret = injected; @@ -497,10 +473,8 @@ static inline bool acrn_inject_pending_intr(struct acrn_vcpu *vcpu, } if (bitmap_test_and_clear_lock(ACRN_REQUEST_EVENT, pending_req_bits)) { - ret = vlapic_inject_intr(vcpu_vlapic(vcpu), guest_irq_enabled, ret); + vlapic_inject_intr(vcpu_vlapic(vcpu), guest_irq_enabled, ret); } - - return ret; } /* diff --git a/hypervisor/arch/x86/guest/vlapic.c b/hypervisor/arch/x86/guest/vlapic.c index d976324d3..0eaaddbab 100644 --- a/hypervisor/arch/x86/guest/vlapic.c +++ b/hypervisor/arch/x86/guest/vlapic.c @@ -1728,11 +1728,10 @@ static void ptapic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, __un vlapic->vm->vm_id, vlapic->vcpu->vcpu_id, vector); } -static bool ptapic_inject_intr(struct acrn_vlapic *vlapic, +static void ptapic_inject_intr(struct acrn_vlapic *vlapic, __unused bool guest_irq_enabled, __unused bool injected) { pr_err("Invalid op %s, VM%u, vCPU%u", __func__, vlapic->vm->vm_id, vlapic->vcpu->vcpu_id); - return injected; } static bool ptapic_has_pending_delivery_intr(__unused struct acrn_vcpu *vcpu) @@ -2242,23 +2241,20 @@ vlapic_apicv_get_apic_page_addr(struct acrn_vlapic *vlapic) return hva2hpa(&(vlapic->apic_page)); } -static bool apicv_basic_inject_intr(struct acrn_vlapic *vlapic, +static void apicv_basic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected) { uint32_t vector = 0U; - bool ret = injected; + if (guest_irq_enabled && (!injected)) { vlapic_update_ppr(vlapic); if (vlapic_find_deliverable_intr(vlapic, &vector)) { exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector); vlapic_get_deliverable_intr(vlapic, vector); - ret = true; } } vlapic_update_tpr_threshold(vlapic); - - return ret; } /* @@ -2328,8 +2324,8 @@ static void vlapic_apicv_inject_pir(struct acrn_vlapic *vlapic) } } -static bool apicv_advanced_inject_intr(struct acrn_vlapic *vlapic, - __unused bool guest_irq_enabled, bool injected) +static void apicv_advanced_inject_intr(struct acrn_vlapic *vlapic, + __unused bool guest_irq_enabled, __unused bool injected) { /* * From SDM Vol3 26.3.2.5: @@ -2345,13 +2341,11 @@ static bool apicv_advanced_inject_intr(struct acrn_vlapic *vlapic, * needed. And then try to handle vmcs event injection. */ vlapic_apicv_inject_pir(vlapic); - - return injected; } -bool vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected) +void vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected) { - return vlapic->ops->inject_intr(vlapic, guest_irq_enabled, injected); + vlapic->ops->inject_intr(vlapic, guest_irq_enabled, injected); } static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu) diff --git a/hypervisor/include/arch/x86/guest/vlapic.h b/hypervisor/include/arch/x86/guest/vlapic.h index 5c9d193bc..c9419e881 100644 --- a/hypervisor/include/arch/x86/guest/vlapic.h +++ b/hypervisor/include/arch/x86/guest/vlapic.h @@ -90,7 +90,7 @@ struct acrn_vlapic { 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); + void (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu); bool (*has_pending_intr)(struct acrn_vcpu *vcpu); bool (*apic_read_access_may_valid)(uint32_t offset); @@ -110,7 +110,7 @@ void vlapic_set_apicv_ops(void); * @{ */ -bool vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); +void vlapic_inject_intr(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected); bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu); bool vlapic_has_pending_intr(struct acrn_vcpu *vcpu);