aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vioapic.c
diff options
context:
space:
mode:
authorSteven Smith <ssmith@xensource.com>2006-09-29 14:42:04 +0100
committerSteven Smith <ssmith@xensource.com>2006-09-29 14:42:04 +0100
commit1e75ea849ed05552525f57e4318876f66ebbc28a (patch)
treee32976ce8d00c0e4400845defc2c9be52e85a897 /xen/arch/x86/hvm/vioapic.c
parent448496a5e2d50d023a5d2aae9d7f35d90b63d78d (diff)
downloadxen-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.c22
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);