ia64/xen-unstable

changeset 11690:c620b16d4063

[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>
author Steven Smith <ssmith@xensource.com>
date Fri Sep 29 14:42:04 2006 +0100 (2006-09-29)
parents 477a0084ff47
children 509ff527c59d
files xen/arch/x86/hvm/i8259.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vmx/io.c xen/include/asm-x86/hvm/vioapic.h xen/include/asm-x86/hvm/vpic.h
line diff
     1.1 --- a/xen/arch/x86/hvm/i8259.c	Fri Sep 29 11:57:06 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/i8259.c	Fri Sep 29 14:42:04 2006 +0100
     1.3 @@ -86,7 +86,7 @@ static int pic_get_irq(PicState *s)
     1.4  
     1.5      ASSERT(spin_is_locked(&s->pics_state->lock));
     1.6  
     1.7 -    mask = s->irr & ~s->imr;
     1.8 +    mask = (s->irr|s->irr_xen) & ~s->imr;
     1.9      priority = get_priority(s, mask);
    1.10      if (priority == 8)
    1.11          return -1;
    1.12 @@ -128,6 +128,32 @@ void pic_update_irq(struct hvm_virpic *s
    1.13      }
    1.14  }
    1.15  
    1.16 +void pic_set_xen_irq(void *opaque, int irq, int level)
    1.17 +{
    1.18 +    struct hvm_virpic *s = opaque;
    1.19 +    unsigned long flags;
    1.20 +    PicState *ps;
    1.21 +
    1.22 +    spin_lock_irqsave(&s->lock, flags);
    1.23 +
    1.24 +    hvm_vioapic_set_xen_irq(current->domain, irq, level);
    1.25 +
    1.26 +    /* Set it on the 8259s */
    1.27 +    ps = &s->pics[irq >> 3];
    1.28 +    if (!(ps->elcr & (1 << (irq & 7)))) {
    1.29 +	DPRINTK("edge-triggered override IRQ?\n");
    1.30 +	domain_crash(current->domain);
    1.31 +    }
    1.32 +    if (level) {
    1.33 +	ps->irr_xen |= 1 << (irq & 7);
    1.34 +    } else {
    1.35 +	ps->irr_xen &= ~(1 << (irq & 7));
    1.36 +    }
    1.37 +
    1.38 +    pic_update_irq(s);
    1.39 +    spin_unlock_irqrestore(&s->lock, flags);
    1.40 +}
    1.41 +
    1.42  void pic_set_irq_new(void *opaque, int irq, int level)
    1.43  {
    1.44      struct hvm_virpic *s = opaque;
    1.45 @@ -136,9 +162,6 @@ void pic_set_irq_new(void *opaque, int i
    1.46      spin_lock_irqsave(&s->lock, flags);
    1.47      hvm_vioapic_set_irq(current->domain, irq, level);
    1.48      pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
    1.49 -    /* used for IOAPIC irqs */
    1.50 -    if (s->alt_irq_func)
    1.51 -        s->alt_irq_func(s->alt_irq_opaque, irq, level);
    1.52      pic_update_irq(s);
    1.53      spin_unlock_irqrestore(&s->lock, flags);
    1.54  }
    1.55 @@ -371,6 +394,7 @@ static uint32_t pic_poll_read (PicState 
    1.56              s->pics_state->pics[0].irr &= ~(1 << 2);
    1.57          }
    1.58          s->irr &= ~(1 << ret);
    1.59 +        s->irr_xen &= ~(1 << ret);
    1.60          s->isr &= ~(1 << ret);
    1.61          if (addr1 >> 7 || ret != 2)
    1.62              pic_update_irq(s->pics_state);
    1.63 @@ -400,7 +424,7 @@ static uint32_t pic_ioport_read(void *op
    1.64              if (s->read_reg_select)
    1.65                  ret = s->isr;
    1.66              else
    1.67 -                ret = s->irr;
    1.68 +                ret = s->irr | s->irr_xen;
    1.69          } else {
    1.70              ret = s->imr;
    1.71          }
    1.72 @@ -472,18 +496,6 @@ void pic_init(struct hvm_virpic *s, void
    1.73      s->irq_request_opaque = irq_request_opaque;
    1.74  }
    1.75  
    1.76 -void pic_set_alt_irq_func(struct hvm_virpic *s,
    1.77 -                          void (*alt_irq_func)(void *, int, int),
    1.78 -                          void *alt_irq_opaque)
    1.79 -{
    1.80 -    unsigned long flags;
    1.81 -
    1.82 -    spin_lock_irqsave(&s->lock, flags);
    1.83 -    s->alt_irq_func = alt_irq_func;
    1.84 -    s->alt_irq_opaque = alt_irq_opaque;
    1.85 -    spin_unlock_irqrestore(&s->lock, flags);
    1.86 -}
    1.87 -
    1.88  static int intercept_pic_io(ioreq_t *p)
    1.89  {
    1.90      struct hvm_virpic  *pic;
     2.1 --- a/xen/arch/x86/hvm/svm/intr.c	Fri Sep 29 11:57:06 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Fri Sep 29 14:42:04 2006 +0100
     2.3 @@ -122,13 +122,8 @@ asmlinkage void svm_intr_assist(void)
     2.4        }
     2.5  
     2.6        callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
     2.7 -      if ( callback_irq != 0 &&
     2.8 -           local_events_need_delivery() ) {
     2.9 -          /*inject para-device call back irq*/
    2.10 -          v->vcpu_info->evtchn_upcall_mask = 1;
    2.11 -          pic_set_irq(pic, callback_irq, 0);
    2.12 -          pic_set_irq(pic, callback_irq, 1);
    2.13 -      }
    2.14 +      if ( callback_irq != 0)
    2.15 +          pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
    2.16  
    2.17        if ( cpu_has_pending_irq(v) )
    2.18            intr_vector = cpu_get_interrupt(v, &intr_type);
     3.1 --- a/xen/arch/x86/hvm/vioapic.c	Fri Sep 29 11:57:06 2006 +0100
     3.2 +++ b/xen/arch/x86/hvm/vioapic.c	Fri Sep 29 14:42:04 2006 +0100
     3.3 @@ -479,7 +479,7 @@ static void ioapic_deliver(hvm_vioapic_t
     3.4  
     3.5  static int ioapic_get_highest_irq(hvm_vioapic_t *s)
     3.6  {
     3.7 -    uint32_t irqs = s->irr & ~s->isr & ~s->imr;
     3.8 +    uint32_t irqs = (s->irr | s->irr_xen) & ~s->isr & ~s->imr;
     3.9      return fls(irqs) - 1;
    3.10  }
    3.11  
    3.12 @@ -501,6 +501,7 @@ static void service_ioapic(hvm_vioapic_t
    3.13          }
    3.14  
    3.15          s->irr &= ~(1 << irqno);
    3.16 +	s->irr_xen &= ~(1 << irqno);
    3.17      }
    3.18  }
    3.19  
    3.20 @@ -526,6 +527,25 @@ void hvm_vioapic_do_irqs_clear(struct do
    3.21      service_ioapic(s);
    3.22  }
    3.23  
    3.24 +void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level)
    3.25 +{
    3.26 +    hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic;
    3.27 +
    3.28 +    if (!hvm_apic_support(d) || !IOAPICEnabled(s) ||
    3.29 +	s->redirtbl[irq].RedirForm.mask)
    3.30 +        return;
    3.31 +
    3.32 +    if (s->redirtbl[irq].RedirForm.trigmod != IOAPIC_LEVEL_TRIGGER) {
    3.33 +	DPRINTK("Forcing edge triggered APIC irq %d?\n", irq);
    3.34 +	domain_crash(d);
    3.35 +    }
    3.36 +
    3.37 +    if (level)
    3.38 +	s->irr_xen |= 1 << irq;
    3.39 +    else
    3.40 +	s->irr_xen &= ~(1 << irq);
    3.41 +}
    3.42 +
    3.43  void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
    3.44  {
    3.45      hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
     4.1 --- a/xen/arch/x86/hvm/vmx/io.c	Fri Sep 29 11:57:06 2006 +0100
     4.2 +++ b/xen/arch/x86/hvm/vmx/io.c	Fri Sep 29 14:42:04 2006 +0100
     4.3 @@ -92,13 +92,8 @@ asmlinkage void vmx_intr_assist(void)
     4.4      }
     4.5  
     4.6      callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
     4.7 -    if ( callback_irq != 0 &&
     4.8 -         local_events_need_delivery() ) {
     4.9 -        /*inject para-device call back irq*/
    4.10 -        v->vcpu_info->evtchn_upcall_mask = 1;
    4.11 -        pic_set_irq(pic, callback_irq, 0);
    4.12 -        pic_set_irq(pic, callback_irq, 1);
    4.13 -    }
    4.14 +    if ( callback_irq != 0 )
    4.15 +        pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
    4.16  
    4.17      has_ext_irq = cpu_has_pending_irq(v);
    4.18  
     5.1 --- a/xen/include/asm-x86/hvm/vioapic.h	Fri Sep 29 11:57:06 2006 +0100
     5.2 +++ b/xen/include/asm-x86/hvm/vioapic.h	Fri Sep 29 14:42:04 2006 +0100
     5.3 @@ -88,6 +88,7 @@ typedef union RedirStatus
     5.4  
     5.5  typedef struct hvm_vioapic {
     5.6      uint32_t irr;
     5.7 +    uint32_t irr_xen; /* interrupts forced on by the hypervisor. */
     5.8      uint32_t isr;           /* This is used for level trigger */
     5.9      uint32_t imr;
    5.10      uint32_t ioregsel;
    5.11 @@ -105,6 +106,7 @@ hvm_vioapic_t *hvm_vioapic_init(struct d
    5.12  
    5.13  void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
    5.14  void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs);
    5.15 +void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level);
    5.16  void hvm_vioapic_set_irq(struct domain *d, int irq, int level);
    5.17  
    5.18  int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
     6.1 --- a/xen/include/asm-x86/hvm/vpic.h	Fri Sep 29 11:57:06 2006 +0100
     6.2 +++ b/xen/include/asm-x86/hvm/vpic.h	Fri Sep 29 14:42:04 2006 +0100
     6.3 @@ -34,6 +34,8 @@ typedef struct IOAPICState IOAPICState;
     6.4  typedef struct PicState {
     6.5      uint8_t last_irr; /* edge detection */
     6.6      uint8_t irr; /* interrupt request register */
     6.7 +    uint8_t irr_xen; /* interrupts forced on by the hypervisor e.g.
     6.8 +			the callback irq. */
     6.9      uint8_t imr; /* interrupt mask register */
    6.10      uint8_t isr; /* interrupt service register */
    6.11      uint8_t priority_add; /* highest irq priority */
    6.12 @@ -58,20 +60,16 @@ struct hvm_virpic {
    6.13      void (*irq_request)(void *opaque, int level);
    6.14      void *irq_request_opaque;
    6.15      /* IOAPIC callback support */
    6.16 -    void (*alt_irq_func)(void *opaque, int irq_num, int level);
    6.17 -    void *alt_irq_opaque;
    6.18      spinlock_t lock;
    6.19  };
    6.20  
    6.21  
    6.22 +void pic_set_xen_irq(void *opaque, int irq, int level);
    6.23  void pic_set_irq(struct hvm_virpic *s, int irq, int level);
    6.24  void pic_set_irq_new(void *opaque, int irq, int level);
    6.25  void pic_init(struct hvm_virpic *s, 
    6.26                void (*irq_request)(void *, int),
    6.27                void *irq_request_opaque);
    6.28 -void pic_set_alt_irq_func(struct hvm_virpic *s, 
    6.29 -                          void (*alt_irq_func)(void *, int, int),
    6.30 -                          void *alt_irq_opaque);
    6.31  int pic_read_irq(struct hvm_virpic *s);
    6.32  void pic_update_irq(struct hvm_virpic *s); /* Caller must hold s->lock */
    6.33  uint32_t pic_intack_read(struct hvm_virpic *s);