--- /n/sources/plan9/sys/man/3/arch Tue Sep 18 22:24:42 2012 +++ /sys/man/3/arch Sat Jan 5 00:00:00 2013 @@ -7,6 +7,7 @@ .sp 0.3v .B /dev/archctl .B /dev/cputype +.B /dev/cputemp .B /dev/ioalloc .B /dev/iob .B /dev/iol @@ -19,6 +20,11 @@ Reads from .I cputype recover the processor type and clock rate in MHz. +Reads from +.I cputemp +recover one line containing per processor containing +two fields: the processor temperature and precision +in degrees Celsius. Reads from .I archctl yield at least data of this form: --- /n/sources/plan9/sys/src/9/pcboot/dat.h Fri Aug 17 20:11:39 2012 +++ /sys/src/9/pcboot/dat.h Sat Jan 5 00:00:00 2013 @@ -324,6 +324,7 @@ Pge = 1<<13, /* page global extension */ Pse2 = 1<<17, /* more page size extensions */ Clflush = 1<<19, + Acpif = 1<<22, Mmx = 1<<23, Fxsr = 1<<24, /* have SSE FXSAVE/FXRSTOR */ Sse = 1<<25, /* thus sfence instr. */ --- /n/sources/plan9/sys/src/9/pc/dat.h Wed Aug 15 19:06:06 2012 +++ /sys/src/9/pc/dat.h Sat Jan 5 00:00:00 2013 @@ -323,6 +323,7 @@ Pge = 1<<13, /* page global extension */ Pse2 = 1<<17, /* more page size extensions */ Clflush = 1<<19, + Acpif = 1<<22, Mmx = 1<<23, Fxsr = 1<<24, /* have SSE FXSAVE/FXRSTOR */ Sse = 1<<25, /* thus sfence instr. */ --- /n/sources/plan9/sys/src/9/pc/devarch.c Wed Aug 15 19:12:39 2012 +++ /sys/src/9/pc/devarch.c Sat Jan 5 00:00:00 2013 @@ -869,6 +869,159 @@ return readstr(offset, a, n, str); } +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 char Notemp[] = "-1 -1 unsupported\n"; + +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, Notemp); + 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 %lud%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, Notemp); + 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 %lud%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, Notemp); + 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; +} + static long archctlread(Chan*, void *a, long nn, vlong offset) { @@ -1041,6 +1194,18 @@ if(m->cpuiddx & Sse2) coherence = mfence; + if(intelcputempok()) + addarchfile("cputemp", 0444, intelcputemprd, nil); + if(strcmp(m->cpuidid, "AuthenticAMD") == 0) + switch(X86FAMILY(m->cpuidax)){ + case 0xf: + addarchfile("cputemp", 0444, amd0ftemprd, nil); + break; + case 0x10: + case 0x1f: + addarchfile("cputemp", 0444, amd10temprd, nil); + break; + } addarchfile("cputype", 0444, cputyperead, nil); addarchfile("archctl", 0664, archctlread, archctlwrite); }