Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153073409
D36610.id114524.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
29 KB
Referenced Files
None
Subscribers
None
D36610.id114524.diff
View Options
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -834,24 +834,6 @@
static void
watchdog_fire(void)
{
- int nintr;
- uint64_t inttotal;
- u_long *curintr;
- char *curname;
-
- curintr = intrcnt;
- curname = intrnames;
- inttotal = 0;
- nintr = sintrcnt / sizeof(u_long);
-
- printf("interrupt total\n");
- while (--nintr >= 0) {
- if (*curintr)
- printf("%-12s %20lu\n", curname, *curintr);
- curname += strlen(curname) + 1;
- inttotal += *curintr++;
- }
- printf("Total %20ju\n", (uintmax_t)inttotal);
#if defined(KDB) && !defined(KDB_UNATTENDED)
kdb_backtrace();
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
@@ -3,6 +3,7 @@
*
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
* All rights reserved.
+ * Copyright © 2022 Elliott Mitchell
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -54,6 +55,7 @@
#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/smp.h>
+#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/unistd.h>
@@ -109,8 +111,8 @@
#endif
static TAILQ_HEAD(, intr_event) event_list =
TAILQ_HEAD_INITIALIZER(event_list);
-static struct mtx event_lock;
-MTX_SYSINIT(intr_event_list, &event_lock, "intr event list", MTX_DEF);
+static struct sx event_lock;
+SX_SYSINIT(intr_event_list, &event_lock, "intr event list");
static void intr_event_update(struct intr_event *ie);
static int intr_event_schedule_thread(struct intr_event *ie, struct trapframe *frame);
@@ -297,6 +299,8 @@
ie->ie_assign_cpu = assign_cpu;
ie->ie_flags = flags;
ie->ie_cpu = NOCPU;
+ ie->ie_stray = 0;
+ ie->ie_intrcnt = 0;
CK_SLIST_INIT(&ie->ie_handlers);
mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
@@ -304,9 +308,9 @@
vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap);
va_end(ap);
strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
- mtx_lock(&event_lock);
+ sx_xlock(&event_lock);
TAILQ_INSERT_TAIL(&event_list, ie, ie_list);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
if (event != NULL)
*event = ie;
CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
@@ -515,11 +519,11 @@
if (ie == NULL)
return (EINVAL);
- mtx_lock(&event_lock);
+ sx_xlock(&event_lock);
mtx_lock(&ie->ie_lock);
if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
mtx_unlock(&ie->ie_lock);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
return (EBUSY);
}
TAILQ_REMOVE(&event_list, ie, ie_list);
@@ -530,7 +534,7 @@
}
#endif
mtx_unlock(&ie->ie_lock);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
mtx_destroy(&ie->ie_lock);
free(ie, M_ITHREAD);
return (0);
@@ -1330,9 +1334,9 @@
* handlers as their main argument.
* Return value:
* o 0: everything ok.
- * o EINVAL: stray interrupt.
+ * o non-0: stray interrupt, current count.
*/
-int
+u_long
intr_event_handle(struct intr_event *ie, struct trapframe *frame)
{
struct intr_handler *ih;
@@ -1348,9 +1352,16 @@
intr_prof_stack_use(td, frame);
#endif
- /* An interrupt with no event or handlers is a stray interrupt. */
- if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers))
- return (EINVAL);
+ /* An interrupt with no event is a stray interrupt. */
+ if (ie == NULL)
+ return (~0UL);
+
+ /* Increment the interrupt counter. */
+ atomic_add_long(&ie->ie_intrcnt, 1);
+
+ /* An interrupt with no handlers is a stray interrupt. */
+ if (CK_SLIST_EMPTY(&ie->ie_handlers))
+ return (atomic_fetchadd_long(&ie->ie_stray, 1) + 1);
/*
* Execute fast interrupt handlers directly.
@@ -1452,7 +1463,7 @@
#ifdef notyet
/* The interrupt is not aknowledged by any filter and has no ithread. */
if (!thread && !filter)
- return (EINVAL);
+ return (atomic_fetchadd_long(&ie->ie_stray, 1) + 1);
#endif
return (0);
}
@@ -1612,52 +1623,74 @@
/*
* Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
- * The data for this machine dependent, and the declarations are in machine
- * dependent code. The layout of intrnames and intrcnt however is machine
- * independent.
- *
- * We do not know the length of intrcnt and intrnames at compile time, so
- * calculate things at run time.
+ * The data for this machine independent.
*/
-static int
-sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+int
+intr_event_sysctl_intrnames(SYSCTL_HANDLER_ARGS)
{
- return (sysctl_handle_opaque(oidp, intrnames, sintrnames, req));
-}
+ struct intr_event *ie;
+ u_int len;
+ const char straystr[] = "stray ";
+ int error;
-SYSCTL_PROC(_hw, OID_AUTO, intrnames,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
- sysctl_intrnames, "",
- "Interrupt Names");
+ 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);
+}
-static int
-sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+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 *intrcnt32;
- unsigned i;
- int error;
+ uint32_t val32;
if (req->flags & SCTL_MASK32) {
- if (!req->oldptr)
- return (sysctl_handle_opaque(oidp, NULL, sintrcnt / 2, req));
- intrcnt32 = malloc(sintrcnt / 2, M_TEMP, M_NOWAIT);
- if (intrcnt32 == NULL)
- return (ENOMEM);
- for (i = 0; i < sintrcnt / sizeof (u_long); i++)
- intrcnt32[i] = intrcnt[i];
- error = sysctl_handle_opaque(oidp, intrcnt32, sintrcnt / 2, req);
- free(intrcnt32, M_TEMP);
- return (error);
+ sz = sizeof(val32);
+ arg = &val32;
}
#endif
- return (sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req));
-}
-SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
- sysctl_intrcnt, "",
- "Interrupt Counts");
+ sx_slock(&event_lock);
+ TAILQ_FOREACH(ie, &event_list, ie_list) {
+#ifdef SCTL_MASK32
+ val32 =
+#endif
+ val = ie->ie_intrcnt;
+ error = SYSCTL_OUT(req, arg, sz);
+ if (error != 0)
+ goto out;
+
+#ifdef SCTL_MASK32
+ val32 =
+#endif
+ val = ie->ie_stray;
+ error = SYSCTL_OUT(req, arg, sz);
+ if (error != 0)
+ goto out;
+ }
+out:
+ sx_sunlock(&event_lock);
+ return (error);
+}
#ifdef DDB
/*
@@ -1665,19 +1698,11 @@
*/
DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE)
{
- u_long *i;
- char *cp;
- u_int j;
-
- cp = intrnames;
- j = 0;
- for (i = intrcnt; j < (sintrcnt / sizeof(u_long)) && !db_pager_quit;
- i++, j++) {
- if (*cp == '\0')
- break;
- if (*i != 0)
- db_printf("%s\t%lu\n", cp, *i);
- cp += strlen(cp) + 1;
- }
+ struct intr_event *ie;
+
+ for (ie = TAILQ_FIRST(&event_list); ie && !db_pager_quit;
+ ie = TAILQ_NEXT(ie, ie_list))
+ 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
@@ -152,7 +152,7 @@
char *intrnames;
size_t sintrcnt;
size_t sintrnames;
-static u_int intrcnt_index;
+u_int nintrcnt;
static struct intr_irqsrc *intr_map_get_isrc(u_int res_id);
static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc);
@@ -166,7 +166,6 @@
static void
intr_irq_init(void *dummy __unused)
{
- u_int intrcnt_count;
SLIST_INIT(&pic_list);
mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
@@ -177,17 +176,15 @@
* - 2 counters for each I/O interrupt.
* - MAXCPU counters for each IPI counters for SMP.
*/
- intrcnt_count = intr_nirq * 2;
+ nintrcnt = 1;
#ifdef SMP
- intrcnt_count += INTR_IPI_COUNT * MAXCPU;
+ nintrcnt += INTR_IPI_COUNT * MAXCPU;
#endif
- intrcnt = mallocarray(intrcnt_count, sizeof(u_long), M_INTRNG,
+ intrcnt = mallocarray(nintrcnt, sizeof(u_long), M_INTRNG,
M_WAITOK | M_ZERO);
- intrnames = mallocarray(intrcnt_count, INTRNAME_LEN, M_INTRNG,
+ intrnames = mallocarray(nintrcnt, INTRNAME_LEN, M_INTRNG,
M_WAITOK | M_ZERO);
- sintrcnt = intrcnt_count * sizeof(u_long);
- sintrnames = intrcnt_count * INTRNAME_LEN;
irq_sources = mallocarray(intr_nirq, sizeof(struct intr_irqsrc*),
M_INTRNG, M_WAITOK | M_ZERO);
}
@@ -201,41 +198,7 @@
INTRNAME_LEN - 1, name);
}
-/*
- * Update name for interrupt source with interrupt event.
- */
-static void
-intrcnt_updatename(struct intr_irqsrc *isrc)
-{
-
- /* QQQ: What about stray counter name? */
- mtx_assert(&isrc_table_lock, MA_OWNED);
- intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index);
-}
-
-/*
- * Virtualization for interrupt source interrupt counter increment.
- */
-static inline void
-isrc_increment_count(struct intr_irqsrc *isrc)
-{
-
- if (isrc->isrc_flags & INTR_ISRCF_PPI)
- atomic_add_long(&isrc->isrc_count[0], 1);
- else
- isrc->isrc_count[0]++;
-}
-
-/*
- * Virtualization for interrupt source interrupt stray counter increment.
- */
-static inline void
-isrc_increment_straycount(struct intr_irqsrc *isrc)
-{
-
- isrc->isrc_count[1]++;
-}
-
+#ifdef INTR_SOLO
/*
* Virtualization for interrupt source interrupt name update.
*/
@@ -246,47 +209,15 @@
mtx_assert(&isrc_table_lock, MA_OWNED);
- if (name != NULL) {
+ if (name != NULL)
snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name);
- intrcnt_setname(str, isrc->isrc_index);
- snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name,
- name);
- intrcnt_setname(str, isrc->isrc_index + 1);
- } else {
+ else
snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name);
- intrcnt_setname(str, isrc->isrc_index);
- snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name);
- intrcnt_setname(str, isrc->isrc_index + 1);
- }
-}
-
-/*
- * Virtualization for interrupt source interrupt counters setup.
- */
-static void
-isrc_setup_counters(struct intr_irqsrc *isrc)
-{
- u_int index;
- /*
- * XXX - it does not work well with removable controllers and
- * interrupt sources !!!
- */
- index = atomic_fetchadd_int(&intrcnt_index, 2);
- isrc->isrc_index = index;
- isrc->isrc_count = &intrcnt[index];
- isrc_update_name(isrc, NULL);
-}
-
-/*
- * Virtualization for interrupt source interrupt counters release.
- */
-static void
-isrc_release_counters(struct intr_irqsrc *isrc)
-{
-
- panic("%s: not implemented", __func__);
+ strlcpy(isrc->isrc_event->ie_fullname, str,
+ sizeof(isrc->isrc_event->ie_fullname));
}
+#endif
#ifdef SMP
/*
@@ -298,7 +229,12 @@
u_int index, i;
char str[INTRNAME_LEN];
- index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
+ index = (u_int)(atomic_fetchadd_ptr(&sintrcnt,
+ sizeof(u_long) * MAXCPU) / sizeof(u_long));
+ if (index >= nintrcnt)
+ panic("overflowed IPI interrupt name table size (index=%u)",
+ index);
+ atomic_add_ptr(&sintrnames, INTRNAME_LEN * MAXCPU);
for (i = 0; i < MAXCPU; i++) {
snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name);
intrcnt_setname(str, index + i);
@@ -368,8 +304,6 @@
KASSERT(isrc != NULL, ("%s: no source", __func__));
- isrc_increment_count(isrc);
-
#ifdef INTR_SOLO
if (isrc->isrc_filter != NULL) {
int error;
@@ -384,7 +318,6 @@
return (0);
}
- isrc_increment_straycount(isrc);
return (EINVAL);
}
@@ -484,13 +417,7 @@
mtx_unlock(&isrc_table_lock);
return (error);
}
- /*
- * Setup interrupt counters, but not for IPI sources. Those are setup
- * later and only for used ones (up to INTR_IPI_COUNT) to not exhaust
- * our counter pool.
- */
- if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
- isrc_setup_counters(isrc);
+
mtx_unlock(&isrc_table_lock);
return (0);
}
@@ -504,8 +431,6 @@
int error;
mtx_lock(&isrc_table_lock);
- if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
- isrc_release_counters(isrc);
error = isrc_free_irq(isrc);
mtx_unlock(&isrc_table_lock);
return (error);
@@ -721,15 +646,8 @@
return (error);
}
- error = intr_event_add_handler(isrc->isrc_event, name, filter, handler,
- arg, intr_priority(flags), flags, cookiep);
- if (error == 0) {
- mtx_lock(&isrc_table_lock);
- intrcnt_updatename(isrc);
- mtx_unlock(&isrc_table_lock);
- }
-
- return (error);
+ return (intr_event_add_handler(isrc->isrc_event, name, filter, handler,
+ arg, intr_priority(flags), flags, cookiep));
}
/*
@@ -1159,7 +1077,6 @@
if (isrc->isrc_handlers == 0)
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
- intrcnt_updatename(isrc);
mtx_unlock(&isrc_table_lock);
}
return (error);
@@ -1169,7 +1086,6 @@
intr_describe_irq(device_t dev, struct resource *res, void *cookie,
const char *descr)
{
- int error;
struct intr_irqsrc *isrc;
u_int res_id;
@@ -1191,13 +1107,7 @@
return (0);
}
#endif
- error = intr_event_describe_handler(isrc->isrc_event, cookie, descr);
- if (error == 0) {
- mtx_lock(&isrc_table_lock);
- intrcnt_updatename(isrc);
- mtx_unlock(&isrc_table_lock);
- }
- return (error);
+ return (intr_event_describe_handler(isrc->isrc_event, cookie, descr));
}
#ifdef SMP
@@ -1569,7 +1479,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);
@@ -1753,3 +1663,53 @@
M_INTRNG, M_WAITOK | M_ZERO);
}
SYSINIT(intr_map_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_map_init, NULL);
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");
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
@@ -93,13 +93,11 @@
struct powerpc_intr {
struct intr_event *event;
- long *cntp;
void *priv; /* PIC-private data */
device_t pic;
u_int irq;
u_int intline;
u_int vector;
- u_int cntindex;
int fwcode;
int ipi;
int pi_domain;
@@ -116,7 +114,6 @@
int base;
};
-static u_int intrcnt_index = 0;
static struct mtx intr_table_lock;
static struct powerpc_intr **powerpc_intrs;
static struct pic piclist[MAX_PICS];
@@ -131,9 +128,9 @@
u_long *intrcnt;
char *intrnames;
-size_t sintrcnt = sizeof(intrcnt);
-size_t sintrnames = sizeof(intrnames);
-int nintrcnt;
+size_t sintrcnt;
+size_t sintrnames;
+u_int nintrcnt;
/*
* Just to start
@@ -172,7 +169,7 @@
powerpc_intrs = mallocarray(num_io_irqs, sizeof(*powerpc_intrs),
M_INTR, M_WAITOK | M_ZERO);
- nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
+ nintrcnt = 1 + mp_ncpus * 2;
#ifdef COUNT_IPIS
if (mp_ncpus > 1)
nintrcnt += 8 * mp_ncpus;
@@ -181,11 +178,6 @@
M_ZERO);
intrnames = mallocarray(nintrcnt, MAXCOMLEN + 1, M_INTR, M_WAITOK |
M_ZERO);
- sintrcnt = nintrcnt * sizeof(u_long);
- sintrnames = nintrcnt * (MAXCOMLEN + 1);
-
- intrcnt_setname("???", 0);
- intrcnt_index = 1;
}
/*
* This needs to happen before SI_SUB_CPU
@@ -211,11 +203,12 @@
void
intrcnt_add(const char *name, u_long **countp)
{
- int idx;
+ u_int idx;
- idx = atomic_fetchadd_int(&intrcnt_index, 1);
- KASSERT(idx < nintrcnt, ("intrcnt_add: Interrupt counter index %d/%d"
- "reached nintrcnt : %d", intrcnt_index, idx, nintrcnt));
+ idx = atomic_fetchadd_int(&sintrcnt, sizeof(u_long)) / sizeof(u_long);
+ KASSERT(idx < nintrcnt, ("%s: Interrupt counter index %u reached "
+ "nintrcnt : %u, for \"%s\"", __func__, idx, nintrcnt, name));
+ atomic_add_int(&sintrnames, MAXCOMLEN + 1);
*countp = &intrcnt[idx];
intrcnt_setname(name, idx);
}
@@ -224,7 +217,6 @@
static struct powerpc_intr *
intr_create(u_int irq)
{
- char intrname[16];
struct powerpc_intr *i, *iscan;
int vector;
@@ -244,7 +236,6 @@
}
i->event = NULL;
- i->cntp = NULL;
i->priv = NULL;
i->trig = INTR_TRIGGER_CONFORM;
i->pol = INTR_POLARITY_CONFORM;
@@ -272,10 +263,8 @@
if (iscan == NULL && i->vector != -1) {
powerpc_intrs[i->vector] = i;
- i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
- i->cntp = &intrcnt[i->cntindex];
- sprintf(intrname, "irq%u:", i->irq);
- intrcnt_setname(intrname, i->cntindex);
+ snprintf(i->event->ie_fullname, sizeof(i->event->ie_fullname),
+ "irq%u:", i->irq);
nvectors++;
}
mtx_unlock(&intr_table_lock);
@@ -576,9 +565,6 @@
CPU_ZERO(&i->pi_cpuset);
CPU_COPY(&cpuset_domain[domain], &i->pi_cpuset);
}
- mtx_lock(&intr_table_lock);
- intrcnt_setname(i->event->ie_fullname, i->cntindex);
- mtx_unlock(&intr_table_lock);
if (!cold) {
error = powerpc_map_irq(i);
@@ -674,8 +660,6 @@
if (i == NULL)
goto stray;
- (*i->cntp)++;
-
ie = i->event;
KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
@@ -727,3 +711,53 @@
PIC_UNMASK(i->pic, i->intline, i->priv);
}
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");
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 <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/ck.h>
+#include <sys/sysctl.h>
struct intr_event;
struct intr_thread;
@@ -126,6 +127,8 @@
int ie_cpu; /* CPU this event is bound to. */
volatile int ie_phase; /* Switched to establish a barrier. */
volatile int ie_active[2]; /* Filters in ISR context. */
+ u_long ie_stray; /* Stray interrupt counter */
+ u_long ie_intrcnt; /* Interrupt counter */
};
/* Interrupt event flags kept in ie_flags. */
@@ -156,12 +159,6 @@
extern struct intr_event *clk_intr_event;
-/* Counts and names for statistics (defined in MD code). */
-extern u_long *intrcnt; /* counts for each device and stray */
-extern char *intrnames; /* string table containing device names */
-extern size_t sintrcnt; /* size of intrcnt table */
-extern size_t sintrnames; /* size of intrnames table */
-
#ifdef DDB
void db_dump_intr_event(struct intr_event *ie, int handlers);
#endif
@@ -182,7 +179,7 @@
int intr_event_describe_handler(struct intr_event *ie, void *cookie,
const char *descr);
int intr_event_destroy(struct intr_event *ie);
-int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
+u_long intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie);
int intr_event_suspend_handler(void *cookie);
int intr_event_resume_handler(void *cookie);
@@ -196,4 +193,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/sys/intr.h b/sys/sys/intr.h
--- a/sys/sys/intr.h
+++ b/sys/sys/intr.h
@@ -104,8 +104,6 @@
u_int isrc_flags;
char isrc_name[INTR_ISRC_NAMELEN];
cpuset_t isrc_cpu; /* on which CPUs is enabled */
- u_int isrc_index;
- u_long * isrc_count;
u_int isrc_handlers;
struct intr_event * isrc_event;
#ifdef INTR_SOLO
diff --git a/sys/x86/include/intr.h b/sys/x86/include/intr.h
--- a/sys/x86/include/intr.h
+++ b/sys/x86/include/intr.h
@@ -128,9 +128,6 @@
struct intsrc {
struct pic *is_pic;
struct intr_event *is_event;
- u_long *is_count;
- u_long *is_straycount;
- u_int is_index;
u_int is_handlers;
u_int is_domain;
u_int is_cpu;
diff --git a/sys/x86/isa/atpic.c b/sys/x86/isa/atpic.c
--- a/sys/x86/isa/atpic.c
+++ b/sys/x86/isa/atpic.c
@@ -131,8 +131,6 @@
inthand_t *at_intr, *at_intr_pti;
int at_irq; /* Relative to PIC base. */
enum intr_trigger at_trigger;
- u_long at_count;
- u_long at_straycount;
};
static void atpic_register_sources(struct pic *pic);
@@ -464,8 +462,6 @@
for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
if (i == ICU_SLAVEID)
continue;
- ai->at_intsrc.is_count = &ai->at_count;
- ai->at_intsrc.is_straycount = &ai->at_straycount;
setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
ai->at_irq, pti ? ai->at_intr_pti : ai->at_intr, SDT_ATPIC,
SEL_KPL, GSEL_ATPIC);
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
@@ -76,7 +76,6 @@
typedef void (*mask_fn)(void *);
-static int intrcnt_index;
static struct intsrc **interrupt_sources;
#ifdef SMP
static struct intsrc **interrupt_sorted;
@@ -97,9 +96,9 @@
u_long *intrcnt;
char *intrnames;
-size_t sintrcnt = sizeof(intrcnt);
-size_t sintrnames = sizeof(intrnames);
-int nintrcnt;
+size_t sintrcnt;
+size_t sintrnames;
+u_int nintrcnt;
static MALLOC_DEFINE(M_INTR, "intr", "Interrupt Sources");
@@ -108,8 +107,6 @@
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
-static void intrcnt_updatename(struct intsrc *is);
-static void intrcnt_register(struct intsrc *is);
/*
* SYSINIT levels for SI_SUB_INTR:
@@ -176,13 +173,12 @@
#endif
/*
- * - 1 ??? dummy counter.
* - 2 counters for each I/O interrupt.
* - 1 counter for each CPU for lapic timer.
* - 1 counter for each CPU for the Hyper-V vmbus driver.
* - 8 counters for each CPU for IPI counters for SMP.
*/
- nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
+ nintrcnt = 1 + mp_ncpus * 2;
#ifdef COUNT_IPIS
if (mp_ncpus > 1)
nintrcnt += 8 * mp_ncpus;
@@ -191,11 +187,6 @@
M_ZERO);
intrnames = mallocarray(nintrcnt, MAXCOMLEN + 1, M_INTR, M_WAITOK |
M_ZERO);
- sintrcnt = nintrcnt * sizeof(u_long);
- sintrnames = nintrcnt * (MAXCOMLEN + 1);
-
- intrcnt_setname("???", 0);
- intrcnt_index = 1;
/*
* NB: intrpic_lock is not held here to avoid LORs due to
@@ -239,7 +230,6 @@
intr_event_destroy(isrc->is_event);
return (EEXIST);
}
- intrcnt_register(isrc);
interrupt_sources[vector] = isrc;
isrc->is_handlers = 0;
sx_xunlock(&intrsrc_lock);
@@ -270,7 +260,6 @@
arg, intr_priority(flags), flags, cookiep);
if (error == 0) {
sx_xlock(&intrsrc_lock);
- intrcnt_updatename(isrc);
isrc->is_handlers++;
if (isrc->is_handlers == 1) {
isrc->is_domain = domain;
@@ -297,7 +286,6 @@
isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI);
isrc->is_pic->pic_disable_intr(isrc);
}
- intrcnt_updatename(isrc);
sx_xunlock(&intrsrc_lock);
}
return (error);
@@ -328,6 +316,7 @@
{
struct intr_event *ie;
int vector;
+ u_long strays;
/*
* We count software interrupts when we process them. The
@@ -335,7 +324,6 @@
* argument for counting hardware interrupts when they're
* processed too.
*/
- (*isrc->is_count)++;
VM_CNT_INC(v_intr);
ie = isrc->is_event;
@@ -352,12 +340,11 @@
* For stray interrupts, mask and EOI the source, bump the
* stray count, and log the condition.
*/
- if (intr_event_handle(ie, frame) != 0) {
+ if ((strays = intr_event_handle(ie, frame)) != 0) {
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- (*isrc->is_straycount)++;
- if (*isrc->is_straycount < INTR_STRAY_LOG_MAX)
+ if (strays < INTR_STRAY_LOG_MAX)
log(LOG_ERR, "stray irq%d\n", vector);
- else if (*isrc->is_straycount == INTR_STRAY_LOG_MAX)
+ else if (strays == INTR_STRAY_LOG_MAX)
log(LOG_CRIT,
"too many stray irq %d's: not logging anymore\n",
vector);
@@ -434,41 +421,16 @@
MAXCOMLEN, name);
}
-static void
-intrcnt_updatename(struct intsrc *is)
-{
-
- intrcnt_setname(is->is_event->ie_fullname, is->is_index);
-}
-
-static void
-intrcnt_register(struct intsrc *is)
-{
- char straystr[MAXCOMLEN + 1];
-
- 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;
- snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
- is->is_pic->pic_vector(is));
- intrcnt_updatename(is);
- is->is_count = &intrcnt[is->is_index];
- intrcnt_setname(straystr, is->is_index + 1);
- is->is_straycount = &intrcnt[is->is_index + 1];
- mtx_unlock_spin(&intrcnt_lock);
-}
-
void
intrcnt_add(const char *name, u_long **countp)
{
mtx_lock_spin(&intrcnt_lock);
- MPASS(intrcnt_index < nintrcnt);
- *countp = &intrcnt[intrcnt_index];
- intrcnt_setname(name, intrcnt_index);
- intrcnt_index++;
+ MPASS(sintrcnt < nintrcnt * sizeof(u_long));
+ *countp = &intrcnt[sintrcnt / sizeof(u_long)];
+ intrcnt_setname(name, sintrcnt / sizeof(u_long));
+ sintrcnt += sizeof(u_long);
+ sintrnames += MAXCOMLEN + 1;
mtx_unlock_spin(&intrcnt_lock);
}
@@ -525,16 +487,11 @@
intr_describe(u_int vector, void *ih, const char *descr)
{
struct intsrc *isrc;
- int error;
isrc = intr_lookup(vector);
if (isrc == NULL)
return (EINVAL);
- error = intr_event_describe_handler(isrc->is_event, ih, descr);
- if (error)
- return (error);
- intrcnt_updatename(isrc);
- return (0);
+ return (intr_event_describe_handler(isrc->is_event, ih, descr));
}
void
@@ -735,12 +692,11 @@
isrc = interrupt_sources[i];
if (isrc == NULL)
continue;
- sbuf_printf(&sbuf, "%s:%d @cpu%d(domain%d): %ld\n",
+ sbuf_printf(&sbuf, "%s @cpu%d(domain%d): %lu\n",
isrc->is_event->ie_fullname,
- isrc->is_index,
isrc->is_cpu,
isrc->is_domain,
- *isrc->is_count);
+ isrc->is_event->ie_intrcnt);
}
sx_sunlock(&intrsrc_lock);
@@ -751,7 +707,7 @@
SYSCTL_PROC(_hw, OID_AUTO, intrs,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
0, 0, sysctl_hw_intrs, "A",
- "interrupt:number @cpu: count");
+ "interrupt @cpu: count");
/*
* Compare two, possibly NULL, entries in the interrupt source array
@@ -765,7 +721,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)
@@ -845,3 +801,53 @@
return (PCPU_GET(apic_id));
}
#endif
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 19, 11:29 PM (5 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31807490
Default Alt Text
D36610.id114524.diff (29 KB)
Attached To
Mode
D36610: kern/intr: implement intrcnt/intrnames sysctl from event counters
Attached
Detach File
Event Timeline
Log In to Comment