--- /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);
}
|