Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -120,9 +120,10 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info); -#define XEN_INVALID_EVTCHN 0 /* Invalid event channel */ +#define INVALID_PORT ~0 /* Invalid xi_port value */ -#define is_valid_evtchn(x) ((x) != XEN_INVALID_EVTCHN) +#define is_valid_evtchn(x) ((uint64_t)(x) - 1 < NR_EVENT_CHANNELS) +#define isrc_port_valid(i) ((uint64_t)((i)->xi_port) < NR_EVENT_CHANNELS) struct xen_arch_isrc { struct intsrc xai_intsrc; /* @TOP -> *xen_arch_isrc */ @@ -232,7 +233,7 @@ * event channel globally, use evtchn_mask(). */ static inline void -evtchn_cpu_mask_port(u_int cpu, evtchn_port_t port) +xen_intr_cpu_mask_port(u_int cpu, evtchn_port_t port) { struct xen_intr_pcpu_data *pcpu; @@ -254,7 +255,7 @@ * also be globally enabled. See evtchn_unmask(). */ static inline void -evtchn_cpu_unmask_port(u_int cpu, evtchn_port_t port) +xen_intr_cpu_unmask_port(u_int cpu, evtchn_port_t port) { struct xen_intr_pcpu_data *pcpu; @@ -337,7 +338,7 @@ 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__); @@ -376,15 +377,15 @@ mtx_lock(&xen_intr_isrc_lock); KASSERT(isrc->xi_arch.xai_intsrc.is_handlers == 0, ("Release called, but xenisrc still in use")); - evtchn_mask_port(isrc->xi_port); - evtchn_clear_port(isrc->xi_port); + evtchn_mask_port(isrc->xi_port + 1); + evtchn_clear_port(isrc->xi_port + 1); /* Rebind port to CPU 0. */ - evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); - evtchn_cpu_unmask_port(0, isrc->xi_port); + xen_intr_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); + xen_intr_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 (isrc->xi_close != 0 && isrc_port_valid(isrc)) { + struct evtchn_close close = { .port = isrc->xi_port + 1 }; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) panic("EVTCHNOP_close failed"); } @@ -394,7 +395,7 @@ mtx_unlock(&xen_intr_isrc_lock); isrc->xi_cpu = 0; - isrc->xi_port = 0; + isrc->xi_port = INVALID_PORT; isrc->xi_cookie = NULL; mtx_lock(&xen_intr_x86_lock); isrc->xi_type = EVTCHN_TYPE_UNBOUND; @@ -443,8 +444,8 @@ if (isrc == NULL) return (ENOSPC); mtx_lock(&xen_intr_isrc_lock); - isrc->xi_port = local_port; - xen_intr_port_to_isrc[local_port] = isrc; + isrc->xi_port = local_port - 1; + xen_intr_port_to_isrc[isrc->xi_port] = isrc; refcount_init(&isrc->xi_refcount, 1); mtx_unlock(&xen_intr_isrc_lock); @@ -715,7 +716,7 @@ if (error != 0) panic("unable to rebind xen IPI: %d", error); - isrc->xi_port = bind_ipi.port; + isrc->xi_port = bind_ipi.port - 1; #else panic("Resume IPI event channel on UP"); #endif @@ -735,7 +736,7 @@ if (error != 0) panic("unable to rebind xen VIRQ#%d: %d", isrc->xi_virq, error); - isrc->xi_port = bind_virq.port; + isrc->xi_port = bind_virq.port - 1; } static void @@ -744,7 +745,7 @@ int cpu = isrc->xi_cpu; int error; - isrc->xi_port = 0; + isrc->xi_port = INVALID_PORT; switch (isrc->xi_type) { case EVTCHN_TYPE_IPI: xen_rebind_ipi(isrc); @@ -799,35 +800,35 @@ /* Clear existing port mappings */ for (isrc_idx = 0; isrc_idx < NR_EVENT_CHANNELS; ++isrc_idx) if (xen_intr_port_to_isrc[isrc_idx] != NULL) - xen_intr_port_to_isrc[isrc_idx]->xi_port = ~0; + xen_intr_port_to_isrc[isrc_idx]->xi_port = INVALID_PORT; /* Remap in-use isrcs, using xen_intr_port_to_isrc as listing */ for (isrc_idx = 0; isrc_idx < NR_EVENT_CHANNELS; ++isrc_idx) { struct xenisrc *cur = xen_intr_port_to_isrc[isrc_idx]; /* empty or entry already taken care of */ - if (cur == NULL || cur->xi_port != ~0) + if (cur == NULL || isrc_port_valid(cur)) continue; xen_intr_port_to_isrc[isrc_idx] = NULL; do { struct xenisrc *next; - KASSERT(cur->xi_port == ~0, + KASSERT(!isrc_port_valid(cur), ("%s(): Multiple channels on single intr?", __func__)); xen_intr_rebind_isrc(cur); /* invalid entry left behind? */ - if (!is_valid_evtchn(cur->xi_port)) + if (!isrc_port_valid(cur)) break; next = xen_intr_port_to_isrc[cur->xi_port]; xen_intr_port_to_isrc[cur->xi_port] = cur; - evtchn_unmask_port(cur->xi_port); + evtchn_unmask_port(cur->xi_port + 1); cur = next; } while (cur != NULL); @@ -848,7 +849,7 @@ { struct xenisrc *isrc = (struct xenisrc *)base_isrc; - evtchn_mask_port(isrc->xi_port); + evtchn_mask_port(isrc->xi_port + 1); } /** @@ -927,7 +928,7 @@ mtx_lock(&xen_intr_isrc_lock); isrc = (struct xenisrc *)base_isrc; - if (!is_valid_evtchn(isrc->xi_port)) { + if (!isrc_port_valid(isrc)) { mtx_unlock(&xen_intr_isrc_lock); return (EINVAL); } @@ -936,7 +937,7 @@ * Mask the event channel while binding it to prevent interrupt * delivery with an inconsistent state in isrc->xi_cpu. */ - masked = evtchn_test_and_set_mask(isrc->xi_port); + masked = evtchn_test_and_set_mask(isrc->xi_port + 1); if ((isrc->xi_type == EVTCHN_TYPE_VIRQ) || (isrc->xi_type == EVTCHN_TYPE_IPI)) { /* @@ -944,28 +945,28 @@ * the Hypervisor at evtchn_bind_virq time, so * all we need to do is update the per-CPU masks. */ - evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); + xen_intr_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); isrc->xi_cpu = to_cpu; - evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); + xen_intr_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); goto out; } - bind_vcpu.port = isrc->xi_port; + bind_vcpu.port = isrc->xi_port + 1; bind_vcpu.vcpu = vcpu_id; error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu); if (isrc->xi_cpu != to_cpu) { if (error == 0) { /* Commit to new binding by removing the old one. */ - evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); + xen_intr_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); isrc->xi_cpu = to_cpu; - evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); + xen_intr_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); } } out: if (masked == 0) - evtchn_unmask_port(isrc->xi_port); + evtchn_unmask_port(isrc->xi_port + 1); mtx_unlock(&xen_intr_isrc_lock); return (0); #else @@ -1012,7 +1013,7 @@ isrc = (struct xenisrc *)base_isrc; if (isrc->xi_masked == 0) - evtchn_unmask_port(isrc->xi_port); + evtchn_unmask_port(isrc->xi_port + 1); } /* @@ -1035,7 +1036,7 @@ { struct xenisrc *isrc = (struct xenisrc *)base_isrc; - evtchn_unmask_port(isrc->xi_port); + evtchn_unmask_port(isrc->xi_port + 1); } /*--------------------------- Public Functions -------------------------------*/ @@ -1303,7 +1304,7 @@ KASSERT(isrc->xi_type == EVTCHN_TYPE_PORT || isrc->xi_type == EVTCHN_TYPE_IPI, ("evtchn_signal on something other than a local port")); - struct evtchn_send send = { .port = isrc->xi_port }; + struct evtchn_send send = { .port = isrc->xi_port + 1 }; (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); } } @@ -1317,7 +1318,7 @@ if (isrc == NULL) return (0); - return (isrc->xi_port); + return (isrc->xi_port + 1); } int @@ -1345,7 +1346,7 @@ xen_intr_get_evtchn_from_port(evtchn_port_t port, xen_intr_handle_t *handlep) { - if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS) + if (!is_valid_evtchn(port)) return (EINVAL); if (handlep == NULL) { @@ -1391,7 +1392,7 @@ int i; db_printf("Port %d Type: %s\n", - isrc->xi_port, xen_intr_print_type(isrc->xi_type)); + isrc->xi_port + 1, xen_intr_print_type(isrc->xi_type)); if (isrc->xi_type == EVTCHN_TYPE_VIRQ) db_printf("\tVirq: %d\n", isrc->xi_virq);