Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/io/vioapic.c
Show First 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | vioapic_send_intr(struct vioapic *vioapic, int pin) | ||||
if ((low & IOART_INTMASK) == IOART_INTMSET) { | if ((low & IOART_INTMASK) == IOART_INTMSET) { | ||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", pin); | VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", pin); | ||||
return; | return; | ||||
} | } | ||||
phys = ((low & IOART_DESTMOD) == IOART_DESTPHY); | phys = ((low & IOART_DESTMOD) == IOART_DESTPHY); | ||||
delmode = low & IOART_DELMOD; | delmode = low & IOART_DELMOD; | ||||
level = low & IOART_TRGRLVL ? true : false; | level = low & IOART_TRGRLVL ? true : false; | ||||
if (level) | if (level) { | ||||
if ((low & IOART_REM_IRR) != 0) { | |||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: irr pending", | |||||
pin); | |||||
return; | |||||
} | |||||
vioapic->rtbl[pin].reg |= IOART_REM_IRR; | vioapic->rtbl[pin].reg |= IOART_REM_IRR; | ||||
} | |||||
vector = low & IOART_INTVEC; | vector = low & IOART_INTVEC; | ||||
dest = high >> APIC_ID_SHIFT; | dest = high >> APIC_ID_SHIFT; | ||||
vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector); | vlapic_deliver_intr(vioapic->vm, level, dest, phys, delmode, vector); | ||||
} | } | ||||
static void | static void | ||||
vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate) | vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate) | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | if (regnum >= IOAPIC_REDTBL && | ||||
last = vioapic->rtbl[pin].reg; | last = vioapic->rtbl[pin].reg; | ||||
data64 = (uint64_t)data << lshift; | data64 = (uint64_t)data << lshift; | ||||
mask64 = (uint64_t)0xffffffff << lshift; | mask64 = (uint64_t)0xffffffff << lshift; | ||||
vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS; | vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS; | ||||
vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS; | vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS; | ||||
/* | |||||
* Switching from level to edge triggering will clear the IRR | |||||
* bit. This is what FreeBSD will do in order to EOI an | |||||
* interrupt when the IO-APIC doesn't support targeted EOI (see | |||||
* _ioapic_eoi_source). | |||||
*/ | |||||
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", | VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx", | ||||
pin, vioapic->rtbl[pin].reg); | pin, vioapic->rtbl[pin].reg); | ||||
/* | /* | ||||
* If any fields in the redirection table entry (except mask | * If any fields in the redirection table entry (except mask | ||||
* or polarity) have changed then rendezvous all the vcpus | * or polarity) have changed then rendezvous all the vcpus | ||||
* to update their vlapic trigger-mode registers. | * to update their vlapic trigger-mode registers. | ||||
*/ | */ | ||||
changed = last ^ vioapic->rtbl[pin].reg; | changed = last ^ vioapic->rtbl[pin].reg; | ||||
if (changed & ~(IOART_INTMASK | IOART_INTPOL)) { | if (changed & ~(IOART_INTMASK | IOART_INTPOL)) { | ||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: recalculate " | VIOAPIC_CTR1(vioapic, "ioapic pin%d: recalculate " | ||||
"vlapic trigger-mode register", pin); | "vlapic trigger-mode register", pin); | ||||
VIOAPIC_UNLOCK(vioapic); | VIOAPIC_UNLOCK(vioapic); | ||||
allvcpus = vm_active_cpus(vioapic->vm); | allvcpus = vm_active_cpus(vioapic->vm); | ||||
(void)vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus, | (void)vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus, | ||||
vioapic_update_tmr, NULL); | vioapic_update_tmr, NULL); | ||||
VIOAPIC_LOCK(vioapic); | VIOAPIC_LOCK(vioapic); | ||||
} | } | ||||
/* | /* | ||||
* Generate an interrupt if the following conditions are met: | * Generate an interrupt if the following conditions are met: | ||||
* - previous interrupt has been EOIed | |||||
* - pin trigger mode is level | * - pin trigger mode is level | ||||
* - pin level is asserted | * - pin level is asserted | ||||
*/ | */ | ||||
if ((vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 && | if ((vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGRLVL && | ||||
(vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGRLVL && | |||||
(vioapic->rtbl[pin].acnt > 0)) { | (vioapic->rtbl[pin].acnt > 0)) { | ||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl " | VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl " | ||||
"write, acnt %d", pin, vioapic->rtbl[pin].acnt); | "write, acnt %d", pin, vioapic->rtbl[pin].acnt); | ||||
vioapic_send_intr(vioapic, pin); | vioapic_send_intr(vioapic, pin); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 144 Lines • Show Last 20 Lines |