hv: set/clear TMR bit like hardware behave

Current ACRN implementation update TMR bits one time only when related RTE fields changed,
which is not acting like actual hardware.

From SDM vol3 10.8.4:
"Upon acceptance of an interrupt into the IRR, the corresponding TMR bit is cleared for
edge-triggered interrupts and set for leveltriggered interrupts."

This commit change the ACRN implementation to set/clear corresponding TMR bit when inject
intr to vlapic.

Tracked-On: #2343
Signed-off-by: Yan, Like <like.yan@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yan, Like 2019-01-04 14:52:02 +08:00 committed by wenlingz
parent c9b617485f
commit f15cc7d6de
2 changed files with 36 additions and 51 deletions

View File

@ -460,6 +460,36 @@ vlapic_esr_write_handler(struct acrn_vlapic *vlapic)
vlapic->esr_pending = 0U;
}
static void
vlapic_set_tmr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
{
struct lapic_regs *lapic;
struct lapic_reg *tmrptr;
lapic = &(vlapic->apic_page);
tmrptr = &lapic->tmr[0];
if (level) {
bitmap32_set_lock((uint16_t)(vector & 0x1fU), &tmrptr[vector >> 5U].v);
} else {
bitmap32_clear_lock((uint16_t)(vector & 0x1fU), &tmrptr[vector >> 5U].v);
}
}
static void
vlapic_reset_tmr(struct acrn_vlapic *vlapic)
{
int16_t i;
struct lapic_regs *lapic;
dev_dbg(ACRN_DBG_LAPIC,
"vlapic resetting all vectors to edge-triggered");
lapic = &(vlapic->apic_page);
for (i = 0; i < 8; i++) {
lapic->tmr[i].v = 0U;
}
}
/*
* Returns 1 if the vcpu needs to be notified of the interrupt and 0 otherwise.
* @pre vector >= 16
@ -468,8 +498,7 @@ static bool
vlapic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
{
struct lapic_regs *lapic;
struct lapic_reg *irrptr, *tmrptr;
uint32_t mask;
struct lapic_reg *irrptr;
uint32_t idx;
int32_t pending_intr;
bool ret = true;
@ -483,6 +512,9 @@ vlapic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
ret = false;
} else if (is_apicv_intr_delivery_supported()) {
pending_intr = apicv_set_intr_ready(vlapic, vector);
vlapic_set_tmr(vlapic, vector, level);
if ((pending_intr != 0) && (is_apicv_posted_intr_supported()) && (get_cpu_id() != vlapic->vcpu->pcpu_id)) {
/*
* Send interrupt to vCPU via posted interrupt way:
@ -502,24 +534,14 @@ vlapic_accept_intr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
}
} else {
idx = vector >> 5U;
mask = 1U << (vector & 0x1fU);
irrptr = &lapic->irr[0];
/* If the interrupt is set, don't try to do it again */
if (bitmap32_test_and_set_lock((uint16_t)(vector & 0x1fU), &irrptr[idx].v)) {
ret = false;
} else {
/*
* Verify that the trigger-mode of the interrupt matches with
* the vlapic TMR registers.
*/
tmrptr = &lapic->tmr[0];
if ((tmrptr[idx].v & mask) != (level ? mask : 0U)) {
dev_dbg(ACRN_DBG_LAPIC, "vlapic TMR[%u] is 0x%08x but interrupt is %s-triggered",
idx, tmrptr[idx].v, level ? "level" : "edge");
}
vlapic_dump_irr(vlapic, "vlapic_accept_intr");
/* set tmr if corresponding irr bit changes from 0 to 1 */
vlapic_set_tmr(vlapic, vector, level);
}
}
@ -1844,24 +1866,6 @@ vlapic_enabled(const struct acrn_vlapic *vlapic)
return ret;
}
static void
vlapic_set_tmr(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
{
struct lapic_regs *lapic;
struct lapic_reg *tmrptr;
uint32_t mask, idx;
lapic = &(vlapic->apic_page);
tmrptr = &lapic->tmr[0];
idx = vector >> 5U;
mask = 1U << (vector & 0x1fU);
if (level) {
tmrptr[idx].v |= mask;
} else {
tmrptr[idx].v &= ~mask;
}
}
/*
* APICv batch set tmr will try to set multi vec at the same time
* to avoid unnecessary VMCS read/update.
@ -1874,22 +1878,6 @@ vlapic_apicv_batch_set_tmr(struct acrn_vlapic *vlapic)
}
}
void
vlapic_reset_tmr(struct acrn_vlapic *vlapic)
{
struct acrn_vcpu *vcpu = vlapic->vcpu;
uint32_t vector;
dev_dbg(ACRN_DBG_LAPIC,
"vlapic resetting all vectors to edge-triggered");
for (vector = 0U; vector <= 255U; vector++) {
vlapic_set_tmr(vlapic, vector, false);
}
vcpu_make_request(vcpu, ACRN_REQUEST_TMR_UPDATE);
}
void
vlapic_set_tmr_one_vec(struct acrn_vlapic *vlapic, uint32_t delmode,
uint32_t vector, bool level)

View File

@ -227,9 +227,6 @@ int32_t vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg);
void vlapic_deliver_intr(struct acrn_vm *vm, bool level, uint32_t dest,
bool phys, uint32_t delmode, uint32_t vec, bool rh);
/* Reset the trigger-mode bits for all vectors to be edge-triggered */
void vlapic_reset_tmr(struct acrn_vlapic *vlapic);
/*
* Set the trigger-mode bit associated with 'vector' to level-triggered if
* the (dest,phys,delmode) tuple resolves to an interrupt being delivered to