# HG changeset patch
# User Steven Smith <ssmith@xxxxxxxxxxxxx>
# Date 1159537324 -3600
# Node ID c620b16d4063a824b5536b76b90e45d2b0e647e5
# Parent 477a0084ff47ac99a8fdd0fdf21dca1cb69e7346
[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@xxxxxxxxx>
---
xen/arch/x86/hvm/i8259.c | 46 +++++++++++++++++++++++---------------
xen/arch/x86/hvm/svm/intr.c | 9 +------
xen/arch/x86/hvm/vioapic.c | 22 +++++++++++++++++-
xen/arch/x86/hvm/vmx/io.c | 9 +------
xen/include/asm-x86/hvm/vioapic.h | 2 +
xen/include/asm-x86/hvm/vpic.h | 8 ++----
6 files changed, 59 insertions(+), 37 deletions(-)
diff -r 477a0084ff47 -r c620b16d4063 xen/arch/x86/hvm/i8259.c
--- a/xen/arch/x86/hvm/i8259.c Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/arch/x86/hvm/i8259.c Fri Sep 29 14:42:04 2006 +0100
@@ -86,7 +86,7 @@ static int pic_get_irq(PicState *s)
ASSERT(spin_is_locked(&s->pics_state->lock));
- mask = s->irr & ~s->imr;
+ mask = (s->irr|s->irr_xen) & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8)
return -1;
@@ -128,6 +128,32 @@ void pic_update_irq(struct hvm_virpic *s
}
}
+void pic_set_xen_irq(void *opaque, int irq, int level)
+{
+ struct hvm_virpic *s = opaque;
+ unsigned long flags;
+ PicState *ps;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ hvm_vioapic_set_xen_irq(current->domain, irq, level);
+
+ /* Set it on the 8259s */
+ ps = &s->pics[irq >> 3];
+ if (!(ps->elcr & (1 << (irq & 7)))) {
+ DPRINTK("edge-triggered override IRQ?\n");
+ domain_crash(current->domain);
+ }
+ if (level) {
+ ps->irr_xen |= 1 << (irq & 7);
+ } else {
+ ps->irr_xen &= ~(1 << (irq & 7));
+ }
+
+ pic_update_irq(s);
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
void pic_set_irq_new(void *opaque, int irq, int level)
{
struct hvm_virpic *s = opaque;
@@ -136,9 +162,6 @@ void pic_set_irq_new(void *opaque, int i
spin_lock_irqsave(&s->lock, flags);
hvm_vioapic_set_irq(current->domain, irq, level);
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
- /* used for IOAPIC irqs */
- if (s->alt_irq_func)
- s->alt_irq_func(s->alt_irq_opaque, irq, level);
pic_update_irq(s);
spin_unlock_irqrestore(&s->lock, flags);
}
@@ -371,6 +394,7 @@ static uint32_t pic_poll_read (PicState
s->pics_state->pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
+ s->irr_xen &= ~(1 << ret);
s->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq(s->pics_state);
@@ -400,7 +424,7 @@ static uint32_t pic_ioport_read(void *op
if (s->read_reg_select)
ret = s->isr;
else
- ret = s->irr;
+ ret = s->irr | s->irr_xen;
} else {
ret = s->imr;
}
@@ -470,18 +494,6 @@ void pic_init(struct hvm_virpic *s, void
spin_unlock_irqrestore(&s->lock, flags);
s->irq_request = irq_request;
s->irq_request_opaque = irq_request_opaque;
-}
-
-void pic_set_alt_irq_func(struct hvm_virpic *s,
- void (*alt_irq_func)(void *, int, int),
- void *alt_irq_opaque)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->alt_irq_func = alt_irq_func;
- s->alt_irq_opaque = alt_irq_opaque;
- spin_unlock_irqrestore(&s->lock, flags);
}
static int intercept_pic_io(ioreq_t *p)
diff -r 477a0084ff47 -r c620b16d4063 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/arch/x86/hvm/svm/intr.c Fri Sep 29 14:42:04 2006 +0100
@@ -122,13 +122,8 @@ asmlinkage void svm_intr_assist(void)
}
callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
- if ( callback_irq != 0 &&
- local_events_need_delivery() ) {
- /*inject para-device call back irq*/
- v->vcpu_info->evtchn_upcall_mask = 1;
- pic_set_irq(pic, callback_irq, 0);
- pic_set_irq(pic, callback_irq, 1);
- }
+ if ( callback_irq != 0)
+ pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
if ( cpu_has_pending_irq(v) )
intr_vector = cpu_get_interrupt(v, &intr_type);
diff -r 477a0084ff47 -r c620b16d4063 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/arch/x86/hvm/vioapic.c Fri Sep 29 14:42:04 2006 +0100
@@ -479,7 +479,7 @@ static void ioapic_deliver(hvm_vioapic_t
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->irr &= ~(1 << irqno);
+ s->irr_xen &= ~(1 << irqno);
}
}
@@ -524,6 +525,25 @@ void hvm_vioapic_do_irqs_clear(struct do
s->irr &= ~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)
diff -r 477a0084ff47 -r c620b16d4063 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/io.c Fri Sep 29 14:42:04 2006 +0100
@@ -92,13 +92,8 @@ asmlinkage void vmx_intr_assist(void)
}
callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
- if ( callback_irq != 0 &&
- local_events_need_delivery() ) {
- /*inject para-device call back irq*/
- v->vcpu_info->evtchn_upcall_mask = 1;
- pic_set_irq(pic, callback_irq, 0);
- pic_set_irq(pic, callback_irq, 1);
- }
+ if ( callback_irq != 0 )
+ pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
has_ext_irq = cpu_has_pending_irq(v);
diff -r 477a0084ff47 -r c620b16d4063 xen/include/asm-x86/hvm/vioapic.h
--- a/xen/include/asm-x86/hvm/vioapic.h Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/include/asm-x86/hvm/vioapic.h Fri Sep 29 14:42:04 2006 +0100
@@ -88,6 +88,7 @@ typedef union RedirStatus
typedef struct hvm_vioapic {
uint32_t irr;
+ uint32_t irr_xen; /* interrupts forced on by the hypervisor. */
uint32_t isr; /* This is used for level trigger */
uint32_t imr;
uint32_t ioregsel;
@@ -105,6 +106,7 @@ hvm_vioapic_t *hvm_vioapic_init(struct d
void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs);
+void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level);
void hvm_vioapic_set_irq(struct domain *d, int irq, int level);
int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
diff -r 477a0084ff47 -r c620b16d4063 xen/include/asm-x86/hvm/vpic.h
--- a/xen/include/asm-x86/hvm/vpic.h Fri Sep 29 11:57:06 2006 +0100
+++ b/xen/include/asm-x86/hvm/vpic.h Fri Sep 29 14:42:04 2006 +0100
@@ -34,6 +34,8 @@ typedef struct PicState {
typedef struct PicState {
uint8_t last_irr; /* edge detection */
uint8_t irr; /* interrupt request register */
+ uint8_t irr_xen; /* interrupts forced on by the hypervisor e.g.
+ the callback irq. */
uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* highest irq priority */
@@ -58,20 +60,16 @@ struct hvm_virpic {
void (*irq_request)(void *opaque, int level);
void *irq_request_opaque;
/* IOAPIC callback support */
- void (*alt_irq_func)(void *opaque, int irq_num, int level);
- void *alt_irq_opaque;
spinlock_t lock;
};
+void pic_set_xen_irq(void *opaque, int irq, int level);
void pic_set_irq(struct hvm_virpic *s, int irq, int level);
void pic_set_irq_new(void *opaque, int irq, int level);
void pic_init(struct hvm_virpic *s,
void (*irq_request)(void *, int),
void *irq_request_opaque);
-void pic_set_alt_irq_func(struct hvm_virpic *s,
- void (*alt_irq_func)(void *, int, int),
- void *alt_irq_opaque);
int pic_read_irq(struct hvm_virpic *s);
void pic_update_irq(struct hvm_virpic *s); /* Caller must hold s->lock */
uint32_t pic_intack_read(struct hvm_virpic *s);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|