Index: sys/x86/xen/xen_intr.c =================================================================== --- sys/x86/xen/xen_intr.c +++ sys/x86/xen/xen_intr.c @@ -120,10 +120,6 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info); -#define XEN_INVALID_EVTCHN 0 /* Invalid event channel */ - -#define is_valid_evtchn(x) ((x) != XEN_INVALID_EVTCHN) - struct xenisrc { struct intsrc xi_intsrc; enum evtchn_type xi_type; @@ -333,10 +329,10 @@ return (isrc); } - if (xen_intr_auto_vector_count > NR_EVENT_CHANNELS) { + if (xen_intr_auto_vector_count >= NR_EVENT_CHANNELS) { if (!warned) { warned = 1; - printf("%s: Event channels exhausted.\n", __func__); + printf("%s: Xen interrupts exhausted.\n", __func__); } mtx_unlock(&xen_intr_x86_lock); return (NULL); @@ -382,18 +378,22 @@ evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); evtchn_cpu_unmask_port(0, isrc->xi_port); - if (isrc->xi_close != 0 && is_valid_evtchn(isrc->xi_port)) { - struct evtchn_close close = { .port = isrc->xi_port }; - if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) - panic("EVTCHNOP_close failed"); - } + if (isrc->xi_port < NR_EVENT_CHANNELS) { + if (isrc->xi_close != 0) { + struct evtchn_close close = { .port = isrc->xi_port }; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) + panic("EVTCHNOP_close failed"); + } - xen_intr_port_to_isrc[isrc->xi_port] = NULL; + /* another thread could have grabbed if caller already closed */ + if (xen_intr_port_to_isrc[isrc->xi_port] == isrc) + xen_intr_port_to_isrc[isrc->xi_port] = NULL; + } /* not reachable from xen_intr_port_to_isrc[], therefore unlock */ mtx_unlock(&xen_intr_isrc_lock); isrc->xi_cpu = 0; - isrc->xi_port = 0; + isrc->xi_port = ~0; isrc->xi_cookie = NULL; /* * Fun with locking here. xen_intr_x86_lock is actually controlling @@ -448,7 +448,7 @@ return (ENOSPC); mtx_lock(&xen_intr_isrc_lock); isrc->xi_port = local_port; - xen_intr_port_to_isrc[local_port] = isrc; + xen_intr_port_to_isrc[isrc->xi_port] = isrc; refcount_init(&isrc->xi_refcount, 1); mtx_unlock(&xen_intr_isrc_lock); @@ -714,7 +714,7 @@ isrc->xi_port = bind_ipi.port; isrc->xi_cpu = 0; - xen_intr_port_to_isrc[bind_ipi.port] = isrc; + xen_intr_port_to_isrc[isrc->xi_port] = isrc; error = xen_intr_assign_cpu(&isrc->xi_intsrc, cpu_apic_ids[cpu]); @@ -722,7 +722,7 @@ panic("unable to bind xen IPI to CPU#%d: %d", cpu, error); - evtchn_unmask_port(bind_ipi.port); + evtchn_unmask_port(isrc->xi_port); #else panic("Resume IPI event channel on UP"); #endif @@ -744,7 +744,7 @@ isrc->xi_port = bind_virq.port; isrc->xi_cpu = 0; - xen_intr_port_to_isrc[bind_virq.port] = isrc; + xen_intr_port_to_isrc[isrc->xi_port] = isrc; #ifdef SMP error = xen_intr_assign_cpu(&isrc->xi_intsrc, @@ -754,7 +754,7 @@ isrc->xi_virq, cpu, error); #endif - evtchn_unmask_port(bind_virq.port); + evtchn_unmask_port(isrc->xi_port); } /** @@ -794,7 +794,7 @@ vector = first_evtchn_irq + isrc_idx; isrc = (struct xenisrc *)intr_lookup_source(vector); if (isrc != NULL) { - isrc->xi_port = 0; + isrc->xi_port = ~0; switch (isrc->xi_type) { case EVTCHN_TYPE_IPI: xen_rebind_ipi(isrc); @@ -898,7 +898,7 @@ mtx_lock(&xen_intr_isrc_lock); isrc = (struct xenisrc *)base_isrc; - if (!is_valid_evtchn(isrc->xi_port)) { + if (isrc->xi_port >= NR_EVENT_CHANNELS) { mtx_unlock(&xen_intr_isrc_lock); return (EINVAL); } @@ -1317,7 +1317,8 @@ xen_intr_get_evtchn_from_port(evtchn_port_t port, xen_intr_handle_t *handlep) { - if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS) + /* event channel 0 is reserved, >= NR_EVENT_CHANNELS is invalid */ + if (port == 0 || port >= NR_EVENT_CHANNELS) return (EINVAL); if (handlep == NULL) {