Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -236,7 +236,7 @@ * \return A pointer to a free Xen interrupt source object or NULL. */ static struct xenisrc * -xen_intr_find_unused_isrc(enum evtchn_type type) +xen_intr_find_unused_isrc(const struct xenisrc *const params) { int isrc_idx; @@ -252,7 +252,9 @@ && isrc->xi_type == EVTCHN_TYPE_UNBOUND) { KASSERT(xen_arch_intr_has_handlers(isrc), ("Free evtchn still has handlers")); - isrc->xi_type = type; + CTASSERT(offsetof(struct xenisrc, xi_arch) == 0); + memcpy(&isrc->xi_arch + 1, ¶ms->xi_arch + 1, + sizeof(struct xenisrc) - sizeof(xen_arch_isrc_t)); return (isrc); } } @@ -268,14 +270,14 @@ * object or NULL. */ static struct xenisrc * -xen_intr_alloc_isrc(enum evtchn_type type) +xen_intr_alloc_isrc(const struct xenisrc *const params) { static int warned; struct xenisrc *isrc; unsigned int vector; mtx_lock(&xen_intr_x86_lock); - isrc = xen_intr_find_unused_isrc(type); + isrc = xen_intr_find_unused_isrc(params); if (isrc != NULL) { mtx_unlock(&xen_intr_x86_lock); @@ -301,7 +303,10 @@ isrc = malloc(sizeof(*isrc), M_XENINTR, M_WAITOK | M_ZERO); isrc->xi_arch.xai_intsrc.is_pic = &xen_intr_pic; isrc->xi_arch.xai_vector = vector; - isrc->xi_type = type; + + CTASSERT(offsetof(struct xenisrc, xi_arch) == 0); + memcpy(&isrc->xi_arch + 1, ¶ms->xi_arch + 1, + sizeof(struct xenisrc) - sizeof(xen_arch_isrc_t)); intr_register_source(&isrc->xi_arch.xai_intsrc); return (isrc); @@ -332,6 +337,7 @@ struct evtchn_close close = { .port = isrc->xi_port }; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) panic("EVTCHNOP_close failed"); + isrc->xi_close = 0; /* mark as closed */ } xen_intr_port_to_isrc[isrc->xi_port] = NULL; @@ -369,8 +375,8 @@ * \returns 0 on success, otherwise an errno. */ static int -xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port, - enum evtchn_type type, const char *intr_owner, driver_filter_t filter, +xen_intr_bind_isrc(struct xenisrc **isrcp, const struct xenisrc *params, + const char *intr_owner, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, xen_intr_handle_t *port_handlep) { @@ -383,11 +389,10 @@ return (EINVAL); } - isrc = xen_intr_alloc_isrc(type); + isrc = xen_intr_alloc_isrc(params); if (isrc == NULL) return (ENOSPC); mtx_lock(&xen_intr_isrc_lock); - isrc->xi_port = local_port; xen_intr_port_to_isrc[isrc->xi_port] = isrc; refcount_init(&isrc->xi_refcount, 1); mtx_unlock(&xen_intr_isrc_lock); @@ -396,7 +401,7 @@ *port_handlep = xen_intr_handle_from_isrc(isrc); #ifdef SMP - if (type == EVTCHN_TYPE_PORT) { + if (params->xi_type == EVTCHN_TYPE_PORT) { /* * By default all interrupts are assigned to vCPU#0 * unless specified otherwise, so shuffle them to balance @@ -927,20 +932,19 @@ enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; - int error; + struct xenisrc params = { + .xi_type = EVTCHN_TYPE_PORT, + .xi_port = local_port, + /* + * The Event Channel API didn't open this port, so it is not + * responsible for closing it automatically on unbind. + */ + .xi_close = 0, + }; - error = xen_intr_bind_isrc(&isrc, local_port, EVTCHN_TYPE_PORT, + return (xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, flags, - port_handlep); - if (error != 0) - return (error); - - /* - * The Event Channel API didn't open this port, so it is not - * responsible for closing it automatically on unbind. - */ - isrc->xi_close = 0; - return (0); + port_handlep)); } int @@ -949,6 +953,7 @@ enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; + struct xenisrc params = { .xi_type = EVTCHN_TYPE_PORT, }; struct evtchn_alloc_unbound alloc_unbound; int error; @@ -964,7 +969,8 @@ return (-error); } - error = xen_intr_bind_isrc(&isrc, alloc_unbound.port, EVTCHN_TYPE_PORT, + params.xi_port = alloc_unbound.port; + error = xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, flags, port_handlep); if (error != 0) { @@ -984,6 +990,9 @@ void *arg, enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; + struct xenisrc params = { + .xi_type = EVTCHN_TYPE_PORT, + }; struct evtchn_bind_interdomain bind_interdomain; int error; @@ -999,8 +1008,9 @@ return (-error); } - error = xen_intr_bind_isrc(&isrc, bind_interdomain.local_port, - EVTCHN_TYPE_PORT, device_get_nameunit(dev), filter, handler, arg, + params.xi_port = bind_interdomain.local_port; + error = xen_intr_bind_isrc(&isrc, ¶ms, + device_get_nameunit(dev), filter, handler, arg, flags, port_handlep); if (error) { evtchn_close_t close = { .port = bind_interdomain.local_port }; @@ -1024,6 +1034,10 @@ { int vcpu_id = PCPU_ID_GET(cpu); struct xenisrc *isrc; + struct xenisrc params = { + .xi_type = EVTCHN_TYPE_VIRQ, + .xi_virq = virq, + }; struct evtchn_bind_virq bind_virq = { .virq = virq, .vcpu = vcpu_id }; int error; @@ -1037,7 +1051,8 @@ return (-error); } - error = xen_intr_bind_isrc(&isrc, bind_virq.port, EVTCHN_TYPE_VIRQ, + params.xi_port = bind_virq.port; + error = xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, flags, port_handlep); @@ -1072,7 +1087,6 @@ * responsible for closing it automatically on unbind. */ isrc->xi_close = 1; - isrc->xi_virq = virq; return (0); } @@ -1084,6 +1098,9 @@ #ifdef SMP int vcpu_id = PCPU_ID_GET(cpu); struct xenisrc *isrc; + struct xenisrc params = { + .xi_type = EVTCHN_TYPE_IPI, + }; struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; /* Same size as the one used by intr_handler->ih_name. */ char name[MAXCOMLEN + 1]; @@ -1099,9 +1116,10 @@ return (-error); } + params.xi_port = bind_ipi.port; snprintf(name, sizeof(name), "cpu%u", cpu); - error = xen_intr_bind_isrc(&isrc, bind_ipi.port, EVTCHN_TYPE_IPI, + error = xen_intr_bind_isrc(&isrc, ¶ms, name, filter, NULL, NULL, flags, port_handlep); if (error != 0) { evtchn_close_t close = { .port = bind_ipi.port };