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)); if (intr_register_source(&isrc->xi_arch.xai_intsrc) != 0) { free(isrc, M_XENINTR); return (NULL); @@ -380,8 +385,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) { @@ -394,11 +399,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); @@ -407,7 +411,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 @@ -923,20 +927,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 @@ -945,6 +948,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; @@ -960,11 +964,12 @@ 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) { - evtchn_close_t close = { .port = alloc_unbound.port }; + evtchn_close_t close = { .port = params.xi_port }; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) panic("EVTCHNOP_close failed"); return (error); @@ -980,6 +985,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; @@ -995,11 +1003,12 @@ 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 }; + evtchn_close_t close = { .port = params.xi_port }; if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) panic("EVTCHNOP_close failed"); return (error); @@ -1020,6 +1029,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; @@ -1033,7 +1046,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); @@ -1043,7 +1057,7 @@ #endif if (error != 0) { - evtchn_close_t close = { .port = bind_virq.port }; + evtchn_close_t close = { .port = params.xi_port }; xen_intr_unbind(*port_handlep); if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) @@ -1068,7 +1082,6 @@ * responsible for closing it automatically on unbind. */ isrc->xi_close = 1; - isrc->xi_virq = virq; return (0); } @@ -1080,6 +1093,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]; @@ -1095,12 +1111,13 @@ 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 }; + evtchn_close_t close = { .port = params.xi_port }; xen_intr_unbind(*port_handlep); if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close))