9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] pentium msr support
@ 1998-03-09  6:42 forsyth
  0 siblings, 0 replies; 2+ messages in thread
From: forsyth @ 1998-03-09  6:42 UTC (permalink / raw)


>>-	qlock(&msrlock);
>>-	for (i = 0; i < nf; ++i) {
>>-		switch (*f[i]) {
>>-		case 'c':
>>-			n = get_ulong(f[i]+1, 0, 1, "bad counter");
>>-			c[n] = 1;
>>-			break;

since get_ulong calls error(), i think you need to:

	qlock(&msrlock);
	if(waserror()){
		qunlock(&msrlock);
		nexterror();
	}
	...
and
	poperror();
at the end of the routine.






^ permalink raw reply	[flat|nested] 2+ messages in thread

* [9fans] pentium msr support
@ 1998-03-09  8:18 schwartz+9fans
  0 siblings, 0 replies; 2+ messages in thread
From: schwartz+9fans @ 1998-03-09  8:18 UTC (permalink / raw)


Anyone want to help me test something?  Support for Pentium performance
monitor counters, like the other unixie systems have these days.  The
enclosed code has only been tried on a Pentium, and it won't do the
right thing on a multiprocessor (I didn't want to tinker with clock.c,
to keep the changes to a minimum.)

Unpack in a fresh directory:

# To unbundle, run this file
echo README
sed 's/.//' >README <<'//GO.SYSIN DD README'
-To install:
-
-cp msr.s msr.h devmsr.c /sys/src/9/pc
-cd /sys/src/9/port; patch < print.c-diff
-add “msr Ψ” to dev in 9pc
-
-bind -a '#Ψ' /dev
-
-usage:
-
-#Ψ/cpuid
-	read: type features vendor
-#Ψ/msr
-	no user serviceable parts
-#Ψ/pmc
-	read: timestamp counter-0 counter-1
-	write: clears counters
-#Ψ/pmcctl
-	read: current mode
-	write: counter ring number event,
-	c{0,1} r{u,s,us} n{e,c} e0xff
-
-	counter arg is an integer (0 or 1)
-	ring arg is u(ser), s(ystem) or both,
-	number arg is e(vents) or c(locks),
-	event arg is integer as read by atol
-
//GO.SYSIN DD README
echo rdtsc.c
sed 's/.//' >rdtsc.c <<'//GO.SYSIN DD rdtsc.c'
-#include <u.h>
-#include <libc.h>
-#include "msr.h"
-
-void main()
-{
-	int r = print("%ulld\n", rdtsc());
-	exits(r>0?0:"print");
-}
//GO.SYSIN DD rdtsc.c
echo cpuid.c
sed 's/.//' >cpuid.c <<'//GO.SYSIN DD cpuid.c'
-#include <u.h>
-#include <libc.h>
-#include "msr.h"
-
-void err(const char* msg)
-{
-	perror(msg);
-	exits("err");
-}
-
-enum {
-	Etype = 0x3<<12,
-	Efamily = 0x7<<8,
-	Emodel = 0xf<<4,
-	
-};
-
-static char* type[] = {
-	"primary", "overdrive", "secondary", "reserved"
-};
-
-
-static char *flags[] = {
-	"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-	"cx8", "apic", "10", "sysent", "mtrr", "pge", "mca", "cmov",
-	"pat", "17", "18", "19", "20", "21", "22", "mmx",
-	"fxsave", "25", "26", "27", "28", "29", "30", "31"
-};
-
-void main()
-{
-	char buf[512];
-	char *flds[32];
-	int n, fd, cpu;
-
-	if ((fd = open("/dev/cpuid", OREAD)) < 0)
-		err("open");
-	if ((n = read(fd, buf, sizeof(buf))) < 0)
-		err("read");
-	buf[n-1] = 0;
-	close(fd);
-
-	setfields("\n");
-	n = getfields(buf, flds, sizeof(flds)/sizeof(flds[0]));
-	for (cpu = 0; cpu < n; ++cpu) {
-		char *p;
-		unsigned long a = strtoul(flds[cpu], &p, 10);
-		unsigned long d = strtoul(p, &p, 10);
-		int i;
-
-		print("cpu %d\n", cpu);
-		print("vendor %s\n", p+1);
-		print("type %ud\n", (a>>12) & 0x3);
-		print("family %ud\n", (a>>8) & 0xf);
-		print("model %ud\n", (a>>4) & 0xf);
-		print("stepping %d\n", (a>>0) & 0xf);
-		print("features ");
-		for (i = 0; i < 32; ++i)
-			if (d & (1<<i)) print("%s ", flags[i]);
-		print("\n");
-	}
-	exits(0);
-}
//GO.SYSIN DD cpuid.c
echo pmc.c
sed 's/.//' >pmc.c <<'//GO.SYSIN DD pmc.c'
-#include <u.h>
-#include <libc.h>
-#include "msr.h"
-
-void err(const char* msg)
-{
-	perror(msg);
-	exits("err");
-}
-
-void readat(int fd, int off, char* buf, int size)
-{
-	if (seek(fd, off, 0) < 0)
-		err("seek"); 
-	if (read(fd, buf, size) != size)
-		err("read");
-}
-
-int fd = -1;
-
-uvlong readmsr(int msr)
-{
-	uvlong val;
-	readat(fd, msr, (char*)&val, sizeof val);
-	return val;
-}
-
-void main()
-{
-	uvlong a, b;
-
-	if ((fd = open("/dev/msr", ORDWR)) < 0)
-		err("open");
-
-	a = readmsr(0x10);
-	if (print("tsc %ulld₁₀\n", a) < 0)
-		err("print");
-
-	a = readmsr(0x11);
-	if (print("cesr %ullo₈\n", a) < 0)
-		err("print");
-
-	a = readmsr(0x12);
-	b = readmsr(0x13);
-	if (print("pmc %ulld₁₀ %ulld₁₀\n", a, b) < 0)
-		err("print");
-
-#ifdef PPRO
-	a = rdmsr(0x12);
-	b = rdmsr(0x13);
-	if (print("pmc %ulld₁₀ %ulld₁₀\n", a, b) < 0)
-		err("print");
-#endif
-
-	exits(0);
-}
//GO.SYSIN DD pmc.c
echo watch-pmc.c
sed 's/.//' >watch-pmc.c <<'//GO.SYSIN DD watch-pmc.c'
-#include <u.h>
-#include <libc.h>
-
-void err(const char* msg)
-{
-	perror(msg);
-	exits("err");
-}
-
-int isnum(char c) {
-	return '0' <= c && c <='9';
-}
-
-char *atoull(char *s, unsigned long long *n)
-{
-	*n = 0;
-	while (!isnum(*s)) ++s;
-	while (isnum(*s)) *n = (*n)*10 + *s++ - '0';
-	return s;
-}
-
-void main(int argc, char *argv[])
-{
-	uvlong t, a, b;
-	uvlong ot, oa, ob;
-	int fd, delay;
-	char buf[128];
-
-	delay = (argc > 1) ? atol(argv[1])*1000 : 2000;
-
-	if ((fd = open("/dev/pmc", OREAD)) < 0)
-		err("open");
-
-	t = a = b = ot = oa = ob = 0;
-	while ((seek(fd, 0, 0) != -1) && (read(fd, buf, sizeof buf) > 0)) {
-		char *p = buf;
-		ot = t;
-		oa = a;
-		ob = b;
-		p = atoull(p, &t);
-		p = atoull(p, &a);
-		p = atoull(p, &b);
-		if (print("%ulld(%ulld) %ulld(%ulld) %ulld(%ulld)\n", t, t-ot, a, a-oa, b, b-ob) < 0)
-			err("print");
-		sleep(delay);
-	}
-	exits(0);
-}
//GO.SYSIN DD watch-pmc.c
echo msr.s
sed 's/.//' >msr.s <<'//GO.SYSIN DD msr.s'
-/* uvlong rdtsc(void); */
-TEXT rdtsc(SB),$0
-	MOVL .ret+0(FP),CX
-	BYTE $0x0f
-	BYTE $0x31
-	MOVL AX,0(CX)
-	MOVL DX,4(CX)
-	RET ,
-	END ,
-
-/* uvlong rdmsr(uint msr); */
-TEXT rdmsr(SB),$0
-	MOVL .msr+4(FP),CX
-	BYTE $0x0f
-	BYTE $0x32
-	MOVL .ret+0(FP),CX
-	MOVL AX,0(CX)
-	MOVL DX,4(CX)
-	RET ,
-	END ,
-
-/* void wrmsr(uint msr, uvlong val); */
-TEXT wrmsr(SB),$0
-	MOVL .msr+0(FP), CX
-	MOVL .val0+4(FP), AX
-	MOVL .val1+8(FP), DX
-	BYTE $0x0f
-	BYTE $0x30
-	RET ,
-	END ,
-
-/* void x86_cpuid(int n, ulong *a, ulong *b, ulong *c, ulong *d); */
-TEXT x86_cpuid(SB),$0
-	MOVL	n+0(FP),AX
-	/* CPUID */
-	 BYTE $0x0F
-	 BYTE $0xA2
-	MOVL AX,SI
-	MOVL a+4(FP),AX
-	MOVL SI,(AX)
-	MOVL b+8(FP),AX
-	MOVL BX,(AX)
-	MOVL c+12(FP),AX
-	MOVL CX,(AX)
-	MOVL d+16(FP),AX
-	MOVL DX,(AX)
-	RET
-	END
//GO.SYSIN DD msr.s
echo msr.h
sed 's/.//' >msr.h <<'//GO.SYSIN DD msr.h'
-#ifndef MSR_H
-#define MSR_H
-typedef unsigned long long msr_t; /* 64 bits */
-msr_t rdtsc(void);
-msr_t rdmsr(unsigned int msr);
-void wrmsr(unsigned int msr, msr_t val);
-extern x86_cpuid(int n, unsigned long *a, unsigned long *b, unsigned long *c, unsigned long *d);
-#endif
//GO.SYSIN DD msr.h
echo devmsr.c
sed 's/.//' >devmsr.c <<'//GO.SYSIN DD devmsr.c'
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"devtab.h"
-#include	"msr.h"
-
-char Enfields[] = "wrong number of fields";
-
-static void pmcctl_write(char *);
-static void check_msr(int);
-static char* fmt_pmcctl(char *, int);
-
-static int valid_msr_0(int);
-static msr_t rdmsr_ctr_0(int);
-static msr_t rdmsr_tsc_0(void);
-static void wrmsr_ctr_0(int, msr_t);
-static void wrmsr_cesr_0(int);
-static int valid_msr_5(int);
-static msr_t rdmsr_ctr_5(int);
-static void wrmsr_ctr_5(int, msr_t);
-static void wrmsr_cesr_5(int);
-static int valid_msr_6(int);
-static msr_t rdmsr_ctr_6(int);
-static void wrmsr_ctr_6(int, msr_t);
-static void wrmsr_cesr_6(int);
-
-enum {
-	Qdir = 0,
-	Qmsr,
-	Qpmc,
-	Qpmcctl,
-	Qcpuid,
-	Nmsrdir = Qcpuid,
-
-	Nfield = 10,
-	Ncntr = 2
-};
-
-Dirtab const msrdir[] = {
-	"msr",		{Qmsr},		0,	0664,
-	"pmc",		{Qpmc},		0,	0664,
-	"pmcctl",	{Qpmcctl},	0,	0664,
-	"cpuid",	{Qcpuid},	0,	0444,
-};
-
-typedef struct
-{
-	unsigned int processor, features;
-	char vendor[12+1];
-} cpuid_t;
-
-typedef struct
-{
-	unsigned short msr;
-	unsigned char event;
-	unsigned char user, sys, edge; /* “I'd use plan 9 before i'd use bitfields -- pjw” */
-} pmcctl_t;
-
-static cpuid_t cpuid[MAXMACH];
-static pmcctl_t pmcctl[MAXMACH][Ncntr];
-
-static int (*valid_msr)(int);
-static void (*wrmsr_cesr)(int);
-static msr_t (*rdmsr_ctr)(int);
-static void (*wrmsr_ctr)(int, msr_t);
-static msr_t (*rdmsr_tsc)(void);
-
-QLock msrlock;
-
-/* ----- */
-
-void msrreset(void)
-{
-}
-
-void msrinit(void)
-{
-	ulong a, b, c, d;
-	int x = x86();
-
-	valid_msr = valid_msr_0;
-	wrmsr_cesr = wrmsr_cesr_0;
-	wrmsr_ctr = wrmsr_ctr_0;
-	rdmsr_ctr = rdmsr_ctr_0;
-	rdmsr_tsc = rdmsr_tsc_0;
-
-	switch (x) {
-	case 3:
-	case 4:
-		strcpy(cpuid[0].vendor, "unknown  x86");
-		cpuid[0].processor = 0;
-		cpuid[0].features = 0;
-		return;
-	case 5:
-		valid_msr = valid_msr_5;
-		wrmsr_cesr = wrmsr_cesr_5;
-		wrmsr_ctr = wrmsr_ctr_5;
-		rdmsr_ctr = rdmsr_ctr_5;
-		break;
-	case 6:
-		valid_msr = valid_msr_6;
-		wrmsr_cesr = wrmsr_cesr_6;
-		wrmsr_ctr = wrmsr_ctr_6;
-		rdmsr_ctr = rdmsr_ctr_6;
-		break;
-	}
-	rdmsr_tsc = rdtsc;
-
-	x86_cpuid(0, &a, &b, &c, &d);
-	memmove(cpuid[0].vendor+0, (char*)&b, 4);
-	memmove(cpuid[0].vendor+4, (char*)&d, 4);
-	memmove(cpuid[0].vendor+8, (char*)&c, 4);
-	cpuid[0].vendor[sizeof(cpuid[0].vendor)-1] = 0;
-
-	x86_cpuid(1, &a, &b, &c, &d);
-	cpuid[0].processor = a;
-	cpuid[0].features = d;
-}
-
-Chan* msrattach(char *spec)
-{
-	return devattach(L'Ψ', spec);
-}
-
-Chan* msrclone(Chan *c, Chan *nc)
-{
-	return devclone(c, nc);
-}
-
-int msrwalk(Chan *c, char *name)
-{
-	return devwalk(c, name,  msrdir, Nmsrdir, devgen);
-}
-
-void msrstat(Chan *c, char *dp)
-{
-	devstat(c, dp, msrdir, Nmsrdir, devgen);
-}
-
-Chan* msropen(Chan *c, int omode)
-{
-	omode = openmode(omode);
-	switch (c->qid.path) {
-	case Qmsr:
-		/* sensitive */
-		if (strcmp(u->p->user, eve) != 0)
-			error(Eperm);
-		break;
-	}
-	return devopen(c, omode, msrdir, Nmsrdir, devgen);
-}
-
-void msrcreate(Chan *c, char *name, int omode, ulong perm)
-{
-	USED(c, name, omode, perm);
-	error(Eperm);
-}
-
-void msrclose(Chan *c)
-{
-	USED(c);
-}
-
-long msrread(Chan *c, void *buf, long n, ulong offset)
-{
-	msr_t t, a, b;
-	char tmp[255];
-	
-	switch (c->qid.path &~ CHDIR) {
-	case Qdir:
-		return devdirread(c, buf, n, msrdir, Nmsrdir, devgen);
-	case Qmsr:
-		check_msr(offset);
-		if (n > sizeof(a))
-			n = sizeof(a);
-		qlock(&msrlock);		
-		a = rdmsr(offset);
-		qunlock(&msrlock);
-		memmove(buf, (char*)&a, n);
-		return n;
-	case Qpmc:
-		qlock(&msrlock);		
-		t = rdmsr_tsc();
-		a = rdmsr_ctr(0);
-		b = rdmsr_ctr(1);
-		qunlock(&msrlock);
-		snprint(tmp, sizeof tmp, "%ulld %ulld %ulld\n", t, a, b);
-		/* XXX - %ulld requires fix to kernel doprint */
-		return readstr(offset, buf, n, tmp);
-	case Qpmcctl:
-		return readstr(offset, buf, n, fmt_pmcctl(tmp, sizeof tmp));
-	case Qcpuid:
-		snprint(tmp, sizeof tmp, "%ud %ud %s\n",
-			cpuid[0].processor, cpuid[0].features, cpuid[0].vendor);
-		return readstr(offset, buf, n, tmp);
-	}
-	error(Ebadarg);
-	return 0;
-}
-
-long msrwrite(Chan *c, void *buf, long n, ulong offset)
-{
-	msr_t val;
-	char cbuf[64];
-
-	switch (c->qid.path &~ CHDIR) {
-	case Qdir:
-		error(Eperm);
-	case Qmsr:
-		check_msr(offset);
-		if (0 > n || n > sizeof(val))
-			error(Ebadarg);		
-		memmove((char*)&val, buf, n);
-		qlock(&msrlock);
-		wrmsr(offset, val);
-		qunlock(&msrlock);
-		return n;
-	case Qpmc:
-		qlock(&msrlock);
-		wrmsr_ctr(0, 0LL);
-		wrmsr_ctr(1, 0LL);
-		qunlock(&msrlock);
-		return n;
-	case Qpmcctl:
-		if(offset != 0 || n >= sizeof(cbuf))
-			error(Ebadarg);
-		memmove(cbuf, buf, n);
-		cbuf[n] = 0;
-		pmcctl_write(cbuf);
-		return n;
-	}
-	error(Ebadarg);
-	return 0;
-}
-
-void msrremove(Chan *c)
-{
-	USED(c);
-	error(Eperm);
-}
-
-void msrwstat(Chan *c, char *dp)
-{
-	USED(c, dp);
-	error(Eperm);
-}
-
-/* ----- */
-
-static unsigned long get_ulong(char *buf, unsigned int lo, unsigned int hi, char const *err)
-{
-	char *p = 0;
-	unsigned long i = strtoul(buf, &p, 0);
-	if (p == buf) error(Ebadarg);
-	if (!(lo <= i && i <= hi))
-		error(err);
-	return i;
-}
-
-static char* fmt_pmcctl(char *buf, int size)
-{
-	int i, n;
-	char *bp = buf;
-	
-	qlock(&msrlock);
-	for (i = 0; i < Ncntr; ++i) {
-		n = snprint(bp, size, "c%ud r%s%s n%c e%ud\n",
-			i,
-			pmcctl[0][i].user?"u":"", 
-			pmcctl[0][i].sys?"s":"",
-			pmcctl[0][i].edge?'c':'e',
-			pmcctl[0][i].event);
-		bp += n;
-		size -= n;
-	}
-	qunlock(&msrlock);
-	return buf;
-}
-
-static void pmcctl_write(char *arg)
-{
-	int i, n, nf;
-	pmcctl_t *pp;
-	char *f[16];
-	int z[Ncntr];
-	int c[Ncntr];
-
-	/* counter ring number event zero */
-	/* c{0,1} r[u][s] n{e,c} e0x22 z */
-
-	nf = getfields(arg, f, sizeof(f)/sizeof(f[0]), " \t\n");
-	pp = pmcctl[0];
-	c[0] = c[1] = z[0] = z[1] = n = 0;
-	qlock(&msrlock);
-	for (i = 0; i < nf; ++i) {
-		switch (*f[i]) {
-		case 'c':
-			n = get_ulong(f[i]+1, 0, 1, "bad counter");
-			c[n] = 1;
-			break;
-		case 'r':
-			pp[n].user = !!strchr(f[i]+1, 'u');
-			pp[n].sys = !!strchr(f[i]+1, 's');
-			break;
-		case 'n':
-			pp[n].edge = !!strchr(f[i]+1, 'c');
-			break;
-		case 'e':
-			pp[n].event = get_ulong(f[i]+1, 0, 0xff, "bad event");
-			break;
-		case 'z':
-			z[n] = 1;
-			break;
-		}
-	}
-	for (i = 0; i < Ncntr; ++i)
-		if (c[i]) wrmsr_cesr(i);
-	for (i = 0; i < Ncntr; ++i)
-		if (z[i]) wrmsr_ctr(i, 0LL);
-	qunlock(&msrlock);
-}
-
-static void check_msr(int msr)
-{
-	if (!valid_msr(msr)) {
-		char tmp[64];
-		snprint(tmp, sizeof(tmp), "bad msr #%ud", msr);
-		error(tmp);
-	}
-}
-
-/* ----- */
-
-static int valid_msr_0(int msr)	{ USED(msr); error(Ebadctl);  return 0;}
-static msr_t rdmsr_ctr_0(int n)	{ USED(n); return 0; }
-static msr_t rdmsr_tsc_0(void) { return 0; }
-static void wrmsr_ctr_0(int n, msr_t v) { USED(n, v); return; }
-static void wrmsr_cesr_0(int n) { USED(n); return; }
-
-static int valid_msr_5(int msr) { return (0 <= msr && msr <= 0x13); }
-static msr_t rdmsr_ctr_5(int n) { return rdmsr(0x12+n); }
-static void wrmsr_ctr_5(int n, msr_t val) { wrmsr(0x12+n, val); }
-static void wrmsr_cesr_5(int n) 
-{
-	pmcctl_t *pp = pmcctl[0];
-	wrmsr(0x11,
-		(pp[1].edge<<24)|(pp[1].user<<23)|(pp[1].sys<<22)|(pp[1].event<<16)|
-		(pp[0].edge<<8)|(pp[0].user<<7)|(pp[0].sys<<6)|(pp[0].event));
-	USED(n);
-}
-
-static int valid_msr_6(int msr) { return (0 <= msr && msr <= 0x406); /* ?? */ }
-static msr_t rdmsr_ctr_6(int n) { return rdmsr(0xC1+n); }
-static void wrmsr_ctr_6(int n, msr_t val) { wrmsr(0xC1+n, val); }
-static void wrmsr_cesr_6(int n) 
-{
-	pmcctl_t *pp = pmcctl[0];
-	wrmsr(0x186+n, (1UL<<22)|(pp[n].edge<<18)|(pp[n].sys<<17)|(pp[n].user<<16)|(pp[n].event));
-}
-
//GO.SYSIN DD devmsr.c
echo print.c-diff
sed 's/.//' >print.c-diff <<'//GO.SYSIN DD print.c-diff'
-term% diff /n/cd/sys/src/9/port/print.c print.c
-230c230
-< 	vlong vl;
----
-> 	long long vl;
-258c258
-< 		vl = *(vlong*)o;
----
-> 		vl = *(long long*)o;
-261a262,266
-> 	case FUNSIGN|FVLONG|FLONG:
-> 		vl = *(unsigned long long*)o;
-> 		r = VLONG;
-> 		break;
-> 
-301c306
-< 			n = vl % b;
----
-> 			n = (unsigned long long)vl % b;
-303c308
-< 			n = (ulong)v % b;
----
-> 			n = (unsigned long)v % b;
-314c319
-< 			vl = vl / b;
----
-> 			vl = (unsigned long long)vl / b;
-319c324
-< 		if(fp->f3 & FVLONG)
----
-> 		if(fp->f3 & FVLONG) {
-321a327,328
-> 			continue;
-> 		}
//GO.SYSIN DD print.c-diff




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~1998-03-09  8:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-03-09  6:42 [9fans] pentium msr support forsyth
1998-03-09  8:18 schwartz+9fans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).