Index: sys/dev/xen/bus/xen_intr.c =================================================================== --- sys/dev/xen/bus/xen_intr.c +++ sys/dev/xen/bus/xen_intr.c @@ -319,7 +319,6 @@ xen_intr_port_to_isrc[isrc->xi_port] = NULL; } - isrc->xi_cpu = 0; isrc->xi_type = EVTCHN_TYPE_UNBOUND; isrc->xi_port = INVALID_EVTCHN; mtx_unlock(&xen_intr_isrc_lock); @@ -348,9 +347,10 @@ * * \returns 0 on success, otherwise an errno. */ -#define BIND_PARAMS(type, ...) \ +#define BIND_PARAMS(type, cpu, ...) \ { \ .xi_type = (type), \ + .xi_cpu = (cpu), \ .xi_cookie = NULL, \ __VA_ARGS__ \ } @@ -361,6 +361,9 @@ { struct xenisrc *isrc; int error; +#ifdef SMP + u_int cpu; +#endif *isrcp = NULL; if (port_handlep == NULL) { @@ -372,6 +375,10 @@ if (isrc == NULL) return (ENOSPC); refcount_init(&isrc->xi_refcount, 1); +#ifdef SMP + cpu = isrc->xi_cpu; +#endif + isrc->xi_cpu = 0; /* initialize to the likely correct value */ mtx_lock(&xen_intr_isrc_lock); xen_intr_port_to_isrc[isrc->xi_port] = isrc; mtx_unlock(&xen_intr_isrc_lock); @@ -382,13 +389,29 @@ /* ->xi_cookie is cleared in BIND_PARAMS() */ #ifdef SMP - if (isrc->xi_type == EVTCHN_TYPE_PORT) { + if (cpu > mp_maxid) { /* * By default all interrupts are assigned to vCPU#0 * unless specified otherwise, so shuffle them to balance * the interrupt load. */ - xen_intr_assign_cpu(isrc, intr_next_cpu(0)); + cpu = intr_next_cpu(0); + } + + error = xen_arch_intr_event_bind(isrc, cpu); + if (error != 0) { /* *very* unlikely */ + xen_intr_release_isrc(isrc); + return (error); + } + + if (isrc->xi_cpu != cpu) { + /* + * Too early in the boot process for the generic interrupt + * code to perform the binding. Update our event channel + * masks manually so events can't fire on the wrong cpu + * during AP startup. + */ + xen_intr_assign_cpu(isrc, cpu); } #endif @@ -848,7 +871,7 @@ enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; - struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT, + struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT, ~0U, .xi_port = local_port, /* * The Event Channel API didn't open this port, so it is not @@ -867,7 +890,7 @@ enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; - struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT); + struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT, ~0U); struct evtchn_alloc_unbound alloc_unbound; int error; @@ -903,7 +926,7 @@ void *arg, enum intr_type flags, xen_intr_handle_t *port_handlep) { struct xenisrc *isrc; - struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT); + struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_PORT, ~0U); struct evtchn_bind_interdomain bind_interdomain; int error; @@ -944,7 +967,7 @@ { u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); struct xenisrc *isrc; - struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_VIRQ, + struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_VIRQ, cpu, .xi_virq = virq, ); struct evtchn_bind_virq bind_virq = { .virq = virq, .vcpu = vcpu_id }; @@ -964,11 +987,6 @@ error = xen_intr_bind_isrc(&isrc, ¶ms, device_get_nameunit(dev), filter, handler, arg, flags, port_handlep); -#ifdef SMP - if (error == 0) - error = xen_arch_intr_event_bind(isrc, cpu); -#endif - if (error != 0) { evtchn_close_t close = { .port = params.xi_port }; @@ -978,18 +996,6 @@ return (error); } -#ifdef SMP - if (isrc->xi_cpu != cpu) { - /* - * Too early in the boot process for the generic interrupt - * code to perform the binding. Update our event channel - * masks manually so events can't fire on the wrong cpu - * during AP startup. - */ - xen_intr_assign_cpu(isrc, cpu); - } -#endif - /* * The Event Channel API opened this port, so it is * responsible for closing it automatically on unbind. @@ -1006,7 +1012,7 @@ #ifdef SMP u_int vcpu_id = XEN_CPUID_TO_VCPUID(cpu); struct xenisrc *isrc; - struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_IPI); + struct xenisrc params = BIND_PARAMS(EVTCHN_TYPE_IPI, cpu); struct evtchn_bind_ipi bind_ipi = { .vcpu = vcpu_id }; /* Same size as the one used by intr_handler->ih_name. */ char name[MAXCOMLEN + 1]; @@ -1036,16 +1042,6 @@ return (error); } - if (isrc->xi_cpu != cpu) { - /* - * Too early in the boot process for the generic interrupt - * code to perform the binding. Update our event channel - * masks manually so events can't fire on the wrong cpu - * during AP startup. - */ - xen_intr_assign_cpu(isrc, cpu); - } - /* * The Event Channel API opened this port, so it is * responsible for closing it automatically on unbind.