diff --git a/sys/dev/acpica/acpi_apei.c b/sys/dev/acpica/acpi_apei.c --- a/sys/dev/acpica/acpi_apei.c +++ b/sys/dev/acpica/acpi_apei.c @@ -732,7 +732,8 @@ TAILQ_INSERT_TAIL(&sc->nges.ges, ge, nlink); if (sc->nges.swi_ih == NULL) { swi_add(&clk_intr_event, "apei", apei_nmi_swi, - &sc->nges, SWI_CLOCK, INTR_MPSAFE, + &sc->nges, SWI_CLOCK, + INTR_MPSAFE | INTR_MULTIPROC, &sc->nges.swi_ih); apei_nmi_nges = &sc->nges; apei_nmi = apei_nmi_handler; diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -286,8 +286,8 @@ struct intr_event *ie; va_list ap; - /* The only valid flag during creation is IE_SOFT. */ - if ((flags & ~IE_SOFT) != 0) + /* The flags valid during creation are IE_SOFT and IE_MULTIPROC. */ + if ((flags & ~(IE_SOFT | IE_MULTIPROC)) != 0) return (EINVAL); ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO); ie->ie_source = source; @@ -608,6 +608,19 @@ if (ie == NULL || name == NULL || (handler == NULL && filter == NULL)) return (EINVAL); + if ((flags & INTR_MULTIPROC) && !(ie->ie_flags & IE_MULTIPROC)) { +#if defined(INVARIANTS) || defined(DEBUG) + printf("%s: Requested multi-processor interupt, but got " + "uniprocessor interrupt\n", name); +#endif + return (ENODEV); + } +#if defined(INVARIANTS) || defined(DEBUG) + if (!(flags & INTR_MULTIPROC) && (ie->ie_flags & IE_MULTIPROC)) + printf("%s: Requested uniprocessor interupt, but got " + "multi-processor interrupt\n", name); +#endif + /* Allocate and populate an interrupt handler structure. */ ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO); ih->ih_filter = filter; @@ -1059,18 +1072,22 @@ void *arg, int pri, enum intr_type flags, void **cookiep) { struct intr_event *ie; + int ieflags = IE_SOFT; int error = 0; if (flags & INTR_ENTROPY) return (EINVAL); + if (flags & INTR_MULTIPROC) + ieflags |= IE_MULTIPROC; + ie = (eventp != NULL) ? *eventp : NULL; if (ie != NULL) { if (!(ie->ie_flags & IE_SOFT)) return (EINVAL); } else { - error = intr_event_create(&ie, NULL, IE_SOFT, 0, + error = intr_event_create(&ie, NULL, ieflags, 0, NULL, NULL, NULL, swi_assign_cpu, "swi%d:", pri); if (error) return (error); @@ -1625,8 +1642,11 @@ start_softintr(void *dummy) { + KASSERT(clk_intr_event == NULL, ("clk_intr_event non-NULL at %s()", + __func__)); + if (swi_add(&clk_intr_event, "clk", NULL, NULL, SWI_CLOCK, - INTR_MPSAFE, NULL)) + INTR_MPSAFE | INTR_MULTIPROC, NULL)) panic("died while creating clk swi ithread"); } SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -626,12 +626,15 @@ isrc_event_create(struct intr_irqsrc *isrc) { struct intr_event *ie; + u_int flags = 0; int error; if (isrc->isrc_event != NULL) return (0); - error = intr_event_create(&ie, isrc, 0, isrc->isrc_irq, + if (isrc->isrc_flags & (INTR_ISRCF_IPI | INTR_ISRCF_PPI)) + flags |= IE_MULTIPROC; + error = intr_event_create(&ie, isrc, flags, isrc->isrc_irq, intr_isrc_pre_ithread, intr_isrc_post_ithread, intr_isrc_post_filter, intr_isrc_assign_cpu, "%s:", isrc->isrc_name); if (error) diff --git a/sys/sys/bus.h b/sys/sys/bus.h --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -281,7 +281,8 @@ INTR_MD1 = 4096, /* flag reserved for MD use */ INTR_MD2 = 8192, /* flag reserved for MD use */ INTR_MD3 = 16384, /* flag reserved for MD use */ - INTR_MD4 = 32768 /* flag reserved for MD use */ + INTR_MD4 = 32768, /* flag reserved for MD use */ + INTR_MULTIPROC = 0x10000, /* interrupt occurs on multiple procs */ }; enum intr_trigger { diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h --- a/sys/sys/interrupt.h +++ b/sys/sys/interrupt.h @@ -132,6 +132,7 @@ /* Interrupt event flags kept in ie_flags. */ #define IE_SOFT 0x000001 /* Software interrupt. */ #define IE_ADDING_THREAD 0x000004 /* Currently building an ithread. */ +#define IE_MULTIPROC 0x000008 /* Interrupt occurs on multiple procs */ /* Flags to pass to swi_sched. */ #define SWI_FROMNMI 0x1