add facility for poking and prodding x86 MSRs. Reference: /n/atom/patch/applied/rdmsr Date: Tue Apr 8 19:47:49 CES 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/aux/rdmsr.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/aux/rdmsr.c Tue Apr 8 19:47:30 2014 @@ -0,0 +1,41 @@ +#include +#include + +void +usage(void) +{ + fprint(2, "usage: rdmsr ...\n"); + exits("usage"); +} + +void +rdmsr(char *s) +{ + char buf[32]; + int fd, n; + u32int msr; + + msr = strtoul(s, 0, 0); + fd = open("/dev/msr", OREAD); + if(fd == -1) + sysfatal("%s: open: %r", argv0); + n = pread(fd, buf, sizeof buf, msr); + if(n > 0) + write(1, buf, n); + close(fd); +} + +void +main(int argc, char **argv) +{ + int i; + + ARGBEGIN{ + default: + usage(); + }ARGEND + + for(i = 0; i < argc; i++) + rdmsr(argv[i]); + exits(""); +} --- /sys/src/cmd/aux/wrmsr.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/aux/wrmsr.c Tue Apr 8 19:47:30 2014 @@ -0,0 +1,39 @@ +#include +#include + +void +usage(void) +{ + fprint(2, "usage: %s msr value ...\n", argv0); + exits("usage"); +} + +void +rdmsr(char *s, char *v) +{ + int fd; + + fd = open("/dev/msr", OREAD); + if(fd == -1) + sysfatal("%s: open: %r", argv0); + if(pwrite(fd, v, strlen(v), strtoul(s, 0, 0)) == -1) + sysfatal("%s: pwrite: %r", argv0); + close(fd); +} + +void +main(int argc, char **argv) +{ + int i; + + ARGBEGIN{ + default: + usage(); + }ARGEND + if(argc & 1) + usage(); + + for(i = 0; i < argc; i += 2) + rdmsr(argv[i], argv[i+1]); + exits(""); +} --- /sys/src/cmd/aux/mkfile Tue Apr 8 19:47:30 2014 +++ /sys/src/cmd/aux/mkfile Tue Apr 8 19:47:30 2014 @@ -30,6 +30,7 @@ olefs\ pcmcia\ portmap\ + rdmsr\ rdwr\ reboot\ searchfs\ @@ -39,6 +40,7 @@ trampoline\ usage\ write\ + wrmsr\ xlisten\ zerotrunc\ --- /sys/src/nix/k10/devarch.c Tue Apr 8 19:47:30 2014 +++ /sys/src/nix/k10/devarch.c Tue Apr 8 19:47:30 2014 @@ -399,11 +399,45 @@ return readstr(off, a, n, buf); } +/* need to catch #GP */ +static long +msrread(Chan*, void *a, long n, vlong o) +{ + char buf[32]; + u32int msr; + uvlong v; + + if(o != (uint)o) + error(Egreg); + msr = (uint)o; + v = rdmsr(msr); + snprint(buf, sizeof buf, "%#.16llux\n", v); + return readstr(0, a, n, buf); +} + +static long +msrwrite(Chan*, void *a, long n, vlong o) +{ + char buf[32]; + u32int msr; + uvlong v; + + if(o != (uint)o || n > 31) + error(Egreg); + memmove(buf, a, n); + buf[n] = 0; + v = strtoull(buf, nil, 0); + msr = (uint)o; + wrmsr(msr, v); + return n; +} + void archinit(void) { addarchfile("cputype", 0444, cputyperead, nil); addarchfile("archcfg", 0444, archcfgread, nil); + addarchfile("msr", 0664, msrread, msrwrite); } void --- /sys/man/8/rdmsr Thu Jan 1 00:00:00 1970 +++ /sys/man/8/rdmsr Tue Apr 8 19:47:30 2014 @@ -0,0 +1,25 @@ +.TH RDMSR 8 +.SH NAME +rdmsr, wrmsr \- read and write x86 model specific registers +.SH SYNOPSIS +.B aux/rdmsr +.I msr +... +.br +.B aux/wrmsr +.I msr +.I value +... +.SH DESCRIPTION +These programs allow direct access to x86 model specific +registers. Since MSRs may not be read by user programs, +they require +.BR /dev/msr . +.SH SOURCE +.B /sys/src/cmd/aux/rdmsr.c +.br +.B /sys/src/cmd/aux/wrmsr.c +.SH BUGS +Invalid MSR references may result in a #GP trap and +crash. +