]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/cpuid.c
12287024253d0af5b538b4882715d54ad4e39713
[plan9front.git] / sys / src / cmd / aux / cpuid.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #define CUT(x, a, b) (((x)&((1<<((b)+1))-1))>>(a))
6
7 typedef struct Res {
8         ulong ax, bx, cx, dx;
9 } Res;
10
11 Biobuf *out;
12
13 uchar _cpuid[] = {
14         0x5E,                   /* POP SI (PC) */
15         0x5D,                   /* POP BP (Res&) */
16         0x58,                   /* POP AX */
17         0x59,                   /* POP CX */
18
19         0x51,                   /* PUSH CX */
20         0x50,                   /* PUSH AX */
21         0x55,                   /* PUSH BP */
22         0x56,                   /* PUSH SI */
23
24         0x31, 0xDB,             /* XOR BX, BX */
25         0x31, 0xD2,             /* XOR DX, DX */
26
27         0x0F, 0xA2,             /* CPUID */
28
29         0x89, 0x45, 0x00,       /* MOV AX, 0(BP) */
30         0x89, 0x5d, 0x04,       /* MOV BX, 4(BP) */
31         0x89, 0x4d, 0x08,       /* MOV CX, 8(BP) */
32         0x89, 0x55, 0x0C,       /* MOV DX, 12(BP) */
33         0xC3,                   /* RET */
34 };
35
36 Res (*cpuid)(ulong ax, ulong cx) = (Res(*)(ulong, ulong)) _cpuid;
37
38 void
39 func0(ulong)
40 {
41         Res r;
42         char buf[13];
43
44         r = cpuid(0, 0);
45         ((ulong *) buf)[0] = r.bx;
46         ((ulong *) buf)[1] = r.dx;
47         ((ulong *) buf)[2] = r.cx;
48         buf[13] = 0;
49         Bprint(out, "vendor %s\n", buf);
50 }
51
52 void
53 printbits(char *id, ulong x, char **s)
54 {
55         int i, j;
56
57         for(i = 0, j = 0; i < 32; i++)
58                 if((x & (1<<i)) != 0 && s[i] != nil){
59                         if(j++ % 16 == 0){
60                                 if(j != 1)
61                                         Bprint(out, "\n");
62                                 Bprint(out, "%s ", id);
63                         }
64                         Bprint(out, "%s ", s[i]);
65                 }
66         if(j % 16 != 0)
67                 Bprint(out, "\n");
68 }
69
70 void
71 func1(ulong)
72 {
73         Res r;
74         int family, model;
75         static char *bitsdx[32] = {
76                 [0]             "fpu",  "vme",   "de",   "pse",
77                 [4]             "tsc",  "msr",   "pae",  "mce",
78                 [8]             "cx8",  "apic",  nil,    "sep",
79                 [12]    "mtrr", "pge",   "mca",  "cmov",
80                 [16]    "pat",  "pse36", "pn",   "clflush",
81                 [20]    nil,    "dts",   "acpi", "mmx",
82                 [24]    "fxsr", "sse",   "sse2", "ss",
83                 [28]    "ht",   "tm",    "ia64", "pbe",
84         };
85         static char *bitscx[32] = {
86                 [0]             "pni",         "pclmulqdq", "dtes64", "monitor",
87                 [4]             "ds_cpl",      "vmx",       "smx",    "est",
88                 [8]             "tm2",         "ssse3",     "cid",    nil,
89                 [12]    "fma",         "cx16",      "xtpr",   "pdcm",
90                 [16]    nil,           "pcid",      "dca",    "sse4_1",
91                 [20]    "sse4_2",      "x2apic",    "movbe",  "popcnt",
92                 [24]    "tscdeadline", "aes",       "xsave",  "osxsave",
93                 [28]    "avx",         "f16c",      "rdrnd",  "hypervisor",
94         };
95
96         r = cpuid(1, 0);
97         Bprint(out, "procmodel %.8ulx / %.8ulx\n", r.ax, r.bx);
98         family = r.ax >> 8 & 0xf;
99         model = r.ax >> 8 & 0xf;
100         if(family == 15)
101                 family += r.ax >> 20 & 0xff;
102         if(family == 6 || family == 15)
103                 model += r.ax >> 12 & 0xf0;
104         Bprint(out, "typefammod %.1x %.2x %.3x %.1x\n", (int)(r.ax >> 12 & 3), family, model, (int)(r.ax & 0xf));
105         printbits("features", r.dx, bitsdx);
106         printbits("features", r.cx, bitscx);
107 }
108
109 void
110 func13(ulong)
111 {
112         Res r;
113         static char *bitsax[32] = {
114                 [0]     "xsaveopt",
115         };
116
117         r = cpuid(13, 1);
118         printbits("features", r.ax, bitsax);
119 }
120
121 void
122 extfunc1(ulong ax)
123 {
124         Res r;
125         static char *bitsdx[32] = {
126                 [0]             "fpu",  "vme",   "de",      "pse",
127                 [4]             "tsc",  "msr",   "pae",     "mce",
128                 [8]             "cx8",  "apic",  nil,       "syscall",
129                 [12]    "mtrr", "pge",   "mca",     "cmov",
130                 [16]    "pat",  "pse36", nil,       "mp",
131                 [20]    "nx",   nil,     "mmx+",    "mmx",
132                 [24]    "fxsr", "ffxsr", "pg1g",    "tscp",
133                 [28]    nil,    "lm",    "3dnow!+", "3dnow!",
134         };
135         static char *bitscx[32] = {
136                 [0]             "ahf64",   "cmp",   "svm",   "eas",
137                 [4]             "cr8d",    "lzcnt", "sse4a", "msse",
138                 [8]             "3dnow!p", "osvw",  "ibs",   "xop",
139                 [12]    "skinit",  "wdt",   nil,     "lwp",
140                 [16]    "fma4",    "tce",   nil,     "nodeid",
141                 [20]    nil,       "tbm",   "topx",  "pcx_core",
142                 [24]    "pcx_nb",  nil,     nil,     nil,
143                 [28]    nil,       nil,     nil,     nil,
144         };
145
146         r = cpuid(ax, 0);
147         Bprint(out, "extmodel %.8ulx / %.8ulx\n", r.ax, r.bx);
148         printbits("extfeatures", r.dx, bitsdx);
149         printbits("extfeatures", r.cx, bitscx);
150 }
151
152 void
153 extfunc2(ulong ax)
154 {
155         char buf[49];
156         int i;
157         Res r;
158         char *p;
159
160         if(ax != 0x80000004)
161                 return;
162         buf[48] = 0;
163         for(i = 0; i < 3; i++){
164                 r = cpuid(0x80000002 + i, 0);
165                 ((ulong *) buf)[4 * i + 0] = r.ax;
166                 ((ulong *) buf)[4 * i + 1] = r.bx;
167                 ((ulong *) buf)[4 * i + 2] = r.cx;
168                 ((ulong *) buf)[4 * i + 3] = r.dx;
169         }
170         p = buf;
171         while(*p == ' ')
172                 p++;
173         Bprint(out, "procname %s\n", p);
174 }
175
176 void
177 extfunc8(ulong ax)
178 {
179         Res r;
180
181         r = cpuid(ax, 0);
182         Bprint(out, "physbits %uld\n", CUT(r.ax, 0, 7));
183         Bprint(out, "virtbits %uld\n", CUT(r.ax, 8, 15));
184         if(CUT(r.ax, 16, 23) != 0)
185                 Bprint(out, "guestbits %uld\n", CUT(r.ax, 16, 23));
186 }
187
188 void (*funcs[])(ulong) = {
189         [0]     func0,
190         [1]     func1,
191         [13]    func13,
192 };
193
194 void (*extfuncs[])(ulong) = {
195         [1] extfunc1,
196         [2] extfunc2,
197         [3] extfunc2,
198         [4] extfunc2,
199         [8] extfunc8,
200 };
201
202 void
203 stdfunc(ulong ax)
204 {
205         Res r;
206
207         r = cpuid(ax, 0);
208         Bprint(out, "%.8ulx %.8ulx %.8ulx %.8ulx %.8ulx\n", ax, r.ax, r.bx, r.cx, r.dx);
209 }
210
211 char Egreg[] = "this information is classified";
212
213 void
214 notehand(void *, char *s)
215 {
216         if(strncmp(s, "sys:", 4) == 0)
217                 sysfatal(Egreg);
218         noted(NDFLT);
219 }
220
221 void
222 main(int argc, char **argv)
223 {
224         Res r;
225         int i, rflag, aflag;
226         ulong w;
227         static Biobuf buf;
228
229         rflag = aflag = 0;
230         ARGBEGIN {
231         case 'r': rflag++; break;
232         case 'a': aflag++; break;
233         } ARGEND;
234         notify(notehand);
235         /* first long in a.out header */
236         w = *(ulong *)(((uintptr)main)&~0xfff);
237         notify(nil);
238         switch(w){
239         default:
240                 sysfatal(Egreg);
241         case 0x978a0000:        /* amd64 */
242                 /* patch out POP BP -> POP AX */
243                 _cpuid[1] = 0x58;
244         case 0xeb010000:        /* 386 */
245                 break;
246         }
247         Binit(&buf, 1, OWRITE);
248         out = &buf;
249         r = cpuid(0, 0);
250         for(i = 0; i <= r.ax; i++)
251                 if(i >= nelem(funcs) || funcs[i] == nil || rflag){
252                         if(rflag || aflag)
253                                 stdfunc(i);
254                 }else
255                         funcs[i](i);
256         r = cpuid(0x80000000, 0);
257         if(r.ax < 0x80000000)
258                 exits(nil);
259         r.ax -= 0x80000000;
260         for(i = 0; i <= r.ax; i++)
261                 if(i >= nelem(extfuncs) || extfuncs[i] == nil || rflag){
262                         if(rflag || aflag)
263                                 stdfunc(0x80000000 | i);
264                 }else
265                         extfuncs[i](0x80000000 | i);
266         exits(nil);
267 }