Subject: interrupt stats on i386
To: None <port-i386@NetBSD.ORG>
From: John M Vinopal <banshee@gabriella.resort.com>
List: port-i386
Date: 04/04/1996 02:24:17
I hacked together a little something that delves into the dark
heart of i386; its not vmstat -i, but coupled with dmesg, its something.

/* Hackedover vmstat -i for i386
 * Thu Apr  4 02:23:55 PST 1996
 * banshee@resort.com
 */
#include <err.h>
#include <fcntl.h>
#include <kvm.h>
#include <limits.h>
#include <nlist.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* Extracted from isamachdep.[c,h] */

#define   ICU_LEN         16
struct intrhand {
        int     (*ih_fun)();
        void    *ih_arg;
        u_long  ih_count;
        struct  intrhand *ih_next;
        int     ih_level;
        int     ih_irq;
};

struct intrhand *cur[ICU_LEN];

static struct nlist namelist[] = {
#define	X_INTRHAND	0
	{ "_intrhand" },	/* Interrupt handler */
	{ NULL },
};

static kvm_t	*kd = NULL;
char	*nlistf = NULL;
char	*memf = NULL;

#define	KVM_ERROR(_string) {						\
	warnx((_string));						\
	errx(1, kvm_geterr(kd));					\
}

/*
 * Dereference the namelist pointer `v' and fill in the local copy 
 * 'p' which is of size 's'.
 */
#define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));

static void deref_kptr __P(( void *, void *, size_t));

/*
 * Dereference the kernel pointer `kptr' and fill in the local copy 
 * pointed to by `ptr'.  The storage space must be pre-allocated,
 * and the size of the copy passed in `len'.
 */
static void
deref_kptr(kptr, ptr, len)
	void *kptr, *ptr;
	size_t len;
{
	char buf[128];

	if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) {
		bzero(buf, sizeof(buf));
		snprintf(buf, (sizeof(buf) - 1),
		     "can't dereference kptr 0x%x", (uint)kptr);
		KVM_ERROR(buf);
	}
}


int
main()
{
        char		errbuf[_POSIX2_LINE_MAX];
	int		i, irq;

	/* Open the kernel. */
        if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
		errx(1, "kvm_openfiles: %s", errbuf);

	/* Obtain the namelist symbols from the kernel. */
	if (kvm_nlist(kd, namelist))
		KVM_ERROR("kvm_nlist failed to read symbols.");

	deref_nl(X_INTRHAND, &cur, sizeof(struct intrhand) * ICU_LEN);

	printf("IRQ COUNT\n");
	for (irq = 0; irq < ICU_LEN; irq++) {
		struct intrhand *q, tmp;

		q = cur[irq];
		while (q) {
			deref_kptr(q, &tmp, sizeof(struct intrhand));
			printf("%3d %5lu\n", tmp.ih_irq, tmp.ih_count);
			q = tmp.ih_next;
		}
	}
}