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 @@ -1642,3 +1642,92 @@ } SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, NULL); + +/* + * Sysctls used by systat and others: hw.intrnames and hw.intrcnt. + * The data for this machine independent. + */ +int +intr_event_sysctl_intrnames(SYSCTL_HANDLER_ARGS) +{ + struct intr_event *ie; + u_int len; + const char straystr[] = "stray "; + int error; + + sx_slock(&event_lock); + TAILQ_FOREACH(ie, &event_list, ie_list) { + len = strnlen(ie->ie_fullname, sizeof(ie->ie_fullname)) + 1; + error = SYSCTL_OUT(req, ie->ie_fullname, len); + if (error != 0) + goto out; + + error = SYSCTL_OUT(req, straystr, sizeof(straystr) - 1); + if (error != 0) + goto out; + error = SYSCTL_OUT(req, ie->ie_fullname, len); + if (error != 0) + goto out; + } +out: + sx_sunlock(&event_lock); + return (error); +} + +int +intr_event_sysctl_intrcnt(SYSCTL_HANDLER_ARGS) +{ + struct intr_event *ie; + int error = 0; + int sz = sizeof(ie->ie_intrcnt); + u_long val; + void *arg = &val; +#ifdef SCTL_MASK32 + uint32_t val32; + + if (req->flags & SCTL_MASK32) { + sz = sizeof(val32); + arg = &val32; + } +#endif + + sx_slock(&event_lock); + TAILQ_FOREACH(ie, &event_list, ie_list) { +#ifdef SCTL_MASK32 + val32 = +#endif + val = atomic_load_long(&ie->ie_intrcnt); + if (val == 0) + continue; + error = SYSCTL_OUT(req, arg, sz); + if (error != 0) + goto out; + +#ifdef SCTL_MASK32 + val32 = +#endif + val = atomic_load_long(&ie->ie_stray); + error = SYSCTL_OUT(req, arg, sz); + if (error != 0) + goto out; + } +out: + sx_sunlock(&event_lock); + return (error); +} + +#ifdef DDB +/* + * DDB command to dump the interrupt statistics. + */ +DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE) +{ + struct intr_event *ie; + + for (ie = TAILQ_FIRST(&event_list); ie && !db_pager_quit; + ie = TAILQ_NEXT(ie, ie_list)) + if (ie->ie_intrcnt != 0) + db_printf("%s\t%lu\nstray %s\t%lu\n", ie->ie_fullname, + ie->ie_intrcnt, ie->ie_fullname, ie->ie_stray); +} +#endif 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 @@ -269,10 +269,7 @@ * XXX - it does not work well with removable controllers and * interrupt sources !!! */ - index = atomic_fetchadd_int(&intrcnt_index, 2); - if (index + 2 > intrcnt_count) - panic("overflowed interrupt name/counter table (index=%u)", - index); + index = intrcnt_count - 2; isrc->isrc_index = index; isrc->isrc_count = &intrcnt[index]; isrc_update_name(isrc, NULL); @@ -1560,7 +1557,7 @@ if (isrc == NULL) continue; - num = isrc->isrc_count != NULL ? isrc->isrc_count[0] : 0; + num = isrc->isrc_event != NULL ? isrc->isrc_event->ie_intrcnt : 0; db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i, isrc->isrc_name, isrc->isrc_cpu.__bits[0], isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num); @@ -1751,8 +1748,14 @@ static int sysctl_intrnames(SYSCTL_HANDLER_ARGS) { - return (sysctl_handle_opaque(oidp, intrnames, - intrcnt_index * INTRNAME_LEN, req)); + int error; + + error = sysctl_handle_opaque(oidp, intrnames, + intrcnt_index * INTRNAME_LEN, req); + if (error != 0) + return (error); + + return (intr_event_sysctl_intrnames(oidp, arg1, arg2, req)); } SYSCTL_PROC(_hw, OID_AUTO, intrnames, @@ -1763,10 +1766,10 @@ static int sysctl_intrcnt(SYSCTL_HANDLER_ARGS) { + int error; #ifdef SCTL_MASK32 uint32_t *intrcnt32; unsigned i; - int error; if (req->flags & SCTL_MASK32) { if (!req->oldptr) @@ -1781,11 +1784,13 @@ error = sysctl_handle_opaque(oidp, intrcnt32, intrcnt_index * sizeof(uint32_t), req); free(intrcnt32, M_TEMP); - return (error); - } + } else #endif - return (sysctl_handle_opaque(oidp, intrcnt, - intrcnt_index * sizeof(u_long), req)); + error = sysctl_handle_opaque(oidp, intrcnt, + intrcnt_index * sizeof(u_long), req); + + return (error == 0 ? intr_event_sysctl_intrcnt(oidp, arg1, arg2, req) : + error); } SYSCTL_PROC(_hw, OID_AUTO, intrcnt, @@ -1795,9 +1800,9 @@ #ifdef DDB /* - * DDB command to dump the interrupt statistics. + * DDB command to dump the IPI interrupt statistics. */ -DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE) +DB_SHOW_COMMAND_FLAGS(ipicnt, db_show_ipicnt, DB_CMD_MEMSAFE) { u_int i; diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c --- a/sys/powerpc/powerpc/intr_machdep.c +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -270,7 +270,7 @@ if (iscan == NULL && i->vector != -1) { powerpc_intrs[i->vector] = i; - i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1); + i->cntindex = nintrcnt - 1; i->cntp = &intrcnt[i->cntindex]; sprintf(intrname, "irq%u:", i->irq); intrcnt_setname(intrname, i->cntindex); @@ -699,8 +699,14 @@ static int sysctl_intrnames(SYSCTL_HANDLER_ARGS) { - return (sysctl_handle_opaque(oidp, intrnames, - intrcnt_index * INTRNAME_LEN, req)); + int error; + + error = sysctl_handle_opaque(oidp, intrnames, + intrcnt_index * INTRNAME_LEN, req); + if (error != 0) + return (error); + + return (intr_event_sysctl_intrnames(oidp, arg1, arg2, req)); } SYSCTL_PROC(_hw, OID_AUTO, intrnames, @@ -711,10 +717,10 @@ static int sysctl_intrcnt(SYSCTL_HANDLER_ARGS) { + int error; #ifdef SCTL_MASK32 uint32_t *intrcnt32; unsigned i; - int error; if (req->flags & SCTL_MASK32) { if (!req->oldptr) @@ -729,11 +735,13 @@ error = sysctl_handle_opaque(oidp, intrcnt32, intrcnt_index * sizeof(uint32_t), req); free(intrcnt32, M_TEMP); - return (error); - } + } else #endif - return (sysctl_handle_opaque(oidp, intrcnt, - intrcnt_index * sizeof(u_long), req)); + error = sysctl_handle_opaque(oidp, intrcnt, + intrcnt_index * sizeof(u_long), req); + + return (error == 0 ? intr_event_sysctl_intrcnt(oidp, arg1, arg2, req) : + error); } SYSCTL_PROC(_hw, OID_AUTO, intrcnt, @@ -743,9 +751,9 @@ #ifdef DDB /* - * DDB command to dump the interrupt statistics. + * DDB command to dump the IPI interrupt statistics. */ -DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE) +DB_SHOW_COMMAND_FLAGS(ipicnt, db_show_ipicnt, DB_CMD_MEMSAFE) { u_int i; diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h --- a/sys/sys/interrupt.h +++ b/sys/sys/interrupt.h @@ -34,6 +34,7 @@ #include #include #include +#include struct intr_event; struct intr_thread; @@ -194,4 +195,8 @@ void swi_sched(void *cookie, int flags); int swi_remove(void *cookie); +/* For handling the core interrupt counters and names */ +extern int intr_event_sysctl_intrnames(SYSCTL_HANDLER_ARGS); +extern int intr_event_sysctl_intrcnt(SYSCTL_HANDLER_ARGS); + #endif diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c --- a/sys/x86/x86/intr_machdep.c +++ b/sys/x86/x86/intr_machdep.c @@ -447,8 +447,7 @@ KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__)); mtx_lock_spin(&intrcnt_lock); MPASS(intrcnt_index + 2 <= nintrcnt); - is->is_index = intrcnt_index; - intrcnt_index += 2; + is->is_index = nintrcnt - 2; snprintf(straystr, sizeof(straystr), "stray irq%d", is->is_pic->pic_vector(is)); intrcnt_updatename(is); @@ -738,7 +737,7 @@ isrc->is_index, isrc->is_cpu, isrc->is_domain, - *isrc->is_count); + isrc->is_event->ie_intrcnt); } sx_sunlock(&intrsrc_lock); @@ -763,7 +762,7 @@ i1 = *(const struct intsrc * const *)one; i2 = *(const struct intsrc * const *)two; if (i1 != NULL && i2 != NULL) - return (*i1->is_count - *i2->is_count); + return (i1->is_event->ie_intrcnt - i2->is_event->ie_intrcnt); if (i1 != NULL) return (1); if (i2 != NULL) @@ -850,8 +849,14 @@ static int sysctl_intrnames(SYSCTL_HANDLER_ARGS) { - return (sysctl_handle_opaque(oidp, intrnames, - intrcnt_index * INTRNAME_LEN, req)); + int error; + + error = sysctl_handle_opaque(oidp, intrnames, + intrcnt_index * INTRNAME_LEN, req); + if (error != 0) + return (error); + + return (intr_event_sysctl_intrnames(oidp, arg1, arg2, req)); } SYSCTL_PROC(_hw, OID_AUTO, intrnames, @@ -862,10 +867,10 @@ static int sysctl_intrcnt(SYSCTL_HANDLER_ARGS) { + int error; #ifdef SCTL_MASK32 uint32_t *intrcnt32; unsigned i; - int error; if (req->flags & SCTL_MASK32) { if (!req->oldptr) @@ -880,11 +885,13 @@ error = sysctl_handle_opaque(oidp, intrcnt32, intrcnt_index * sizeof(uint32_t), req); free(intrcnt32, M_TEMP); - return (error); - } + } else #endif - return (sysctl_handle_opaque(oidp, intrcnt, - intrcnt_index * sizeof(u_long), req)); + error = sysctl_handle_opaque(oidp, intrcnt, + intrcnt_index * sizeof(u_long), req); + + return (error == 0 ? intr_event_sysctl_intrcnt(oidp, arg1, arg2, req) : + error); } SYSCTL_PROC(_hw, OID_AUTO, intrcnt, @@ -894,9 +901,9 @@ #ifdef DDB /* - * DDB command to dump the interrupt statistics. + * DDB command to dump the IPI interrupt statistics. */ -DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE) +DB_SHOW_COMMAND_FLAGS(ipicnt, db_show_ipicnt, DB_CMD_MEMSAFE) { u_int i;