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 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2019-03-21 00:54:02 +08:00 committed by wenlingz
parent 037fffc203
commit 0c347e607a
5 changed files with 30 additions and 46 deletions

View File

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

View File

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

View File

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

View File

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

View File

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