diff options
author | jmg <jmg@FreeBSD.org> | 2003-07-16 00:08:43 +0000 |
---|---|---|
committer | jmg <jmg@FreeBSD.org> | 2003-07-16 00:08:43 +0000 |
commit | a54595f215d4214fd4bf8611ab2de5ebb1cc5f69 (patch) | |
tree | 19d7e5f94f5d81ed8d6b0f598793c553264f1e27 /sys/sparc64 | |
parent | b103245463e76b8f23e542dab167cca640c53b0b (diff) | |
download | FreeBSD-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/sparc64')
-rw-r--r-- | sys/sparc64/include/asmacros.h | 11 | ||||
-rw-r--r-- | sys/sparc64/include/intr_machdep.h | 1 | ||||
-rw-r--r-- | sys/sparc64/sparc64/exception.S | 24 | ||||
-rw-r--r-- | sys/sparc64/sparc64/genassym.c | 1 | ||||
-rw-r--r-- | sys/sparc64/sparc64/interrupt.S | 13 | ||||
-rw-r--r-- | sys/sparc64/sparc64/intr_machdep.c | 79 |
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); } |