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
This commit is contained in:
John-Mark Gurney 2003-07-16 00:08:43 +00:00
parent 57499a32b1
commit e93581dc7a
6 changed files with 125 additions and 4 deletions

View File

@ -68,6 +68,17 @@
bne,pn %icc, 9b ; \
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.
*/

View File

@ -33,6 +33,7 @@
#define PIL_MAX (1 << 4)
#define IV_MAX (1 << 11)
#define IV_NAMLEN 1024
#define IR_FREE (PIL_MAX * 2)

View File

@ -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

View File

@ -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);

View File

@ -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]

View File

@ -82,16 +82,88 @@
CTASSERT((1 << IV_SHIFT) == sizeof(struct intr_vector));
ih_func_t *intr_handlers[PIL_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);
}