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:
Li Fei1 2020-04-08 09:10:38 +08:00 committed by wenlingz
parent 3c64d59a18
commit e3f2f98c66
3 changed files with 25 additions and 57 deletions

View File

@ -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;
}
/*

View File

@ -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)

View File

@ -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);