mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 12:12:16 +00:00
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:
parent
037fffc203
commit
0c347e607a
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user