diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c index 03ccd7ceb8a2..a964fac7161c 100644 --- a/sys/x86/xen/xen_intr.c +++ b/sys/x86/xen/xen_intr.c @@ -126,7 +126,6 @@ struct xenisrc { int xi_virq; void *xi_cookie; u_int xi_close:1; /* close on unbind? */ - u_int xi_shared:1; /* Shared with other domains. */ u_int xi_activehi:1; u_int xi_edgetrigger:1; }; @@ -579,11 +578,12 @@ xen_intr_handle_upcall(struct trapframe *trap_frame) /* process port */ port = (l1i * LONG_BIT) + l2i; - synch_clear_bit(port, &s->evtchn_pending[0]); isrc = xen_intr_port_to_isrc[port]; - if (__predict_false(isrc == NULL)) + if (__predict_false(isrc == NULL)) { + synch_clear_bit(port, &s->evtchn_pending[0]); continue; + } /* Make sure we are firing on the right vCPU */ KASSERT((isrc->xi_cpu == PCPU_GET(cpuid)), @@ -932,6 +932,9 @@ out: static void xen_intr_disable_source(struct intsrc *isrc, int eoi) { + + if (eoi == PIC_EOI) + xen_intr_eoi_source(isrc); } /* @@ -950,8 +953,13 @@ xen_intr_enable_source(struct intsrc *isrc) * \param isrc The interrupt source to EOI. */ static void -xen_intr_eoi_source(struct intsrc *isrc) +xen_intr_eoi_source(struct intsrc *base_isrc) { + struct xenisrc *isrc; + + isrc = (struct xenisrc *)base_isrc; + synch_clear_bit(isrc->xi_port, + &HYPERVISOR_shared_info->evtchn_pending[0]); } /* @@ -981,8 +989,9 @@ xen_intr_pirq_disable_source(struct intsrc *base_isrc, int eoi) struct xenisrc *isrc; isrc = (struct xenisrc *)base_isrc; - evtchn_mask_port(isrc->xi_port); + if (isrc->xi_edgetrigger == 0) + evtchn_mask_port(isrc->xi_port); if (eoi == PIC_EOI) xen_intr_pirq_eoi_source(base_isrc); } @@ -998,7 +1007,9 @@ xen_intr_pirq_enable_source(struct intsrc *base_isrc) struct xenisrc *isrc; isrc = (struct xenisrc *)base_isrc; - evtchn_unmask_port(isrc->xi_port); + + if (isrc->xi_edgetrigger == 0) + evtchn_unmask_port(isrc->xi_port); } /* @@ -1010,13 +1021,19 @@ static void xen_intr_pirq_eoi_source(struct intsrc *base_isrc) { struct xenisrc *isrc; + int error; - /* XXX Use shared page of flags for this. */ isrc = (struct xenisrc *)base_isrc; + + synch_clear_bit(isrc->xi_port, + &HYPERVISOR_shared_info->evtchn_pending[0]); if (test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map)) { struct physdev_eoi eoi = { .irq = isrc->xi_pirq }; - (void)HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); + error = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); + if (error != 0) + panic("Unable to EOI PIRQ#%d: %d\n", + isrc->xi_pirq, error); } } @@ -1361,7 +1378,6 @@ int xen_register_pirq(int vector, enum intr_trigger trig, enum intr_polarity pol) { struct physdev_map_pirq map_pirq; - struct physdev_irq alloc_pirq; struct xenisrc *isrc; int error; @@ -1382,14 +1398,6 @@ xen_register_pirq(int vector, enum intr_trigger trig, enum intr_polarity pol) return (error); } - alloc_pirq.irq = vector; - alloc_pirq.vector = 0; - error = HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &alloc_pirq); - if (error) { - printf("xen: unable to alloc PIRQ for IRQ#%d\n", vector); - return (error); - } - mtx_lock(&xen_intr_isrc_lock); isrc = xen_intr_alloc_isrc(EVTCHN_TYPE_PIRQ, vector); mtx_unlock(&xen_intr_isrc_lock); @@ -1432,6 +1440,8 @@ xen_register_msi(device_t dev, int vector, int count) KASSERT(isrc != NULL, ("xen: unable to allocate isrc for interrupt")); isrc->xi_pirq = msi_irq.pirq + i; + /* MSI interrupts are always edge triggered */ + isrc->xi_edgetrigger = 1; } mtx_unlock(&xen_intr_isrc_lock); @@ -1573,10 +1583,9 @@ xen_intr_dump_port(struct xenisrc *isrc) isrc->xi_port, xen_intr_print_type(isrc->xi_type)); if (isrc->xi_type == EVTCHN_TYPE_PIRQ) { db_printf("\tPirq: %d ActiveHi: %d EdgeTrigger: %d " - "NeedsEOI: %d Shared: %d\n", + "NeedsEOI: %d\n", isrc->xi_pirq, isrc->xi_activehi, isrc->xi_edgetrigger, - !!test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map), - isrc->xi_shared); + !!test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map)); } if (isrc->xi_type == EVTCHN_TYPE_VIRQ) db_printf("\tVirq: %d\n", isrc->xi_virq);