vioapic
struct vioapic *vioapic; /* (i) virtual ioapic */ \
struct vioapic;
struct vioapic *vm_ioapic(struct vm *vm);
vioapic_send_intr(struct vioapic *vioapic, int pin)
KASSERT(VIOAPIC_LOCKED(vioapic),
low = vioapic->rtbl[pin].reg;
high = vioapic->rtbl[pin].reg >> 32;
VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", pin);
VIOAPIC_CTR1(vioapic, "ioapic pin%d: irr pending",
vioapic->rtbl[pin].reg |= IOART_REM_IRR;
vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector);
vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate)
KASSERT(VIOAPIC_LOCKED(vioapic),
oldcnt = vioapic->rtbl[pin].acnt;
vioapic->rtbl[pin].acnt++;
vioapic->rtbl[pin].acnt--;
newcnt = vioapic->rtbl[pin].acnt;
VIOAPIC_CTR2(vioapic, "ioapic pin%d: bad acnt %d",
VIOAPIC_CTR1(vioapic, "ioapic pin%d: asserted", pin);
VIOAPIC_CTR1(vioapic, "ioapic pin%d: deasserted", pin);
VIOAPIC_CTR3(vioapic, "ioapic pin%d: %s, ignored, acnt %d",
vioapic_send_intr(vioapic, pin);
struct vioapic *vioapic;
vioapic = vm_ioapic(vm);
VIOAPIC_LOCK(vioapic);
vioapic_set_pinstate(vioapic, irq, true);
vioapic_set_pinstate(vioapic, irq, false);
vioapic_set_pinstate(vioapic, irq, true);
vioapic_set_pinstate(vioapic, irq, false);
VIOAPIC_UNLOCK(vioapic);
struct vioapic *vioapic;
vioapic = vm_ioapic(vcpu_vm(vcpu));
VIOAPIC_LOCK(vioapic);
low = vioapic->rtbl[pin].reg;
high = vioapic->rtbl[pin].reg >> 32;
VIOAPIC_UNLOCK(vioapic);
vioapic_read(struct vioapic *vioapic, struct vcpu *vcpu, uint32_t addr)
return (vioapic->id);
return (vioapic->id);
return (vioapic->rtbl[pin].reg >> rshift);
vioapic_write(struct vioapic *vioapic, struct vcpu *vcpu, uint32_t addr,
vioapic->id = data & APIC_ID_MASK;
last = vioapic->rtbl[pin].reg;
vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS;
vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS;
if ((vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGREDG &&
(vioapic->rtbl[pin].reg & IOART_REM_IRR) != 0)
vioapic->rtbl[pin].reg &= ~IOART_REM_IRR;
VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx",
pin, vioapic->rtbl[pin].reg);
changed = last ^ vioapic->rtbl[pin].reg;
VIOAPIC_CTR1(vioapic, "ioapic pin%d: recalculate "
VIOAPIC_UNLOCK(vioapic);
allvcpus = vm_active_cpus(vioapic->vm);
VIOAPIC_LOCK(vioapic);
if ((vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGRLVL &&
(vioapic->rtbl[pin].acnt > 0)) {
VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl "
"write, acnt %d", pin, vioapic->rtbl[pin].acnt);
vioapic_send_intr(vioapic, pin);
vioapic_mmio_rw(struct vioapic *vioapic, struct vcpu *vcpu, uint64_t gpa,
VIOAPIC_LOCK(vioapic);
*data = vioapic->ioregsel;
vioapic->ioregsel = *data;
*data = vioapic_read(vioapic, vcpu,
vioapic->ioregsel);
vioapic_write(vioapic, vcpu, vioapic->ioregsel,
VIOAPIC_UNLOCK(vioapic);
struct vioapic *vioapic;
vioapic = vm_ioapic(vcpu_vm(vcpu));
error = vioapic_mmio_rw(vioapic, vcpu, gpa, rval, size, true);
struct vioapic *vioapic;
vioapic = vm_ioapic(vcpu_vm(vcpu));
error = vioapic_mmio_rw(vioapic, vcpu, gpa, &wval, size, false);
struct vioapic *vioapic;
vioapic = vm_ioapic(vm);
VIOAPIC_CTR1(vioapic, "ioapic processing eoi for vector %d", vector);
VIOAPIC_LOCK(vioapic);
if ((vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0)
if ((vioapic->rtbl[pin].reg & IOART_INTVEC) != vector)
vioapic->rtbl[pin].reg &= ~IOART_REM_IRR;
if (vioapic->rtbl[pin].acnt > 0) {
VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at eoi, "
"acnt %d", pin, vioapic->rtbl[pin].acnt);
vioapic_send_intr(vioapic, pin);
VIOAPIC_UNLOCK(vioapic);
struct vioapic *
struct vioapic *vioapic;
vioapic = malloc(sizeof(struct vioapic), M_VIOAPIC, M_WAITOK | M_ZERO);
vioapic->vm = vm;
mtx_init(&vioapic->mtx, "vioapic lock", NULL, MTX_SPIN);
vioapic->rtbl[i].reg = 0x0001000000010000UL;
return (vioapic);
vioapic_cleanup(struct vioapic *vioapic)
mtx_destroy(&vioapic->mtx);
free(vioapic, M_VIOAPIC);
vioapic_snapshot(struct vioapic *vioapic, struct vm_snapshot_meta *meta)
SNAPSHOT_VAR_OR_LEAVE(vioapic->ioregsel, meta, ret, done);
for (i = 0; i < nitems(vioapic->rtbl); i++) {
SNAPSHOT_VAR_OR_LEAVE(vioapic->rtbl[i].reg, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vioapic->rtbl[i].acnt, meta, ret, done);
#define VIOAPIC_LOCK(vioapic) mtx_lock_spin(&((vioapic)->mtx))
#define VIOAPIC_UNLOCK(vioapic) mtx_unlock_spin(&((vioapic)->mtx))
#define VIOAPIC_LOCKED(vioapic) mtx_owned(&((vioapic)->mtx))
#define VIOAPIC_CTR1(vioapic, fmt, a1) \
VM_CTR1((vioapic)->vm, fmt, a1)
#define VIOAPIC_CTR2(vioapic, fmt, a1, a2) \
VM_CTR2((vioapic)->vm, fmt, a1, a2)
#define VIOAPIC_CTR3(vioapic, fmt, a1, a2, a3) \
VM_CTR3((vioapic)->vm, fmt, a1, a2, a3)
#define VIOAPIC_CTR4(vioapic, fmt, a1, a2, a3, a4) \
VM_CTR4((vioapic)->vm, fmt, a1, a2, a3, a4)
struct vioapic *vioapic_init(struct vm *vm);
void vioapic_cleanup(struct vioapic *vioapic);
int vioapic_snapshot(struct vioapic *vioapic,
struct vioapic *
return (vm->vioapic);
vm->vioapic = vioapic_init(vm);
vioapic_cleanup(vm->vioapic);