Add support for level triggered interrupt pins on the vioapic. Prior to this
commit level triggered interrupts would work as long as the pin was not shared among multiple interrupt sources. The vlapic now keeps track of level triggered interrupts in the trigger mode register and will forward the EOI for a level triggered interrupt to the vioapic. The vioapic in turn uses the EOI to sample the level on the pin and re-inject the vector if the pin is still asserted. The vhpet is the first consumer of level triggered interrupts and advertises that it can generate interrupts on pins 20 through 23 of the vioapic. Discussed with: grehan@
This commit is contained in:
parent
10c273397e
commit
b5b28fc9dc
@ -421,7 +421,7 @@ pptintr(void *arg)
|
||||
vec = pptarg->vec;
|
||||
|
||||
if (ppt->vm != NULL)
|
||||
(void) lapic_set_intr(ppt->vm, pptarg->vcpu, vec);
|
||||
lapic_intr_edge(ppt->vm, pptarg->vcpu, vec);
|
||||
else {
|
||||
/*
|
||||
* XXX
|
||||
|
@ -266,14 +266,14 @@ vhpet_timer_interrupt(struct vhpet *vhpet, int n)
|
||||
if (apicid != 0xff) {
|
||||
/* unicast */
|
||||
vcpuid = vm_apicid2vcpuid(vhpet->vm, apicid);
|
||||
lapic_set_intr(vhpet->vm, vcpuid, vector);
|
||||
lapic_intr_edge(vhpet->vm, vcpuid, vector);
|
||||
} else {
|
||||
/* broadcast */
|
||||
dmask = vm_active_cpus(vhpet->vm);
|
||||
while ((vcpuid = CPU_FFS(&dmask)) != 0) {
|
||||
vcpuid--;
|
||||
CPU_CLR(vcpuid, &dmask);
|
||||
lapic_set_intr(vhpet->vm, vcpuid, vector);
|
||||
lapic_intr_edge(vhpet->vm, vcpuid, vector);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -725,8 +725,9 @@ vhpet_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval, int size,
|
||||
struct vhpet *
|
||||
vhpet_init(struct vm *vm)
|
||||
{
|
||||
int i;
|
||||
int i, pincount;
|
||||
struct vhpet *vhpet;
|
||||
uint64_t allowed_irqs;
|
||||
struct vhpet_callout_arg *arg;
|
||||
struct bintime bt;
|
||||
|
||||
@ -737,12 +738,20 @@ vhpet_init(struct vm *vm)
|
||||
FREQ2BT(HPET_FREQ, &bt);
|
||||
vhpet->freq_sbt = bttosbt(bt);
|
||||
|
||||
pincount = vioapic_pincount(vm);
|
||||
if (pincount >= 24)
|
||||
allowed_irqs = 0x00f00000; /* irqs 20, 21, 22 and 23 */
|
||||
else
|
||||
allowed_irqs = 0;
|
||||
|
||||
/*
|
||||
* Initialize HPET timer hardware state.
|
||||
*/
|
||||
for (i = 0; i < VHPET_NUM_TIMERS; i++) {
|
||||
vhpet->timer[i].cap_config = 0UL << 32 |
|
||||
HPET_TCAP_FSB_INT_DEL | HPET_TCAP_PER_INT;
|
||||
vhpet->timer[i].cap_config = allowed_irqs << 32;
|
||||
vhpet->timer[i].cap_config |= HPET_TCAP_PER_INT;
|
||||
vhpet->timer[i].cap_config |= HPET_TCAP_FSB_INT_DEL;
|
||||
|
||||
vhpet->timer[i].compval = 0xffffffff;
|
||||
callout_init(&vhpet->timer[i].callout, 1);
|
||||
|
||||
|
@ -49,8 +49,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define IOREGSEL 0x00
|
||||
#define IOWIN 0x10
|
||||
|
||||
#define REDIR_ENTRIES 16
|
||||
#define INTR_ASSERTED(vioapic, pin) ((vioapic)->rtbl[(pin)].pinstate == true)
|
||||
#define REDIR_ENTRIES 24
|
||||
#define RTBL_RO_BITS ((uint64_t)(IOART_REM_IRR | IOART_DELIVS))
|
||||
|
||||
struct vioapic {
|
||||
struct vm *vm;
|
||||
@ -59,8 +59,7 @@ struct vioapic {
|
||||
uint32_t ioregsel;
|
||||
struct {
|
||||
uint64_t reg;
|
||||
bool pinstate;
|
||||
bool pending;
|
||||
int acnt; /* sum of pin asserts (+1) and deasserts (-1) */
|
||||
} rtbl[REDIR_ENTRIES];
|
||||
};
|
||||
|
||||
@ -79,6 +78,9 @@ static MALLOC_DEFINE(M_VIOAPIC, "vioapic", "bhyve virtual ioapic");
|
||||
#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)
|
||||
|
||||
#ifdef KTR
|
||||
static const char *
|
||||
pinstate_str(bool asserted)
|
||||
@ -89,14 +91,25 @@ pinstate_str(bool asserted)
|
||||
else
|
||||
return ("deasserted");
|
||||
}
|
||||
|
||||
static const char *
|
||||
trigger_str(bool level)
|
||||
{
|
||||
|
||||
if (level)
|
||||
return ("level");
|
||||
else
|
||||
return ("edge");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate)
|
||||
vioapic_send_intr(struct vioapic *vioapic, int pin)
|
||||
{
|
||||
int vector, apicid, vcpuid;
|
||||
uint32_t low, high;
|
||||
cpuset_t dmask;
|
||||
bool level;
|
||||
|
||||
KASSERT(pin >= 0 && pin < REDIR_ENTRIES,
|
||||
("vioapic_set_pinstate: invalid pin number %d", pin));
|
||||
@ -104,60 +117,94 @@ vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate)
|
||||
KASSERT(VIOAPIC_LOCKED(vioapic),
|
||||
("vioapic_set_pinstate: vioapic is not locked"));
|
||||
|
||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d %s", pin, pinstate_str(newstate));
|
||||
|
||||
/* Nothing to do if interrupt pin has not changed state */
|
||||
if (vioapic->rtbl[pin].pinstate == newstate)
|
||||
return;
|
||||
|
||||
vioapic->rtbl[pin].pinstate = newstate; /* record it */
|
||||
|
||||
/* Nothing to do if interrupt pin is deasserted */
|
||||
if (!INTR_ASSERTED(vioapic, pin))
|
||||
return;
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* We only deal with:
|
||||
* - edge triggered interrupts
|
||||
* - fixed delivery mode
|
||||
* Level-triggered sources will work so long as there is no sharing.
|
||||
*/
|
||||
low = vioapic->rtbl[pin].reg;
|
||||
high = vioapic->rtbl[pin].reg >> 32;
|
||||
if ((low & IOART_INTMASK) == IOART_INTMCLR &&
|
||||
(low & IOART_DESTMOD) == IOART_DESTPHY &&
|
||||
(low & IOART_DELMOD) == IOART_DELFIXED) {
|
||||
vector = low & IOART_INTVEC;
|
||||
apicid = high >> APIC_ID_SHIFT;
|
||||
if (apicid != 0xff) {
|
||||
/* unicast */
|
||||
vcpuid = vm_apicid2vcpuid(vioapic->vm, apicid);
|
||||
VIOAPIC_CTR3(vioapic, "ioapic pin%d triggering "
|
||||
"intr vector %d on vcpuid %d", pin, vector, vcpuid);
|
||||
lapic_set_intr(vioapic->vm, vcpuid, vector);
|
||||
} else {
|
||||
/* broadcast */
|
||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d triggering intr "
|
||||
"vector %d on all vcpus", pin, vector);
|
||||
dmask = vm_active_cpus(vioapic->vm);
|
||||
while ((vcpuid = CPU_FFS(&dmask)) != 0) {
|
||||
vcpuid--;
|
||||
CPU_CLR(vcpuid, &dmask);
|
||||
lapic_set_intr(vioapic->vm, vcpuid, vector);
|
||||
}
|
||||
}
|
||||
} else if ((low & IOART_INTMASK) != IOART_INTMCLR &&
|
||||
(low & IOART_TRGRLVL) != 0) {
|
||||
/*
|
||||
* For level-triggered interrupts that have been
|
||||
* masked, set the pending bit so that an interrupt
|
||||
* will be generated on unmask and if the level is
|
||||
* still asserted
|
||||
*/
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d interrupt pending", pin);
|
||||
vioapic->rtbl[pin].pending = true;
|
||||
|
||||
/*
|
||||
* XXX We only deal with:
|
||||
* - physical destination
|
||||
* - fixed delivery mode
|
||||
*/
|
||||
if ((low & IOART_DESTMOD) != IOART_DESTPHY) {
|
||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d: unsupported dest mode "
|
||||
"0x%08x", pin, low);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((low & IOART_DELMOD) != IOART_DELFIXED) {
|
||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d: unsupported delivery mode "
|
||||
"0x%08x", pin, low);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((low & IOART_INTMASK) == IOART_INTMSET) {
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", pin);
|
||||
return;
|
||||
}
|
||||
|
||||
level = low & IOART_TRGRLVL ? true : false;
|
||||
if (level)
|
||||
vioapic->rtbl[pin].reg |= IOART_REM_IRR;
|
||||
|
||||
vector = low & IOART_INTVEC;
|
||||
apicid = high >> APIC_ID_SHIFT;
|
||||
if (apicid != 0xff) {
|
||||
/* unicast */
|
||||
vcpuid = vm_apicid2vcpuid(vioapic->vm, apicid);
|
||||
VIOAPIC_CTR4(vioapic, "ioapic pin%d: %s triggered intr "
|
||||
"vector %d on vcpuid %d", pin, trigger_str(level),
|
||||
vector, vcpuid);
|
||||
lapic_set_intr(vioapic->vm, vcpuid, vector, level);
|
||||
} else {
|
||||
/* broadcast */
|
||||
VIOAPIC_CTR3(vioapic, "ioapic pin%d: %s triggered intr "
|
||||
"vector %d on all vcpus", pin, trigger_str(level), vector);
|
||||
dmask = vm_active_cpus(vioapic->vm);
|
||||
while ((vcpuid = CPU_FFS(&dmask)) != 0) {
|
||||
vcpuid--;
|
||||
CPU_CLR(vcpuid, &dmask);
|
||||
lapic_set_intr(vioapic->vm, vcpuid, vector, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vioapic_set_pinstate(struct vioapic *vioapic, int pin, bool newstate)
|
||||
{
|
||||
int oldcnt, newcnt;
|
||||
bool needintr;
|
||||
|
||||
KASSERT(pin >= 0 && pin < REDIR_ENTRIES,
|
||||
("vioapic_set_pinstate: invalid pin number %d", pin));
|
||||
|
||||
KASSERT(VIOAPIC_LOCKED(vioapic),
|
||||
("vioapic_set_pinstate: vioapic is not locked"));
|
||||
|
||||
oldcnt = vioapic->rtbl[pin].acnt;
|
||||
if (newstate)
|
||||
vioapic->rtbl[pin].acnt++;
|
||||
else
|
||||
vioapic->rtbl[pin].acnt--;
|
||||
newcnt = vioapic->rtbl[pin].acnt;
|
||||
|
||||
if (newcnt < 0) {
|
||||
VIOAPIC_CTR2(vioapic, "ioapic pin%d: bad acnt %d",
|
||||
pin, newcnt);
|
||||
}
|
||||
|
||||
needintr = false;
|
||||
if (oldcnt == 0 && newcnt == 1) {
|
||||
needintr = true;
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: asserted", pin);
|
||||
} else if (oldcnt == 1 && newcnt == 0) {
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d: deasserted", pin);
|
||||
} else {
|
||||
VIOAPIC_CTR3(vioapic, "ioapic pin%d: %s, ignored, acnt %d",
|
||||
pin, pinstate_str(newstate), newcnt);
|
||||
}
|
||||
|
||||
if (needintr)
|
||||
vioapic_send_intr(vioapic, pin);
|
||||
}
|
||||
|
||||
enum irqstate {
|
||||
@ -228,7 +275,7 @@ vioapic_read(struct vioapic *vioapic, uint32_t addr)
|
||||
return (vioapic->id);
|
||||
break;
|
||||
case IOAPIC_VER:
|
||||
return ((REDIR_ENTRIES << MAXREDIRSHIFT) | 0x11);
|
||||
return (((REDIR_ENTRIES - 1) << MAXREDIRSHIFT) | 0x11);
|
||||
break;
|
||||
case IOAPIC_ARB:
|
||||
return (vioapic->id);
|
||||
@ -255,6 +302,7 @@ vioapic_read(struct vioapic *vioapic, uint32_t addr)
|
||||
static void
|
||||
vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data)
|
||||
{
|
||||
uint64_t data64, mask64;
|
||||
int regnum, pin, lshift;
|
||||
|
||||
regnum = addr & 0xff;
|
||||
@ -279,30 +327,26 @@ vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data)
|
||||
else
|
||||
lshift = 0;
|
||||
|
||||
vioapic->rtbl[pin].reg &= ~((uint64_t)0xffffffff << lshift);
|
||||
vioapic->rtbl[pin].reg |= ((uint64_t)data << lshift);
|
||||
data64 = (uint64_t)data << lshift;
|
||||
mask64 = (uint64_t)0xffffffff << lshift;
|
||||
vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS;
|
||||
vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS;
|
||||
|
||||
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);
|
||||
|
||||
if (vioapic->rtbl[pin].pending &&
|
||||
((vioapic->rtbl[pin].reg & IOART_INTMASK) ==
|
||||
IOART_INTMCLR)) {
|
||||
vioapic->rtbl[pin].pending = false;
|
||||
/*
|
||||
* Inject the deferred level-triggered int if it is
|
||||
* still asserted. Simulate by toggling the pin
|
||||
* off and then on.
|
||||
*/
|
||||
if (vioapic->rtbl[pin].pinstate == true) {
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d pending "
|
||||
"interrupt delivered", pin);
|
||||
vioapic_set_pinstate(vioapic, pin, false);
|
||||
vioapic_set_pinstate(vioapic, pin, true);
|
||||
} else {
|
||||
VIOAPIC_CTR1(vioapic, "ioapic pin%d pending "
|
||||
"interrupt dismissed", pin);
|
||||
}
|
||||
/*
|
||||
* Generate an interrupt if the following conditions are met:
|
||||
* - pin is not masked
|
||||
* - previous interrupt has been EOIed
|
||||
* - pin level is asserted
|
||||
*/
|
||||
if ((vioapic->rtbl[pin].reg & IOART_INTMASK) == IOART_INTMCLR &&
|
||||
(vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 &&
|
||||
(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -366,6 +410,38 @@ vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval,
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
vioapic_process_eoi(struct vm *vm, int vcpuid, int vector)
|
||||
{
|
||||
struct vioapic *vioapic;
|
||||
int pin;
|
||||
|
||||
KASSERT(vector >= 0 && vector < 256,
|
||||
("vioapic_process_eoi: invalid vector %d", vector));
|
||||
|
||||
vioapic = vm_ioapic(vm);
|
||||
VIOAPIC_CTR1(vioapic, "ioapic processing eoi for vector %d", vector);
|
||||
|
||||
/*
|
||||
* XXX keep track of the pins associated with this vector instead
|
||||
* of iterating on every single pin each time.
|
||||
*/
|
||||
VIOAPIC_LOCK(vioapic);
|
||||
for (pin = 0; pin < REDIR_ENTRIES; pin++) {
|
||||
if ((vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0)
|
||||
continue;
|
||||
if ((vioapic->rtbl[pin].reg & IOART_INTVEC) != vector)
|
||||
continue;
|
||||
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 *
|
||||
vioapic_init(struct vm *vm)
|
||||
{
|
||||
@ -390,3 +466,10 @@ vioapic_cleanup(struct vioapic *vioapic)
|
||||
|
||||
free(vioapic, M_VIOAPIC);
|
||||
}
|
||||
|
||||
int
|
||||
vioapic_pincount(struct vm *vm)
|
||||
{
|
||||
|
||||
return (REDIR_ENTRIES);
|
||||
}
|
||||
|
@ -44,4 +44,7 @@ int vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa,
|
||||
uint64_t wval, int size, void *arg);
|
||||
int vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa,
|
||||
uint64_t *rval, int size, void *arg);
|
||||
|
||||
int vioapic_pincount(struct vm *vm);
|
||||
void vioapic_process_eoi(struct vm *vm, int vcpuid, int vector);
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "vmm_lapic.h"
|
||||
#include "vmm_ktr.h"
|
||||
#include "vlapic.h"
|
||||
#include "vioapic.h"
|
||||
|
||||
#define VLAPIC_CTR0(vlapic, format) \
|
||||
VCPU_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
|
||||
@ -211,18 +212,32 @@ vlapic_reset(struct vlapic *vlapic)
|
||||
}
|
||||
|
||||
void
|
||||
vlapic_set_intr_ready(struct vlapic *vlapic, int vector)
|
||||
vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level)
|
||||
{
|
||||
struct LAPIC *lapic = &vlapic->apic;
|
||||
uint32_t *irrptr;
|
||||
uint32_t *irrptr, *tmrptr, mask;
|
||||
int idx;
|
||||
|
||||
if (vector < 0 || vector >= 256)
|
||||
panic("vlapic_set_intr_ready: invalid vector %d\n", vector);
|
||||
|
||||
idx = (vector / 32) * 4;
|
||||
mask = 1 << (vector % 32);
|
||||
|
||||
irrptr = &lapic->irr0;
|
||||
atomic_set_int(&irrptr[idx], 1 << (vector % 32));
|
||||
atomic_set_int(&irrptr[idx], mask);
|
||||
|
||||
/*
|
||||
* Upon acceptance of an interrupt into the IRR the corresponding
|
||||
* TMR bit is cleared for edge-triggered interrupts and set for
|
||||
* level-triggered interrupts.
|
||||
*/
|
||||
tmrptr = &lapic->tmr0;
|
||||
if (level)
|
||||
atomic_set_int(&tmrptr[idx], mask);
|
||||
else
|
||||
atomic_clear_int(&tmrptr[idx], mask);
|
||||
|
||||
VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready");
|
||||
}
|
||||
|
||||
@ -350,10 +365,11 @@ static void
|
||||
vlapic_process_eoi(struct vlapic *vlapic)
|
||||
{
|
||||
struct LAPIC *lapic = &vlapic->apic;
|
||||
uint32_t *isrptr;
|
||||
int i, idx, bitpos;
|
||||
uint32_t *isrptr, *tmrptr;
|
||||
int i, idx, bitpos, vector;
|
||||
|
||||
isrptr = &lapic->isr0;
|
||||
tmrptr = &lapic->tmr0;
|
||||
|
||||
/*
|
||||
* The x86 architecture reserves the the first 32 vectors for use
|
||||
@ -362,15 +378,20 @@ vlapic_process_eoi(struct vlapic *vlapic)
|
||||
for (i = 7; i > 0; i--) {
|
||||
idx = i * 4;
|
||||
bitpos = fls(isrptr[idx]);
|
||||
if (bitpos != 0) {
|
||||
if (bitpos-- != 0) {
|
||||
if (vlapic->isrvec_stk_top <= 0) {
|
||||
panic("invalid vlapic isrvec_stk_top %d",
|
||||
vlapic->isrvec_stk_top);
|
||||
}
|
||||
isrptr[idx] &= ~(1 << (bitpos - 1));
|
||||
isrptr[idx] &= ~(1 << bitpos);
|
||||
VLAPIC_CTR_ISR(vlapic, "vlapic_process_eoi");
|
||||
vlapic->isrvec_stk_top--;
|
||||
vlapic_update_ppr(vlapic);
|
||||
if ((tmrptr[idx] & (1 << bitpos)) != 0) {
|
||||
vector = i * 32 + bitpos;
|
||||
vioapic_process_eoi(vlapic->vm, vlapic->vcpuid,
|
||||
vector);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -405,7 +426,7 @@ vlapic_fire_timer(struct vlapic *vlapic)
|
||||
if (!vlapic_get_lvt_field(lvt, APIC_LVTT_M)) {
|
||||
vmm_stat_incr(vlapic->vm, vlapic->vcpuid, VLAPIC_INTR_TIMER, 1);
|
||||
vector = vlapic_get_lvt_field(lvt,APIC_LVTT_VECTOR);
|
||||
vlapic_set_intr_ready(vlapic, vector);
|
||||
vlapic_set_intr_ready(vlapic, vector, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +472,7 @@ lapic_process_icr(struct vlapic *vlapic, uint64_t icrval)
|
||||
i--;
|
||||
CPU_CLR(i, &dmask);
|
||||
if (mode == APIC_DELMODE_FIXED) {
|
||||
lapic_set_intr(vlapic->vm, i, vec);
|
||||
lapic_intr_edge(vlapic->vm, i, vec);
|
||||
vmm_stat_array_incr(vlapic->vm, vlapic->vcpuid,
|
||||
IPIS_SENT, i, 1);
|
||||
} else
|
||||
|
@ -94,7 +94,7 @@ int vlapic_write(struct vlapic *vlapic, uint64_t offset, uint64_t data);
|
||||
int vlapic_read(struct vlapic *vlapic, uint64_t offset, uint64_t *data);
|
||||
int vlapic_pending_intr(struct vlapic *vlapic);
|
||||
void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
|
||||
void vlapic_set_intr_ready(struct vlapic *vlapic, int vector);
|
||||
void vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level);
|
||||
int vlapic_timer_tick(struct vlapic *vlapic);
|
||||
|
||||
uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
|
||||
|
@ -294,7 +294,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
break;
|
||||
case VM_LAPIC_IRQ:
|
||||
vmirq = (struct vm_lapic_irq *)data;
|
||||
error = lapic_set_intr(sc->vm, vmirq->cpuid, vmirq->vector);
|
||||
error = lapic_intr_edge(sc->vm, vmirq->cpuid, vmirq->vector);
|
||||
break;
|
||||
case VM_IOAPIC_ASSERT_IRQ:
|
||||
ioapic_irq = (struct vm_ioapic_irq *)data;
|
||||
|
@ -59,4 +59,7 @@ CTR3(KTR_VMM, "vm %s: " format, vm_name((vm)), (p1), (p2))
|
||||
|
||||
#define VM_CTR3(vm, format, p1, p2, p3) \
|
||||
CTR4(KTR_VMM, "vm %s: " format, vm_name((vm)), (p1), (p2), (p3))
|
||||
|
||||
#define VM_CTR4(vm, format, p1, p2, p3, p4) \
|
||||
CTR5(KTR_VMM, "vm %s: " format, vm_name((vm)), (p1), (p2), (p3), (p4))
|
||||
#endif
|
||||
|
@ -62,7 +62,7 @@ lapic_intr_accepted(struct vm *vm, int cpu, int vector)
|
||||
}
|
||||
|
||||
int
|
||||
lapic_set_intr(struct vm *vm, int cpu, int vector)
|
||||
lapic_set_intr(struct vm *vm, int cpu, int vector, bool level)
|
||||
{
|
||||
struct vlapic *vlapic;
|
||||
|
||||
@ -73,7 +73,7 @@ lapic_set_intr(struct vm *vm, int cpu, int vector)
|
||||
return (EINVAL);
|
||||
|
||||
vlapic = vm_lapic(vm, cpu);
|
||||
vlapic_set_intr_ready(vlapic, vector);
|
||||
vlapic_set_intr_ready(vlapic, vector, level);
|
||||
|
||||
vm_interrupt_hostcpu(vm, cpu);
|
||||
|
||||
|
@ -66,6 +66,22 @@ void lapic_intr_accepted(struct vm *vm, int cpu, int vector);
|
||||
* Signals to the LAPIC that an interrupt at 'vector' needs to be generated
|
||||
* to the 'cpu', the state is recorded in IRR.
|
||||
*/
|
||||
int lapic_set_intr(struct vm *vm, int cpu, int vector);
|
||||
int lapic_set_intr(struct vm *vm, int cpu, int vector, bool trig);
|
||||
|
||||
#define LAPIC_TRIG_LEVEL true
|
||||
#define LAPIC_TRIG_EDGE false
|
||||
static __inline int
|
||||
lapic_intr_level(struct vm *vm, int cpu, int vector)
|
||||
{
|
||||
|
||||
return (lapic_set_intr(vm, cpu, vector, LAPIC_TRIG_LEVEL));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
lapic_intr_edge(struct vm *vm, int cpu, int vector)
|
||||
{
|
||||
|
||||
return (lapic_set_intr(vm, cpu, vector, LAPIC_TRIG_EDGE));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -259,7 +259,7 @@ basl_fwrite_madt(FILE *fp)
|
||||
EFPRINTF(fp, "\n");
|
||||
}
|
||||
|
||||
/* Always a single IOAPIC entry, with ID ncpu+1 */
|
||||
/* Always a single IOAPIC entry, with ID 0 */
|
||||
EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
|
||||
EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
|
||||
/* iasl expects a hex value for the i/o apic id */
|
||||
|
@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define MPEP_FEATURES (0xBFEBFBFF) /* XXX Intel i7 */
|
||||
|
||||
/* Number of i/o intr entries */
|
||||
#define MPEII_MAX_IRQ 16
|
||||
#define MPEII_MAX_IRQ 24
|
||||
|
||||
/* Define processor entry struct since <x86/mptable.h> gets it wrong */
|
||||
typedef struct BPROCENTRY {
|
||||
|
Loading…
Reference in New Issue
Block a user