[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN][HVM] Make sure that the interrupt which event channel events come in



# HG changeset patch
# User Steven Smith <ssmith@xxxxxxxxxxxxx>
# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.