hv: rework EOI_EXIT_BITMAP update logic

This commit changes the EOI_EXIT_BITMAP as follows:
- add a eoi_exit_bitmap to vlapic structure;
- go through all the RTEs and set eoi_exit_bitmap in the vlapic structure when related RTE fields are modified;
- add ACRN_REQUEST_EOI_EXIT_UPDATE, if eoi_exit_bitmap changed, request the corresponding vcpu to write the bitmap
  to VMCS.

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-14 17:20:50 +08:00
committed by wenlingz
parent f15cc7d6de
commit fc61536b07
5 changed files with 150 additions and 10 deletions

View File

@@ -33,7 +33,7 @@
#include <hypervisor.h>
#define RTBL_RO_BITS (uint32_t)(IOAPIC_RTE_REM_IRR | IOAPIC_RTE_DELIVS)
#define NEED_TMR_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_INTVEC)
#define NEED_EOI_EXIT_UPDATE (IOAPIC_RTE_TRGRMOD | IOAPIC_RTE_DELMOD | IOAPIC_RTE_DEST_MASK | IOAPIC_RTE_INTVEC)
#define ACRN_DBG_IOAPIC 6U
#define ACRN_IOAPIC_VERSION 0x11U
@@ -171,6 +171,66 @@ vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t op
spinlock_release(&(vioapic->mtx));
}
/*
* Generate eoi_exit_bitmap and request each VCPU to update VMCS fields
* To be called with vioapic->mtx
* @pre vioapic != NULL
*/
static void
vioapic_update_eoi_exit(const struct acrn_vioapic *vioapic)
{
struct acrn_vcpu *vcpu;
union ioapic_rte rte;
uint64_t mask;
uint32_t vector, delmode, dest;
uint32_t pin, pincount;
uint16_t vcpu_id;
bool level, phys;
dev_dbg(ACRN_DBG_IOAPIC, "%s", __func__);
/* clear old bitmap to generate new bitmap */
foreach_vcpu(vcpu_id, vioapic->vm, vcpu) {
spinlock_obtain(&(vcpu->arch.lock));
vcpu_reset_eoi_exit_all(vcpu);
}
/* go through RTEs and set corresponding bits of eoi_exit_bitmap */
pincount = vioapic_pincount(vioapic->vm);
for (pin = 0U; pin < pincount; pin++) {
rte = vioapic->rtbl[pin];
level = ((rte.full & IOAPIC_RTE_TRGRLVL) != 0UL);
vector = rte.u.lo_32 & IOAPIC_RTE_LOW_INTVEC;
if (level && ((vector >= 0x20U) && (vector < NR_MAX_VECTOR))) {
/* if level-trigger and vector is valid */
delmode = (uint32_t)(rte.full & IOAPIC_RTE_DELMOD);
if ((delmode != APIC_DELMODE_FIXED) && (delmode != APIC_DELMODE_LOWPRIO)) {
dev_dbg(ACRN_DBG_IOAPIC,
"Ignoring level trigger-mode for delivery-mode 0x%x", delmode);
} else {
dest = (uint32_t)((rte.full) >> IOAPIC_RTE_DEST_SHIFT);
phys = ((rte.full & IOAPIC_RTE_DESTLOG) == 0UL);
calcvdest(vioapic->vm, &mask, dest, phys);
for (vcpu_id = ffs64(mask); vcpu_id != INVALID_BIT_INDEX; vcpu_id = ffs64(mask)) {
vcpu = vcpu_from_vid(vioapic->vm, vcpu_id);
vcpu_set_eoi_exit(vcpu, vector);
bitmap_clear_nolock(vcpu_id, &mask);
}
}
}
}
/* make request if eoi_exit_bitmap changed */
foreach_vcpu(vcpu_id, vioapic->vm, vcpu) {
spinlock_release(&(vcpu->arch.lock));
vcpu_make_request(vcpu, ACRN_REQUEST_EOI_EXIT_UPDATE);
}
}
/*
* Reset the vlapic's trigger-mode register to reflect the ioapic pin
* configuration.
@@ -358,15 +418,9 @@ static void vioapic_indirect_write(struct acrn_vioapic *vioapic, uint32_t addr,
* rendezvous all the vcpus to update their vlapic
* trigger-mode registers.
*/
if ((changed & NEED_TMR_UPDATE) != 0UL) {
uint16_t i;
struct acrn_vcpu *vcpu;
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin);
foreach_vcpu(i, vioapic->vm, vcpu) {
vcpu_make_request(vcpu, ACRN_REQUEST_TMR_UPDATE);
}
if ((changed & NEED_EOI_EXIT_UPDATE) != 0UL) {
dev_dbg(ACRN_DBG_IOAPIC, "ioapic pin%hhu: recalculate vlapic trigger-mode reg", pin);
vioapic_update_eoi_exit(vioapic);
}
/*