mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-20 20:53:46 +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;
|
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)) {
|
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) {
|
if ((exception_type[vector] & EXCEPTION_ERROR_CODE_VALID) != 0U) {
|
||||||
exec_vmwrite32(VMX_ENTRY_EXCEPTION_ERROR_CODE,
|
exec_vmwrite32(VMX_ENTRY_EXCEPTION_ERROR_CODE,
|
||||||
@ -255,30 +261,7 @@ static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector)
|
|||||||
if (get_exception_type(vector) == EXCEPTION_FAULT) {
|
if (get_exception_type(vector) == EXCEPTION_FAULT) {
|
||||||
vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_RF);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +354,7 @@ int32_t external_interrupt_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||||||
return ret;
|
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);
|
uint64_t *pending_req_bits, bool injected);
|
||||||
|
|
||||||
int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu)
|
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);
|
vcpu_set_vmcs_eoi_exit(vcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SDM Vol 3 - table 6-2, inject high priority exception before
|
/*
|
||||||
* maskable hardware interrupt */
|
* Inject pending exception prior pending interrupt to complete the previous instruction.
|
||||||
injected = vcpu_inject_hi_exception(vcpu);
|
*/
|
||||||
|
injected = vcpu_inject_exception(vcpu);
|
||||||
if (!injected) {
|
if (!injected) {
|
||||||
/* inject NMI before maskable hardware interrupt */
|
/* 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)) {
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If "virtual-interrupt delivered" is enabled, CPU will evaluate
|
* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static inline void acrn_inject_pending_intr(struct acrn_vcpu *vcpu,
|
||||||
* @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,
|
|
||||||
uint64_t *pending_req_bits, bool injected)
|
uint64_t *pending_req_bits, bool injected)
|
||||||
{
|
{
|
||||||
bool ret = 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)) {
|
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);
|
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)
|
__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);
|
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)
|
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));
|
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)
|
bool guest_irq_enabled, bool injected)
|
||||||
{
|
{
|
||||||
uint32_t vector = 0U;
|
uint32_t vector = 0U;
|
||||||
bool ret = injected;
|
|
||||||
if (guest_irq_enabled && (!injected)) {
|
if (guest_irq_enabled && (!injected)) {
|
||||||
vlapic_update_ppr(vlapic);
|
vlapic_update_ppr(vlapic);
|
||||||
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
if (vlapic_find_deliverable_intr(vlapic, &vector)) {
|
||||||
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
|
exec_vmwrite32(VMX_ENTRY_INT_INFO_FIELD, VMX_INT_INFO_VALID | vector);
|
||||||
vlapic_get_deliverable_intr(vlapic, vector);
|
vlapic_get_deliverable_intr(vlapic, vector);
|
||||||
ret = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vlapic_update_tpr_threshold(vlapic);
|
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,
|
static void apicv_advanced_inject_intr(struct acrn_vlapic *vlapic,
|
||||||
__unused bool guest_irq_enabled, bool injected)
|
__unused bool guest_irq_enabled, __unused bool injected)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* From SDM Vol3 26.3.2.5:
|
* 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.
|
* needed. And then try to handle vmcs event injection.
|
||||||
*/
|
*/
|
||||||
vlapic_apicv_inject_pir(vlapic);
|
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)
|
static bool apicv_basic_has_pending_delivery_intr(struct acrn_vcpu *vcpu)
|
||||||
|
@ -90,7 +90,7 @@ struct acrn_vlapic {
|
|||||||
|
|
||||||
struct acrn_apicv_ops {
|
struct acrn_apicv_ops {
|
||||||
void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level);
|
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_delivery_intr)(struct acrn_vcpu *vcpu);
|
||||||
bool (*has_pending_intr)(struct acrn_vcpu *vcpu);
|
bool (*has_pending_intr)(struct acrn_vcpu *vcpu);
|
||||||
bool (*apic_read_access_may_valid)(uint32_t offset);
|
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_delivery_intr(struct acrn_vcpu *vcpu);
|
||||||
bool vlapic_has_pending_intr(struct acrn_vcpu *vcpu);
|
bool vlapic_has_pending_intr(struct acrn_vcpu *vcpu);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user