312 lines
7.1 KiB
C
312 lines
7.1 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <bio.h>
|
|
|
|
#define CUT(x, a, b) (((x)&((1<<((b)+1))-1))>>(a))
|
|
|
|
typedef struct Res {
|
|
ulong ax, bx, cx, dx;
|
|
} Res;
|
|
|
|
Biobuf *out;
|
|
|
|
uchar _cpuid[] = {
|
|
0x5E, /* POP SI (PC) */
|
|
0x5D, /* POP BP (Res&) */
|
|
0x58, /* POP AX */
|
|
0x59, /* POP CX */
|
|
|
|
0x51, /* PUSH CX */
|
|
0x50, /* PUSH AX */
|
|
0x55, /* PUSH BP */
|
|
0x56, /* PUSH SI */
|
|
|
|
0x31, 0xDB, /* XOR BX, BX */
|
|
0x31, 0xD2, /* XOR DX, DX */
|
|
|
|
0x0F, 0xA2, /* CPUID */
|
|
|
|
0x89, 0x45, 0x00, /* MOV AX, 0(BP) */
|
|
0x89, 0x5d, 0x04, /* MOV BX, 4(BP) */
|
|
0x89, 0x4d, 0x08, /* MOV CX, 8(BP) */
|
|
0x89, 0x55, 0x0C, /* MOV DX, 12(BP) */
|
|
0xC3, /* RET */
|
|
};
|
|
|
|
Res (*cpuid)(ulong ax, ulong cx) = (Res(*)(ulong, ulong)) _cpuid;
|
|
|
|
void
|
|
func0(ulong)
|
|
{
|
|
Res r;
|
|
char buf[13];
|
|
|
|
r = cpuid(0, 0);
|
|
((ulong *) buf)[0] = r.bx;
|
|
((ulong *) buf)[1] = r.dx;
|
|
((ulong *) buf)[2] = r.cx;
|
|
buf[12] = 0;
|
|
Bprint(out, "vendor %s\n", buf);
|
|
}
|
|
|
|
void
|
|
printbits(char *id, ulong x, char **s)
|
|
{
|
|
int i, j;
|
|
|
|
for(i = 0, j = 0; i < 32; i++)
|
|
if((x & (1<<i)) != 0 && s[i] != nil){
|
|
if(j++ % 16 == 0){
|
|
if(j != 1)
|
|
Bprint(out, "\n");
|
|
Bprint(out, "%s ", id);
|
|
}
|
|
Bprint(out, "%s ", s[i]);
|
|
}
|
|
if(j != 0)
|
|
Bprint(out, "\n");
|
|
}
|
|
|
|
void
|
|
func1(ulong)
|
|
{
|
|
Res r;
|
|
int family, model;
|
|
static char *bitsdx[32] = {
|
|
[0] "fpu", "vme", "de", "pse",
|
|
[4] "tsc", "msr", "pae", "mce",
|
|
[8] "cx8", "apic", nil, "sep",
|
|
[12] "mtrr", "pge", "mca", "cmov",
|
|
[16] "pat", "pse36", "pn", "clflush",
|
|
[20] nil, "dts", "acpi", "mmx",
|
|
[24] "fxsr", "sse", "sse2", "ss",
|
|
[28] "ht", "tm", "ia64", "pbe",
|
|
};
|
|
static char *bitscx[32] = {
|
|
[0] "pni", "pclmulqdq", "dtes64", "monitor",
|
|
[4] "ds_cpl", "vmx", "smx", "est",
|
|
[8] "tm2", "ssse3", "cid", nil,
|
|
[12] "fma", "cx16", "xtpr", "pdcm",
|
|
[16] nil, "pcid", "dca", "sse4_1",
|
|
[20] "sse4_2", "x2apic", "movbe", "popcnt",
|
|
[24] "tscdeadline", "aes", "xsave", "osxsave",
|
|
[28] "avx", "f16c", "rdrnd", "hypervisor",
|
|
};
|
|
|
|
r = cpuid(1, 0);
|
|
Bprint(out, "procmodel %.8ulx / %.8ulx\n", r.ax, r.bx);
|
|
family = r.ax >> 8 & 0xf;
|
|
model = r.ax >> 8 & 0xf;
|
|
if(family == 15)
|
|
family += r.ax >> 20 & 0xff;
|
|
if(family == 6 || family == 15)
|
|
model += r.ax >> 12 & 0xf0;
|
|
Bprint(out, "typefammod %.1x %.2x %.3x %.1x\n", (int)(r.ax >> 12 & 3), family, model, (int)(r.ax & 0xf));
|
|
printbits("features", r.dx, bitsdx);
|
|
printbits("features", r.cx, bitscx);
|
|
}
|
|
|
|
void
|
|
func7(ulong)
|
|
{
|
|
Res r;
|
|
static char *bitebx[32] = {
|
|
[0] "fsgsbase", nil, "sgx", "bmi1",
|
|
[4] "hle", "avx2", nil, "smep",
|
|
[8] "bmi2", "erms", "invpcid", "rtm",
|
|
[12] "pqm", nil, "mpx", "pqe",
|
|
[16] "avx512", "avx512dq", "rdseed", "adx",
|
|
[20] "smap", "avx512ifma", "pcommit", "clflushopt",
|
|
[24] "clwb", "intelpt", "avx512pf", "avx512er",
|
|
[28] "avx512cd", "sha", "avx512bw", "avx512vl",
|
|
};
|
|
static char *bitecx[32] = {
|
|
[0] "prefetchwt1", "avx512vbmi", "umip", "pku",
|
|
[4] "ospke", "waitpkg", "avx512vbmi2", "cetss",
|
|
[8] "gfni", "vaes", "vpclmulqdq", "avx512vnni",
|
|
[12] "avx512bitalg", nil, "avx512vpopcntdq", nil,
|
|
[16] nil, nil, nil, nil,
|
|
[20] nil, nil, "rdpid", nil,
|
|
[24] nil, "cldemote", nil, "movdiri",
|
|
[28] "movdir64b", "enqcmd", "sgxlc", "pks",
|
|
};
|
|
static char *bitedx[32] = {
|
|
[0] nil, nil, "avx512vnniw4", "avx512fmaps4",
|
|
[4] "fsrm", nil, nil, nil,
|
|
[8] "avx512vp2i", nil, nil, nil,
|
|
};
|
|
static char *biteax[32] = {
|
|
[0] nil, nil, nil, nil,
|
|
[4] nil, "avx512bf16", nil, nil,
|
|
};
|
|
|
|
r = cpuid(7, 0);
|
|
printbits("features", r.bx, bitebx);
|
|
printbits("features", r.cx, bitecx);
|
|
printbits("features", r.dx, bitedx);
|
|
r = cpuid(7, 1);
|
|
printbits("features", r.ax, biteax);
|
|
}
|
|
|
|
void
|
|
func13(ulong)
|
|
{
|
|
Res r;
|
|
static char *bitsax[32] = {
|
|
[0] "xsaveopt", "xsavec", "xgetbv1", "xsaves",
|
|
};
|
|
|
|
r = cpuid(13, 1);
|
|
printbits("features", r.ax, bitsax);
|
|
}
|
|
|
|
void
|
|
extfunc1(ulong ax)
|
|
{
|
|
Res r;
|
|
static char *bitsdx[32] = {
|
|
[0] "fpu", "vme", "de", "pse",
|
|
[4] "tsc", "msr", "pae", "mce",
|
|
[8] "cx8", "apic", nil, "syscall",
|
|
[12] "mtrr", "pge", "mca", "cmov",
|
|
[16] "pat", "pse36", nil, "mp",
|
|
[20] "nx", nil, "mmx+", "mmx",
|
|
[24] "fxsr", "ffxsr", "pg1g", "tscp",
|
|
[28] nil, "lm", "3dnow!+", "3dnow!",
|
|
};
|
|
static char *bitscx[32] = {
|
|
[0] "ahf64", "cmp", "svm", "eas",
|
|
[4] "cr8d", "lzcnt", "sse4a", "msse",
|
|
[8] "3dnow!p", "osvw", "ibs", "xop",
|
|
[12] "skinit", "wdt", nil, "lwp",
|
|
[16] "fma4", "tce", nil, "nodeid",
|
|
[20] nil, "tbm", "topx", "pcx_core",
|
|
[24] "pcx_nb", nil, nil, nil,
|
|
[28] nil, nil, nil, nil,
|
|
};
|
|
|
|
r = cpuid(ax, 0);
|
|
Bprint(out, "extmodel %.8ulx / %.8ulx\n", r.ax, r.bx);
|
|
printbits("extfeatures", r.dx, bitsdx);
|
|
printbits("extfeatures", r.cx, bitscx);
|
|
}
|
|
|
|
void
|
|
extfunc2(ulong ax)
|
|
{
|
|
char buf[49];
|
|
int i;
|
|
Res r;
|
|
char *p;
|
|
|
|
if(ax != 0x80000004)
|
|
return;
|
|
buf[48] = 0;
|
|
for(i = 0; i < 3; i++){
|
|
r = cpuid(0x80000002 + i, 0);
|
|
((ulong *) buf)[4 * i + 0] = r.ax;
|
|
((ulong *) buf)[4 * i + 1] = r.bx;
|
|
((ulong *) buf)[4 * i + 2] = r.cx;
|
|
((ulong *) buf)[4 * i + 3] = r.dx;
|
|
}
|
|
p = buf;
|
|
while(*p == ' ')
|
|
p++;
|
|
Bprint(out, "procname %s\n", p);
|
|
}
|
|
|
|
void
|
|
extfunc8(ulong ax)
|
|
{
|
|
Res r;
|
|
|
|
r = cpuid(ax, 0);
|
|
Bprint(out, "physbits %uld\n", CUT(r.ax, 0, 7));
|
|
Bprint(out, "virtbits %uld\n", CUT(r.ax, 8, 15));
|
|
if(CUT(r.ax, 16, 23) != 0)
|
|
Bprint(out, "guestbits %uld\n", CUT(r.ax, 16, 23));
|
|
}
|
|
|
|
void (*funcs[])(ulong) = {
|
|
[0] func0,
|
|
[1] func1,
|
|
[7] func7,
|
|
[13] func13,
|
|
};
|
|
|
|
void (*extfuncs[])(ulong) = {
|
|
[1] extfunc1,
|
|
[2] extfunc2,
|
|
[3] extfunc2,
|
|
[4] extfunc2,
|
|
[8] extfunc8,
|
|
};
|
|
|
|
void
|
|
stdfunc(ulong ax)
|
|
{
|
|
Res r;
|
|
|
|
r = cpuid(ax, 0);
|
|
Bprint(out, "%.8ulx %.8ulx %.8ulx %.8ulx %.8ulx\n", ax, r.ax, r.bx, r.cx, r.dx);
|
|
}
|
|
|
|
char Egreg[] = "this information is classified";
|
|
|
|
void
|
|
notehand(void *, char *s)
|
|
{
|
|
if(strncmp(s, "sys:", 4) == 0)
|
|
sysfatal(Egreg);
|
|
noted(NDFLT);
|
|
}
|
|
|
|
void
|
|
main(int argc, char **argv)
|
|
{
|
|
Res r;
|
|
int i, rflag, aflag;
|
|
ulong w;
|
|
static Biobuf buf;
|
|
|
|
rflag = aflag = 0;
|
|
ARGBEGIN {
|
|
case 'r': rflag++; break;
|
|
case 'a': aflag++; break;
|
|
} ARGEND;
|
|
notify(notehand);
|
|
/* first long in a.out header */
|
|
w = *(ulong *)(((uintptr)main)&~0xfff);
|
|
notify(nil);
|
|
switch(w){
|
|
default:
|
|
sysfatal(Egreg);
|
|
case 0x978a0000: /* amd64 */
|
|
/* patch out POP BP -> POP AX */
|
|
_cpuid[1] = 0x58;
|
|
case 0xeb010000: /* 386 */
|
|
break;
|
|
}
|
|
segflush(_cpuid, sizeof(_cpuid));
|
|
Binit(&buf, 1, OWRITE);
|
|
out = &buf;
|
|
r = cpuid(0, 0);
|
|
for(i = 0; i <= r.ax; i++)
|
|
if(i >= nelem(funcs) || funcs[i] == nil || rflag){
|
|
if(rflag || aflag)
|
|
stdfunc(i);
|
|
}else
|
|
funcs[i](i);
|
|
r = cpuid(0x80000000, 0);
|
|
if(r.ax < 0x80000000)
|
|
exits(nil);
|
|
r.ax -= 0x80000000;
|
|
for(i = 0; i <= r.ax; i++)
|
|
if(i >= nelem(extfuncs) || extfuncs[i] == nil || rflag){
|
|
if(rflag || aflag)
|
|
stdfunc(0x80000000 | i);
|
|
}else
|
|
extfuncs[i](0x80000000 | i);
|
|
exits(nil);
|
|
}
|