diff options
-rw-r--r-- | xen/arch/x86/hvm/i8259.c | 46 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/intr.c | 9 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vioapic.c | 22 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/io.c | 9 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vioapic.h | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vpic.h | 8 |
6 files changed, 59 insertions, 37 deletions
diff --git a/xen/arch/x86/hvm/i8259.c b/xen/arch/x86/hvm/i8259.c index 4e29cbfa85..e90f365044 100644 --- a/xen/arch/x86/hvm/i8259.c +++ b/xen/arch/x86/hvm/i8259.c @@ -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 irq, int level) 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, uint32_t addr1) 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 *opaque, uint32_t addr1) if (s->read_reg_select) ret = s->isr; else - ret = s->irr; + ret = s->irr | s->irr_xen; } else { ret = s->imr; } @@ -472,18 +496,6 @@ void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int), 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) { struct hvm_virpic *pic; diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index d053c6d122..1e283d8bbe 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -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 --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); diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c index 75632a41d6..ae8d89a31d 100644 --- a/xen/arch/x86/hvm/vmx/io.c +++ b/xen/arch/x86/hvm/vmx/io.c @@ -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 --git a/xen/include/asm-x86/hvm/vioapic.h b/xen/include/asm-x86/hvm/vioapic.h index 72c758c133..b5ec7e4597 100644 --- a/xen/include/asm-x86/hvm/vioapic.h +++ b/xen/include/asm-x86/hvm/vioapic.h @@ -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 domain *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 --git a/xen/include/asm-x86/hvm/vpic.h b/xen/include/asm-x86/hvm/vpic.h index 8fa5daa5ad..f6a488e339 100644 --- a/xen/include/asm-x86/hvm/vpic.h +++ b/xen/include/asm-x86/hvm/vpic.h @@ -34,6 +34,8 @@ typedef struct IOAPICState IOAPICState; 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); |