mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 12:42:54 +00:00
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 <fei1.li@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
3c64d59a18
commit
e3f2f98c66
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user