Index: sys/xen/xen_intr.c =================================================================== --- sys/xen/xen_intr.c +++ sys/xen/xen_intr.c @@ -237,7 +237,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; @@ -253,7 +253,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); } } @@ -269,14 +271,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); @@ -302,7 +304,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); @@ -370,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) { @@ -384,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); @@ -397,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 @@ -917,20 +921,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 @@ -939,6 +942,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; @@ -954,7 +958,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) { @@ -974,6 +979,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; @@ -989,8 +997,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 }; @@ -1014,6 +1023,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; @@ -1027,7 +1040,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); @@ -1062,7 +1076,6 @@ * responsible for closing it automatically on unbind. */ isrc->xi_close = 1; - isrc->xi_virq = virq; return (0); } @@ -1074,6 +1087,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]; @@ -1089,9 +1105,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 };