diff options
author | neel <neel@FreeBSD.org> | 2013-11-27 22:18:08 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2013-11-27 22:18:08 +0000 |
commit | 633860276f4acf7dae788fc6a110e2d4ad99e375 (patch) | |
tree | cea36f9c268215563a7354df4f19354d583fa6da /sys/amd64/vmm | |
parent | 8d072f285dc2c5b5ac84c43dfe78900716bf8a36 (diff) | |
download | FreeBSD-src-633860276f4acf7dae788fc6a110e2d4ad99e375.zip FreeBSD-src-633860276f4acf7dae788fc6a110e2d4ad99e375.tar.gz |
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@
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r-- | sys/amd64/vmm/io/ppt.c | 2 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vhpet.c | 19 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vioapic.c | 229 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vioapic.h | 3 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vlapic.c | 39 | ||||
-rw-r--r-- | sys/amd64/vmm/io/vlapic.h | 2 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_dev.c | 2 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_ktr.h | 3 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_lapic.c | 4 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_lapic.h | 18 |
10 files changed, 228 insertions, 93 deletions
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c index a6061e9..fce4bbd 100644 --- a/sys/amd64/vmm/io/ppt.c +++ b/sys/amd64/vmm/io/ppt.c @@ -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 diff --git a/sys/amd64/vmm/io/vhpet.c b/sys/amd64/vmm/io/vhpet.c index d6ef7ca..112480ee 100644 --- a/sys/amd64/vmm/io/vhpet.c +++ b/sys/amd64/vmm/io/vhpet.c @@ -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 @@ done: 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); diff --git a/sys/amd64/vmm/io/vioapic.c b/sys/amd64/vmm/io/vioapic.c index 9ce8a5e..167e8ab 100644 --- a/sys/amd64/vmm/io/vioapic.c +++ b/sys/amd64/vmm/io/vioapic.c @@ -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,62 +117,96 @@ 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)); + low = vioapic->rtbl[pin].reg; + high = vioapic->rtbl[pin].reg >> 32; - /* Nothing to do if interrupt pin has not changed state */ - if (vioapic->rtbl[pin].pinstate == newstate) + /* + * 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; + } - vioapic->rtbl[pin].pinstate = newstate; /* record it */ + if ((low & IOART_DELMOD) != IOART_DELFIXED) { + VIOAPIC_CTR2(vioapic, "ioapic pin%d: unsupported delivery mode " + "0x%08x", pin, low); + return; + } - /* Nothing to do if interrupt pin is deasserted */ - if (!INTR_ASSERTED(vioapic, pin)) + if ((low & IOART_INTMASK) == IOART_INTMSET) { + VIOAPIC_CTR1(vioapic, "ioapic pin%d: masked", 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); - } + 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); } - } 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; } } +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 { IRQSTATE_ASSERT, IRQSTATE_DEASSERT, @@ -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); +} diff --git a/sys/amd64/vmm/io/vioapic.h b/sys/amd64/vmm/io/vioapic.h index 71ca801..65176b3 100644 --- a/sys/amd64/vmm/io/vioapic.h +++ b/sys/amd64/vmm/io/vioapic.h @@ -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 diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index 3061465..6e5b5ea 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -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 diff --git a/sys/amd64/vmm/io/vlapic.h b/sys/amd64/vmm/io/vlapic.h index 402cb79..8ea65ee 100644 --- a/sys/amd64/vmm/io/vlapic.h +++ b/sys/amd64/vmm/io/vlapic.h @@ -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); diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index 898ba3d..f248f68 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -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; diff --git a/sys/amd64/vmm/vmm_ktr.h b/sys/amd64/vmm/vmm_ktr.h index ab28ada..9fb46d8 100644 --- a/sys/amd64/vmm/vmm_ktr.h +++ b/sys/amd64/vmm/vmm_ktr.h @@ -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 diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c index b893ba4..465ce6c 100644 --- a/sys/amd64/vmm/vmm_lapic.c +++ b/sys/amd64/vmm/vmm_lapic.c @@ -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); diff --git a/sys/amd64/vmm/vmm_lapic.h b/sys/amd64/vmm/vmm_lapic.h index a79912e..1461185 100644 --- a/sys/amd64/vmm/vmm_lapic.h +++ b/sys/amd64/vmm/vmm_lapic.h @@ -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 |