summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>2003-07-16 00:08:43 +0000
committerjmg <jmg@FreeBSD.org>2003-07-16 00:08:43 +0000
commita54595f215d4214fd4bf8611ab2de5ebb1cc5f69 (patch)
tree19d7e5f94f5d81ed8d6b0f598793c553264f1e27 /sys
parentb103245463e76b8f23e542dab167cca640c53b0b (diff)
downloadFreeBSD-src-a54595f215d4214fd4bf8611ab2de5ebb1cc5f69.zip
FreeBSD-src-a54595f215d4214fd4bf8611ab2de5ebb1cc5f69.tar.gz
add support for interrupt counting on sparc64. This copies part of the
code from i386. The code has a slight bogon that interrupts are counted twice. Once on the ithread dispatch and once on the dispatch for the vector vmstat -i and systat -vm now contains interrupt counts. Reviewed by: jake
Diffstat (limited to 'sys')
-rw-r--r--sys/sparc64/include/asmacros.h11
-rw-r--r--sys/sparc64/include/intr_machdep.h1
-rw-r--r--sys/sparc64/sparc64/exception.S24
-rw-r--r--sys/sparc64/sparc64/genassym.c1
-rw-r--r--sys/sparc64/sparc64/interrupt.S13
-rw-r--r--sys/sparc64/sparc64/intr_machdep.c79
6 files changed, 125 insertions, 4 deletions
diff --git a/sys/sparc64/include/asmacros.h b/sys/sparc64/include/asmacros.h
index 2fd5143..a0e317b 100644
--- a/sys/sparc64/include/asmacros.h
+++ b/sys/sparc64/include/asmacros.h
@@ -69,6 +69,17 @@
mov r3, r2
/*
+ * Atomically increment an u_long in memory.
+ */
+#define ATOMIC_INC_ULONG(r1, r2, r3) \
+ ldx [r1], r2 ; \
+9: add r2, 1, r3 ; \
+ casxa [r1] ASI_N, r2, r3 ; \
+ cmp r2, r3 ; \
+ bne,pn %icc, 9b ; \
+ mov r3, r2
+
+/*
* Atomically clear a number of bits of an integer in memory.
*/
#define ATOMIC_CLEAR_INT(r1, r2, r3, bits) \
diff --git a/sys/sparc64/include/intr_machdep.h b/sys/sparc64/include/intr_machdep.h
index 2f9c1ef..9d29730 100644
--- a/sys/sparc64/include/intr_machdep.h
+++ b/sys/sparc64/include/intr_machdep.h
@@ -33,6 +33,7 @@
#define PIL_MAX (1 << 4)
#define IV_MAX (1 << 11)
+#define IV_NAMLEN 1024
#define IR_FREE (PIL_MAX * 2)
diff --git a/sys/sparc64/sparc64/exception.S b/sys/sparc64/sparc64/exception.S
index 6126d59..5c200f7 100644
--- a/sys/sparc64/sparc64/exception.S
+++ b/sys/sparc64/sparc64/exception.S
@@ -364,7 +364,7 @@ ENTRY(rsf_fatal)
sir
END(rsf_fatal)
- .comm intrnames, IV_MAX * 8
+ .comm intrnames, IV_NAMLEN
.comm eintrnames, 0
.comm intrcnt, IV_MAX * 8
@@ -2316,6 +2316,17 @@ ENTRY(tl0_intr)
stx %i6, [%sp + SPOFF + CCFSZ + TF_O6]
stx %i7, [%sp + SPOFF + CCFSZ + TF_O7]
+ /* %l3 contains PIL */
+ SET(intrcnt, %l1, %l2)
+ prefetcha [%l2] ASI_N, 1
+ SET(pil_countp, %l1, %l0)
+ sllx %l3, 1, %l1
+ lduh [%l0 + %l1], %l0
+ sllx %l0, 3, %l0
+ add %l0, %l2, %l0
+
+ ATOMIC_INC_ULONG(%l0, %l1, %l2)
+
call critical_enter
nop
@@ -2820,6 +2831,17 @@ ENTRY(tl1_intr)
mov %l5, PCPU_REG
wrpr %g0, PSTATE_KERNEL, %pstate
+ /* %l3 contains PIL */
+ SET(intrcnt, %l5, %l4)
+ prefetcha [%l4] ASI_N, 1
+ SET(pil_countp, %l5, %l6)
+ sllx %l7, 1, %l5
+ lduh [%l5 + %l6], %l5
+ sllx %l5, 3, %l5
+ add %l5, %l4, %l4
+
+ ATOMIC_INC_ULONG(%l4, %l5, %l6)
+
call critical_enter
nop
diff --git a/sys/sparc64/sparc64/genassym.c b/sys/sparc64/sparc64/genassym.c
index ad34548..6360b84 100644
--- a/sys/sparc64/sparc64/genassym.c
+++ b/sys/sparc64/sparc64/genassym.c
@@ -218,6 +218,7 @@ ASSYM(IV_FUNC, offsetof(struct intr_vector, iv_func));
ASSYM(IV_ARG, offsetof(struct intr_vector, iv_arg));
ASSYM(IV_PRI, offsetof(struct intr_vector, iv_pri));
+ASSYM(IV_NAMLEN, IV_NAMLEN);
ASSYM(IV_MAX, IV_MAX);
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
diff --git a/sys/sparc64/sparc64/interrupt.S b/sys/sparc64/sparc64/interrupt.S
index 38cb6cf..69f8cd8 100644
--- a/sys/sparc64/sparc64/interrupt.S
+++ b/sys/sparc64/sparc64/interrupt.S
@@ -169,7 +169,18 @@ ENTRY(intr_fast)
3: ldx [%l0 + IR_FUNC], %o0
ldx [%l0 + IR_ARG], %o1
- ldx [%l0 + IR_VEC], %o2
+ lduw [%l0 + IR_VEC], %o2
+
+ /* load intrcnt[intr_countp[%o2]] into %l4 */
+ SET(intrcnt, %l7, %l2) /* %l5 = intrcnt */
+ prefetcha [%l2] ASI_N, 1
+ SET(intr_countp, %l7, %l3) /* %l6 = intr_countp */
+ sllx %o2, 1, %l4 /* %l4 = vec << 1 */
+ lduh [%l4 + %l3], %l5 /* %l6 = intr_countp[%o2] */
+ sllx %l5, 3, %l6 /* %l6 = intr_countp[%o2] << 3 */
+ add %l6, %l2, %l7 /* %l4 = intrcnt[intr_countp[%o2]] */
+
+ ATOMIC_INC_ULONG(%l7, %l5, %l2)
ldx [PCPU(IRFREE)], %l1
stx %l1, [%l0 + IR_NEXT]
diff --git a/sys/sparc64/sparc64/intr_machdep.c b/sys/sparc64/sparc64/intr_machdep.c
index 8260673..b74da52 100644
--- a/sys/sparc64/sparc64/intr_machdep.c
+++ b/sys/sparc64/sparc64/intr_machdep.c
@@ -82,16 +82,88 @@
CTASSERT((1 << IV_SHIFT) == sizeof(struct intr_vector));
ih_func_t *intr_handlers[PIL_MAX];
-struct intr_vector intr_vectors[IV_MAX];
+u_int16_t pil_countp[PIL_MAX];
+struct intr_vector intr_vectors[IV_MAX];
u_long intr_stray_count[IV_MAX];
+u_int16_t intr_countp[IV_MAX];
+char *pil_names[] = {
+ "stray",
+ "low", /* PIL_LOW */
+ "ithrd", /* PIL_ITHREAD */
+ "rndzvs", /* PIL_RENDEZVOUS */
+ "ast", /* PIL_AST */
+ "stop", /* PIL_STOP */
+ "stray", "stray", "stray", "stray", "stray", "stray", "stray",
+ "fast", /* PIL_FAST */
+ "tick", /* PIL_TICK */
+};
+
/* protect the intr_vectors table */
static struct mtx intr_table_lock;
static void intr_stray_level(struct trapframe *tf);
static void intr_stray_vector(void *cookie);
+/*
+ * not MPSAFE
+ */
+static void
+update_intrname(int vec, const char *name, int ispil)
+{
+ char buf[32];
+ char *cp;
+ int off, name_index;
+
+ if (intrnames[0] == '\0') {
+ /* for bitbucket */
+ if (bootverbose)
+ printf("initalizing intr_countp\n");
+ off = sprintf(intrnames, "???") + 1;
+
+ off += sprintf(intrnames + off, "stray") + 1;
+ for (name_index = 0; name_index < IV_MAX; name_index++)
+ intr_countp[name_index] = 1;
+
+ off += sprintf(intrnames + off, "pil") + 1;
+ for (name_index = 0; name_index < PIL_MAX; name_index++)
+ pil_countp[name_index] = 2;
+ }
+
+ if (name == NULL)
+ name = "???";
+
+ if (snprintf(buf, sizeof(buf), "%s %s%d", name, ispil ? "pil" : "vec",
+ vec) >= sizeof(buf))
+ goto use_bitbucket;
+
+ /*
+ * Search for `buf' in `intrnames'. In the usual case when it is
+ * not found, append it to the end if there is enough space (the \0
+ * terminator for the previous string, if any, becomes a separator).
+ */
+ for (cp = intrnames, name_index = 0; cp != eintrnames &&
+ name_index < IV_MAX; cp += strlen(cp) + 1, name_index++) {
+ if (*cp == '\0') {
+ if (strlen(buf) >= eintrnames - cp)
+ break;
+ strcpy(cp, buf);
+ goto found;
+ }
+ if (strcmp(cp, buf) == 0)
+ goto found;
+ }
+
+use_bitbucket:
+ name_index = 0;
+found:
+ if (!ispil)
+ intr_countp[vec] = name_index;
+ else
+ pil_countp[vec] = name_index;
+}
+
void
intr_setup(int pri, ih_func_t *ihf, int vec, iv_func_t *ivf, void *iva)
{
@@ -104,6 +176,7 @@ intr_setup(int pri, ih_func_t *ihf, int vec, iv_func_t *ivf, void *iva)
intr_vectors[vec].iv_pri = pri;
intr_vectors[vec].iv_vec = vec;
}
+ update_intrname(pri, pil_names[pri], 1);
intr_handlers[pri] = ihf;
intr_restore(ps);
}
@@ -222,7 +295,9 @@ inthand_add(const char *name, int vec, void (*handler)(void *), void *arg,
intr_setup(PIL_FAST, intr_fast, vec, handler, arg);
intr_stray_count[vec] = 0;
- /* XXX: name is not yet used. */
+
+ update_intrname(vec, name, 0);
+
return (0);
}
OpenPOWER on IntegriCloud