diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-05-05 10:44:29 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-05-05 10:44:29 +0200 |
commit | 68c77bf4a6aa932a7f31d8d84a378656542c80c2 (patch) | |
tree | ca131975e95cea44008370e487ebbf2011889d52 /sys/src/9/pc/cputemp.c | |
parent | 70aab46761fe0a9810323bf1664a890c4af3ae5d (diff) |
kernel: add eriks #P/cputemp
Diffstat (limited to 'sys/src/9/pc/cputemp.c')
-rw-r--r-- | sys/src/9/pc/cputemp.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/sys/src/9/pc/cputemp.c b/sys/src/9/pc/cputemp.c new file mode 100644 index 000000000..4cbf620c7 --- /dev/null +++ b/sys/src/9/pc/cputemp.c @@ -0,0 +1,168 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static int +intelcputempok(void) +{ + ulong regs[4]; + + if(m->cpuiddx & Acpif) + if(strcmp(m->cpuidid, "GenuineIntel") == 0){ + cpuid(6, regs); + return regs[0] & 1; + } + return 0; +} + +static long +cputemprd0(Chan*, void *a, long n, vlong offset) +{ + char buf[32], *s; + ulong msr, t, res, d; + vlong emsr; + ulong regs[4]; + static ulong tj; + + cpuid(6, regs); + if((regs[0] & 1) == 0) + return readstr(offset, a, n, "-1±-1 unsupported\n"); + if(tj == 0){ + /* + * magic undocumented msr. tj(max) is 100 or 85. + */ + tj = 100; + d = X86MODEL(m->cpuidax); + d |= (m->cpuidax>>12) & 0xf0; + if((d == 0xf && (m->cpuidax & 0xf)>1) || d == 0xe){ + rdmsr(0xee, &emsr); + msr = emsr; + if(msr & 1<<30) + tj = 85; + } + } + rdmsr(0x19c, &emsr); + msr = emsr; + t = -1; + if(msr & 1<<31){ + t = (msr>>16) & 127; + t = tj - t; + } + res = (msr>>27) & 15; + s = ""; + if((msr & 0x30) == 0x30) + s = " alarm"; + snprint(buf, sizeof buf, "%ld±%uld%s\n", t, res, s); + return readstr(offset, a, n, buf); +} + +static long +intelcputemprd(Chan *c, void *va, long n, vlong offset) +{ + char *a; + long i, r, t; + Mach *w; + + w = up->wired; + a = va; + t = 0; + for(i = 0; i < conf.nmach; i++){ + procwired(up, i); + sched(); + r = cputemprd0(c, a, n, offset); + if(r == 0) + break; + offset -= r; + if(offset < 0) + offset = 0; + n -= r; + a = a + r; + t += r; + } + up->wired = w; + sched(); + return t; +} + +static long +amd0ftemprd(Chan*, void *a, long n, vlong offset) +{ + char *s, *e, buf[64]; + long i, t, j, max; + Pcidev *p; + + p = pcimatch(0, 0x1022, 0x1103); + if(p == nil) + return readstr(offset, a, n, "-1±-1 unsupported\n"); + max = 2; + if(max > conf.nmach) + max = conf.nmach; + s = buf; + e = buf + sizeof buf; + for(j = 0; j < max; j++){ + pcicfgw32(p, 0xe4, pcicfgr32(p, 0xe4) & ~4 | j<<2); + i = pcicfgr32(p, 0xe4); + if(X86STEPPING(m->cpuidax) == 2) + t = i>>16 & 0xff; + else{ + t = i>>14 & 0x3ff; + t *= 3; + t /= 4; + } + t += -49; + s = seprint(s, e, "%ld±%uld%s\n", t, 1l, ""); + } + return readstr(offset, a, n, buf); +} + +static long +amd10temprd(Chan*, void *a, long n, vlong offset) +{ + char *s, *e, *r, *buf; + long i, t, c, nb, cores[MAXMACH]; + Pcidev *p; + + nb = 0; + for(p = 0; p = pcimatch(p, 0x1022, 0x1203); ){ + cores[nb++] = 1 + ((pcicfgr32(p, 0xe8) & 0x3000)>>12); + if(nb == nelem(cores)) + break; + } + if(nb == 0) + return readstr(offset, a, n, "-1±-1 unsupported\n"); + buf = smalloc(MAXMACH*4*32); + s = buf; + e = buf + MAXMACH*4*32; + nb = 0; + c = 0; + for(p = 0; p = pcimatch(p, 0x1022, 0x1203); nb++){ + i = pcicfgr32(p, 0xa4) & 0x7fffffff; + i >>= 21; + t = i/8; + r = ".0"; + if(i % 8 >= 4) + r = "0.5"; + /* + * only one value per nb; repeat per core + */ + while(c++ < conf.nmach && cores[nb]--) + s = seprint(s, e, "%ld%s±0.5%s\n", t, r, ""); + } + i = readstr(offset, a, n, buf); + free(buf); + return i; +} + +void +cputemplink(void) +{ + if(intelcputempok()) + addarchfile("cputemp", 0444, intelcputemprd, nil); + if(X86FAMILY(m->cpuidax) == 0x0f && !strcmp(m->cpuidid, "AuthenticAMD")) + addarchfile("cputemp", 0444, amd0ftemprd, nil); + if(X86FAMILY(m->cpuidax) == 0x10 && !strcmp(m->cpuidid, "AuthenticAMD")) + addarchfile("cputemp", 0444, amd10temprd, nil); +} |