--- /n/sources/plan9/sys/src/cmd/aux/mkfile Thu Aug 16 22:50:45 2012 +++ /sys/src/cmd/aux/mkfile Fri Jul 12 00:00:00 2013 @@ -49,6 +49,7 @@ +#include + +#define X86STEPPING(x) ((x) & 0x0F) +#define X86MODEL(x) ((x)>>4 & 0xf | (x)>>12 & 0xf0) +#define X86FAMILY(x) ((x)>>8 & 0xf | (x)>>16 & 0xf0) + +enum { + Highstdfunc = 0x0, /* also returns vendor string */ + Procsig, + Proctlbcache, + Procserial, + X2apic = 0xb, + + /* Procsig.cx; doesn't work */ + Hasx2apic = 1<<21, +}; + +typedef struct Cpuidreg Cpuidreg; + +struct Cpuidreg { + u32int ax; + u32int bx; + u32int cx; + u32int dx; +}; + +void cpuid1(Cpuidreg*); + +char *fn1dx[32*2] = { +/* 0 */ "fpu", "onboard x87", +/* 1 */ "vme", "virtual mode extensions", +/* 2 */ "de", "debugging extensions", +/* 3 */ "pse", "page size extensions", +/* 4 */ "tsc", "time stamp counter", +/* 5 */ "msr", "model-specific registers", +/* 6 */ "pae", "physical address extension", +/* 7 */ "mce", "machine check exception", +/* 8 */ "cx8", "CMPXCHGQ", +/* 9 */ "apic", "onboard apic", +/* 10 */ "--", "reserved", +/* 11 */ "sep", "SYSENTER", +/* 12 */ "mtrr", "memory type range registers", +/* 13 */ "pge", "cr4 page global enable", +/* 14 */ "mca", "machine check architecture", +/* 15 */ "cmov", "conditional move", +/* 16 */ "pat", "page attribute table", +/* 17 */ "pse36", "36-bit huge pages", +/* 18 */ "pn", "processor serial#", +/* 19 */ "clflush", "CLFLUSH", +/* 20 */ "--", "reserved", +/* 21 */ "dts", "debug store", +/* 22 */ "acpi", "onboard acpi thermal msrs", +/* 23 */ "mmx", "mmx", +/* 24 */ "fxsr", "FXSAVE", +/* 25 */ "sse", "SSE", +/* 26 */ "sse2", "SSE2", +/* 27 */ "ss", "self-snoop", +/* 28 */ "htt", "hyperthreading", +/* 29 */ "tm", "automatic thermal throttle", +/* 30 */ "ia64", "itanium emulating x86", +/* 31 */ "pbe", "pending break enable", +}; + +char *fn1cx[32*2] = { +/* 0 */ "sse3", "SSE3", +/* 1 */ "pclmulqdq", "carryless multiplication", +/* 2 */ "dtes64", "64-bit debug store", +/* 3 */ "mon", "MONITOR", +/* 4 */ "dscpl", "CPL qualified debug store", +/* 5 */ "vmx", "virtual machine extensions", +/* 6 */ "smx", "safer mode extensions", +/* 7 */ "est", "enhanced speedstep", +/* 8 */ "tm2", "thermal monitor 2", +/* 9 */ "ssse3", "supplemntal SSE3", +/* 10 */ "cid", "context id", +/* 11 */ "--", "reserved", +/* 12 */ "fma", "fused multiply-add", +/* 13 */ "cx16", "CMPXCHGO", +/* 14 */ "xtpr", "xtpr update control", +/* 15 */ "pdcm", "perfmon and debug", +/* 16 */ "--", "reserved", +/* 17 */ "pcid", "process context identifiers", +/* 18 */ "dca", "direct cache access dma write", +/* 19 */ "sse41", "SSE 4.1", +/* 20 */ "sse42", "SSE 4.2", +/* 21 */ "x2apic", "x2apic", +/* 22 */ "movbe", "atom(tm) big-endian mov", +/* 23 */ "popcnt", "POPCNT", +/* 24 */ "tscdead", "tsc deadline", +/* 25 */ "aes", "AES", +/* 26 */ "xsave", "XSAVE", +/* 27 */ "osxsave", "os-enabled XSAVE", +/* 28 */ "avx", "advanced vector etensions", +/* 29 */ "f16", "half-precision fp", +/* 30 */ "rdrnd", "RDRAND", +/* 31 */ "hyp", "running on hypervisor", +}; + +char *fn80000001dx[32*2] = { +/* 0 */ "--", "reserved", +/* 1 */ "--", "reserved", +/* 2 */ "--", "reserved", +/* 3 */ "--", "reserved", +/* 4 */ "--", "reserved", +/* 5 */ "--", "reserved", +/* 6 */ "--", "reserved", +/* 7 */ "--", "reserved", +/* 8 */ "--", "reserved", +/* 9 */ "--", "reserved", +/* 10 */ "--", "reserved", +/* 11 */ "syscall", "syscall instruction", +/* 12 */ "--", "reserved", +/* 13 */ "--", "reserved", +/* 14 */ "--", "reserved", +/* 15 */ "--", "reserved", +/* 16 */ "--", "reserved", +/* 17 */ "--", "reserved", +/* 18 */ "--", "reserved", +/* 19 */ "--", "reserved", +/* 20 */ "nox", "execute disable", +/* 21 */ "--", "reserved", +/* 22 */ "--", "reserved", +/* 23 */ "--", "reserved", +/* 24 */ "--", "reserved", +/* 25 */ "--", "reserved", +/* 26 */ "gb", "1gb pages", +/* 27 */ "rdtscp", "RDTSCP supported", +/* 28 */ "--", "reserved", +/* 29 */ "amd64", "64-bit long mode supported", +/* 30 */ "--", "reserved", +/* 31 */ "--", "reserved", +}; + +char *intel80000001cx[32*2] = { +/* 0 */ "lahf64", "LAHF in 64-bit mode", +/* 1 */ "--", "reserved", +/* 2 */ "--", "reserved", +/* 3 */ "--", "reserved", +/* 4 */ "--", "reserved", +/* 5 */ "--", "reserved", +/* 6 */ "--", "reserved", +/* 7 */ "--", "reserved", +/* 8 */ "--", "reserved", +/* 9 */ "--", "reserved", +/* 10 */ "--", "reserved", +/* 11 */ "--", "reserved", +/* 12 */ "--", "reserved", +/* 13 */ "--", "reserved", +/* 14 */ "--", "reserved", +/* 15 */ "--", "reserved", +/* 16 */ "--", "reserved", +/* 17 */ "--", "reserved", +/* 18 */ "--", "reserved", +/* 19 */ "--", "reserved", +/* 20 */ "--", "reserved", +/* 21 */ "--", "reserved", +/* 22 */ "--", "reserved", +/* 23 */ "--", "reserved", +/* 24 */ "--", "reserved", +/* 25 */ "--", "reserved", +/* 26 */ "--", "reserved", +/* 27 */ "--", "reserved", +/* 28 */ "--", "reserved", +/* 29 */ "--", "reserved", +/* 30 */ "--", "reserved", +/* 31 */ "--", "reserved", +}; + +char *amd80000001cx[32*2] = { +/* 0 */ "lahf64", "LAHF in 64-bit mode", +/* 1 */ "legacymp", "legacy multicpre", +/* 2 */ "svm", "secure virtual machine", +/* 3 */ "xapic", "extended apic register", +/* 4 */ "altmovcr8", "lock mov cr0 means mov cr8", +/* 5 */ "abm", "advanced bit maniupation", +/* 6 */ "sse4a", "sse4a support", +/* 7 */ "misalignsse", "misaligned sse mode", +/* 8 */ "3dnowpref", "prefetch(w) support", +/* 9 */ "osvw", "os-visible workaround (apm)", +/* 10 */ "ibs", "instruction-based sampling", +/* 11 */ "xop", "extended operation support (apm6)", +/* 12 */ "skinit", "skinit support", +/* 13 */ "wdt", "watchdog timer support", +/* 14 */ "--", "reserved", +/* 15 */ "lwp", "lightweight profiling support", +/* 16 */ "fma4", "4-op fma", +/* 17 */ "--", "reserved", +/* 18 */ "--", "reserved", +/* 19 */ "nodeid", "support for msrc001_001c", +/* 20 */ "--", "reserved", +/* 21 */ "tbm", "trailing-bit manipulation", +/* 22 */ "--", "reserved", +/* 23 */ "--", "reserved", +/* 24 */ "--", "reserved", +/* 25 */ "--", "reserved", +/* 26 */ "--", "reserved", +/* 27 */ "--", "reserved", +/* 28 */ "--", "reserved", +/* 29 */ "--", "reserved", +/* 30 */ "--", "reserved", +/* 31 */ "--", "reserved", +}; + +void +decodetab(char *tab[32*2], uint r, int verbose) +{ + char buf[1024], *p, *e, *fmt; + int i; + + fmt = "%s "; + if(verbose) + fmt = "\n\t%s"; + e = buf + sizeof buf; + p = buf; + for(i = 0; i < 32; i++) + if(r & 1<> 8; + p = seprint(p, e, "clsize=%d ", i*8); + i = (r & 0xff0000) >> 16; + p = seprint(p, e, "maxapicid=%d ", i); + i = (r & 0xff000000) >> 24; + seprint(p, e, "initialapicid=%d ", i); + + print("%s\n", buf); +} + +void +checkwired(int mach) +{ + char buf[128]; + int fd; + + for(;;){ + sleep(1); + fd = open("/dev/mach", OREAD); + if(fd == -1) + /* old kernel; just hope */ + return; + buf[0] = ' '; + buf[read(fd, buf, sizeof buf)] = 0; + close(fd); + if(atoi(buf) == mach) + return; + sysfatal("wire fails"); + } +} + +void +procwired(int mach) +{ + char buf[128]; + int fd; + + snprint(buf, sizeof buf, "/proc/%d/ctl", getpid()); + fd = open(buf, OWRITE); + if(fprint(fd, "wired %d", mach) < 0) + sysfatal("procwired: %r"); + close(fd); + checkwired(mach); /* don't trust kernel yet */ +} + +int +sysmach(void) +{ + char buf[8192], *p; + int n, fd; + + fd = open("/dev/sysstat", OREAD); + if(fd == -1) + sysfatal("open: %r"); + n = read(fd, buf, sizeof buf); + if(n == -1) + sysfatal("read: %r"); + close(fd); + buf[n] = 0; + p = buf; + for(n = 0;; n++){ + if((p = strchr(p, '\n')) == nil) + return n; + p++; + } +} + +char* +append(char *s, uint r) +{ + memmove(s, &r, 4); + return s+4; +} + +char* +vendorstring(char *buf) +{ + char *p; + Cpuidreg r; + + memset(&r, 0, sizeof r); + r.ax = Highstdfunc; + cpuid1(&r); + p = buf; + p = append(p, r.bx); + p = append(p, r.dx); + p = append(p, r.cx); + *p = 0; + return buf; +} + +int +isamd(void) +{ + char buf[16]; + + return strcmp(vendorstring(buf), "AuthenticAMD") == 0; +} + +void +usage(void) +{ + fprint(2, "usage: cpuid [-w mach] [-efisvt] [-n fn]\n"); + exits("usage"); +} + +char *tab[] = {"ax", "bx", "cx", "dx", }; +int +strtoidx(char *s) +{ + int i; + + for(i = 0; i < nelem(tab); i++) + if(cistrncmp(s, tab[i], 2) == 0) + return i; + usage(); + return -1; +} + +void +strtofn(char *s, Cpuidreg *r) +{ + char *p; + uint *u, i, v; + + memset(r, 0, sizeof *r); + u = (uint*)r; + for(i = 0; i < 4; i++){ + if(strchr(s, '=') - s == 2){ + i = strtoidx(s); + s += 3; + } + v = strtoul(s, &p, 0); + u[i] = v; + if(*p == 0) + break; + s = p+1; + } +} + +void +main(int argc, char **argv) +{ + char flag[32], buf[64], *p; + uint mach[256], apic[256]; + int i, j, k, nmach, smach, nflag; + Cpuidreg r, fn[32]; + + nflag = 0; + memset(mach, 0xff, sizeof mach); + memset(fn, 0, sizeof fn); + ARGBEGIN{ + case 'n': + strtofn(EARGF(usage()), fn + nflag); + case 'c': + case 'e': + case 'f': + case 'i': + case 's': + case 'v': + case 't': + if(nflag == nelem(flag)) + sysfatal("too many flags"); + flag[nflag++] = ARGC(); + break; + case 'w': + mach[nflag] = strtoul(EARGF(usage()), 0, 0); + break; + default: + usage(); + }ARGEND + if(argc != 0) + usage(); + if(nflag == 0) + flag[nflag++] = 's'; + for(j = 0; j < nflag; j++){ + memset(&r, 0, sizeof r); + if(mach[j] != ~0) + procwired(mach[j]); + switch(flag[j]){ + case 'n': + r = fn[j]; + cpuid1(&r); + print("%.8ux %.8ux %.8ux %.8ux\n", + r.ax, r.bx, r.cx, r.dx); + break; + case 'c': + memset(&r, 0, sizeof r); + r.ax = 1; + cpuid1(&r); + print("bx\t"); + fn1bx(r.bx, 0); + break; + case 'e': + memset(&r, 0, sizeof r); + r.ax = 0x80000001; + cpuid1(&r); + print("dx\t"); + decodetab(fn80000001dx, r.dx, 0); + print("cx\t"); + if(isamd()) + decodetab(amd80000001cx, r.cx, 0); + else + decodetab(intel80000001cx, r.cx, 0); + break; + case 'f': + memset(&r, 0, sizeof r); + r.ax = 1; + cpuid1(&r); + print("dx\t"); + decodetab(fn1dx, r.dx, 0); + print("cx\t"); + decodetab(fn1cx, r.cx, 0); + break; + case 'i': + p = buf; + for(i = 0; i < 3; i++){ + memset(&r, 0, sizeof r); + r.ax = 0x80000002+i; + cpuid1(&r); + p = append(p, r.ax); + p = append(p, r.bx); + p = append(p, r.cx); + p = append(p, r.dx); + } + *p = 0; + print("%s\n", buf); + break; + case 's': + r.ax = Procsig; + cpuid1(&r); + print("%.8ux %.2ux.%.2ux.%.2ux\n", + r.ax, X86FAMILY(r.ax), X86MODEL(r.ax), + X86STEPPING(r.ax)); + break; + case 'v': + print("%s\n", vendorstring(buf)); + break; + case 't': + procwired(0); + nmach = 1; + for(i = 0;; i++){ + memset(&r, 0, sizeof r); + r.ax = X2apic; + r.cx = i; + cpuid1(&r); + if((r.cx & 0xff00) == 0) + goto inval; + switch(i){ + case 0: + snprint(buf, sizeof buf, "thread"); + break; + case 1: + nmach = r.bx & 0xffff; + snprint(buf, sizeof buf, "core"); + break; + case 2: + snprint(buf, sizeof buf, "pkg"); + break; + default: + snprint(buf, sizeof buf, "clust%d", i-3); + break; + } + print("%s\t%.8ux %.8ux %.8ux %.8ux\n", + buf, r.ax, r.bx, r.cx, r.dx); + inval: + if((r.ax == 0 || i == 0) && r.bx == 0) + break; + } + smach = sysmach(); + if(smach%nmach == 0) + nmach = smach; + for(i = 0; i < nmach; i++){ + procwired(i); + apic[i] = -1; + memset(&r, 0, sizeof r); + r.ax = X2apic; + r.cx = 1; + cpuid1(&r); + if((r.cx & 0xff00) == 0) + continue; + apic[i] = r.dx; + for(k = 0; k < i; k++) + if(apic[k] == apic[i]) + goto dup; + print("mach%d\tapic %.8ux\n", i, apic[i]); + } + dup: + if(i != nmach) + print("%d machs inactive\n", nmach - i); + break; + } + } + exits(""); +} diff -Nru /sys/src/cmd/aux/cpuid/mkfile /sys/src/cmd/aux/cpuid/mkfile --- /sys/src/cmd/aux/cpuid/mkfile Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/aux/cpuid/mkfile Fri Sep 16 00:00:00 2011 @@ -0,0 +1,9 @@ +