diff options
author | Steven Smith <ssmith@xensource.com> | 2006-09-29 14:42:04 +0100 |
---|---|---|
committer | Steven Smith <ssmith@xensource.com> | 2006-09-29 14:42:04 +0100 |
commit | 1e75ea849ed05552525f57e4318876f66ebbc28a (patch) | |
tree | e32976ce8d00c0e4400845defc2c9be52e85a897 /xen/arch/x86/hvm/vioapic.c | |
parent | 448496a5e2d50d023a5d2aae9d7f35d90b63d78d (diff) | |
download | xen-1e75ea849ed05552525f57e4318876f66ebbc28a.tar.gz xen-1e75ea849ed05552525f57e4318876f66ebbc28a.tar.bz2 xen-1e75ea849ed05552525f57e4318876f66ebbc28a.zip |
[XEN][HVM] Make sure that the interrupt which event channel events come in
on is level triggered rather than edge triggered, since it's a PCI device.
This is complicated by the possibility that another PCI device could be
on the same interrupt; the workaround is to have two irr registers
for the PIC and APIC, and have qemu and Xen generated interrupts go
into different ones.
This broke the alt_irq stuff. Fortunately, nobody uses that anymore, so
I've removed it.
Signed-off-by: Steven Smith <sos22@cam.ac.uk>
Diffstat (limited to 'xen/arch/x86/hvm/vioapic.c')
-rw-r--r-- | xen/arch/x86/hvm/vioapic.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 2999bfe4f1..daa812a6f3 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -479,7 +479,7 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno) static int ioapic_get_highest_irq(hvm_vioapic_t *s) { - uint32_t irqs = s->irr & ~s->isr & ~s->imr; + uint32_t irqs = (s->irr | s->irr_xen) & ~s->isr & ~s->imr; return fls(irqs) - 1; } @@ -501,6 +501,7 @@ static void service_ioapic(hvm_vioapic_t *s) } s->irr &= ~(1 << irqno); + s->irr_xen &= ~(1 << irqno); } } @@ -526,6 +527,25 @@ void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs) service_ioapic(s); } +void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level) +{ + hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic; + + if (!hvm_apic_support(d) || !IOAPICEnabled(s) || + s->redirtbl[irq].RedirForm.mask) + return; + + if (s->redirtbl[irq].RedirForm.trigmod != IOAPIC_LEVEL_TRIGGER) { + DPRINTK("Forcing edge triggered APIC irq %d?\n", irq); + domain_crash(d); + } + + if (level) + s->irr_xen |= 1 << irq; + else + s->irr_xen &= ~(1 << irq); +} + void hvm_vioapic_set_irq(struct domain *d, int irq, int level) { hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic); |