1*2b54f0dbSXin Li #include <stdio.h>
2*2b54f0dbSXin Li #include <stdint.h>
3*2b54f0dbSXin Li #include <inttypes.h>
4*2b54f0dbSXin Li #include <string.h>
5*2b54f0dbSXin Li
6*2b54f0dbSXin Li #include <x86/cpuid.h>
7*2b54f0dbSXin Li
print_cpuid(struct cpuid_regs regs,uint32_t eax)8*2b54f0dbSXin Li static void print_cpuid(struct cpuid_regs regs, uint32_t eax) {
9*2b54f0dbSXin Li printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32"\n",
10*2b54f0dbSXin Li eax, regs.eax, regs.ebx, regs.ecx, regs.edx);
11*2b54f0dbSXin Li }
12*2b54f0dbSXin Li
print_cpuidex(struct cpuid_regs regs,uint32_t eax,uint32_t ecx)13*2b54f0dbSXin Li static void print_cpuidex(struct cpuid_regs regs, uint32_t eax, uint32_t ecx) {
14*2b54f0dbSXin Li printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [SL %02"PRIX32"]\n",
15*2b54f0dbSXin Li eax, regs.eax, regs.ebx, regs.ecx, regs.edx, ecx);
16*2b54f0dbSXin Li }
17*2b54f0dbSXin Li
print_cpuid_vendor(struct cpuid_regs regs,uint32_t eax)18*2b54f0dbSXin Li static void print_cpuid_vendor(struct cpuid_regs regs, uint32_t eax) {
19*2b54f0dbSXin Li if (regs.ebx | regs.ecx | regs.edx) {
20*2b54f0dbSXin Li char vendor_id[12];
21*2b54f0dbSXin Li memcpy(&vendor_id[0], ®s.ebx, sizeof(regs.ebx));
22*2b54f0dbSXin Li memcpy(&vendor_id[4], ®s.edx, sizeof(regs.edx));
23*2b54f0dbSXin Li memcpy(&vendor_id[8], ®s.ecx, sizeof(regs.ecx));
24*2b54f0dbSXin Li printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [%.12s]\n",
25*2b54f0dbSXin Li eax, regs.eax, regs.ebx, regs.ecx, regs.edx, vendor_id);
26*2b54f0dbSXin Li } else {
27*2b54f0dbSXin Li print_cpuid(regs, eax);
28*2b54f0dbSXin Li }
29*2b54f0dbSXin Li }
30*2b54f0dbSXin Li
print_cpuid_brand_string(struct cpuid_regs regs,uint32_t eax)31*2b54f0dbSXin Li static void print_cpuid_brand_string(struct cpuid_regs regs, uint32_t eax) {
32*2b54f0dbSXin Li char brand_string[16];
33*2b54f0dbSXin Li memcpy(&brand_string[0], ®s.eax, sizeof(regs.eax));
34*2b54f0dbSXin Li memcpy(&brand_string[4], ®s.ebx, sizeof(regs.ebx));
35*2b54f0dbSXin Li memcpy(&brand_string[8], ®s.ecx, sizeof(regs.ecx));
36*2b54f0dbSXin Li memcpy(&brand_string[12], ®s.edx, sizeof(regs.edx));
37*2b54f0dbSXin Li printf("CPUID %08"PRIX32": %08"PRIX32"-%08"PRIX32"-%08"PRIX32"-%08"PRIX32" [%.16s]\n",
38*2b54f0dbSXin Li eax, regs.eax, regs.ebx, regs.ecx, regs.edx, brand_string);
39*2b54f0dbSXin Li }
40*2b54f0dbSXin Li
main(int argc,char ** argv)41*2b54f0dbSXin Li int main(int argc, char** argv) {
42*2b54f0dbSXin Li const uint32_t max_base_index = cpuid(0).eax;
43*2b54f0dbSXin Li uint32_t max_structured_index = 0, max_trace_index = 0, max_socid_index = 0;
44*2b54f0dbSXin Li bool has_sgx = false;
45*2b54f0dbSXin Li for (uint32_t eax = 0; eax <= max_base_index; eax++) {
46*2b54f0dbSXin Li switch (eax) {
47*2b54f0dbSXin Li case UINT32_C(0x00000000):
48*2b54f0dbSXin Li print_cpuid_vendor(cpuid(eax), eax);
49*2b54f0dbSXin Li break;
50*2b54f0dbSXin Li case UINT32_C(0x00000004):
51*2b54f0dbSXin Li for (uint32_t ecx = 0; ; ecx++) {
52*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
53*2b54f0dbSXin Li if ((regs.eax & UINT32_C(0x1F)) == 0) {
54*2b54f0dbSXin Li break;
55*2b54f0dbSXin Li }
56*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
57*2b54f0dbSXin Li }
58*2b54f0dbSXin Li break;
59*2b54f0dbSXin Li case UINT32_C(0x00000007):
60*2b54f0dbSXin Li for (uint32_t ecx = 0; ecx <= max_structured_index; ecx++) {
61*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
62*2b54f0dbSXin Li if (ecx == 0) {
63*2b54f0dbSXin Li max_structured_index = regs.eax;
64*2b54f0dbSXin Li has_sgx = !!(regs.ebx & UINT32_C(0x00000004));
65*2b54f0dbSXin Li }
66*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
67*2b54f0dbSXin Li }
68*2b54f0dbSXin Li break;
69*2b54f0dbSXin Li case UINT32_C(0x0000000B):
70*2b54f0dbSXin Li for (uint32_t ecx = 0; ; ecx++) {
71*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
72*2b54f0dbSXin Li if ((regs.ecx & UINT32_C(0x0000FF00)) == 0) {
73*2b54f0dbSXin Li break;
74*2b54f0dbSXin Li }
75*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
76*2b54f0dbSXin Li }
77*2b54f0dbSXin Li break;
78*2b54f0dbSXin Li case UINT32_C(0x00000012):
79*2b54f0dbSXin Li if (has_sgx) {
80*2b54f0dbSXin Li for (uint32_t ecx = 0; ; ecx++) {
81*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
82*2b54f0dbSXin Li if (ecx >= 2 && (regs.eax & UINT32_C(0x0000000F)) == 0) {
83*2b54f0dbSXin Li break;
84*2b54f0dbSXin Li }
85*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
86*2b54f0dbSXin Li }
87*2b54f0dbSXin Li }
88*2b54f0dbSXin Li break;
89*2b54f0dbSXin Li case UINT32_C(0x00000014):
90*2b54f0dbSXin Li for (uint32_t ecx = 0; ecx <= max_trace_index; ecx++) {
91*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
92*2b54f0dbSXin Li if (ecx == 0) {
93*2b54f0dbSXin Li max_trace_index = regs.eax;
94*2b54f0dbSXin Li }
95*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
96*2b54f0dbSXin Li }
97*2b54f0dbSXin Li break;
98*2b54f0dbSXin Li case UINT32_C(0x00000017):
99*2b54f0dbSXin Li for (uint32_t ecx = 0; ecx <= max_socid_index; ecx++) {
100*2b54f0dbSXin Li const struct cpuid_regs regs = cpuidex(eax, ecx);
101*2b54f0dbSXin Li if (ecx == 0) {
102*2b54f0dbSXin Li max_socid_index = regs.eax;
103*2b54f0dbSXin Li }
104*2b54f0dbSXin Li print_cpuidex(regs, eax, ecx);
105*2b54f0dbSXin Li }
106*2b54f0dbSXin Li break;
107*2b54f0dbSXin Li default:
108*2b54f0dbSXin Li print_cpuid(cpuidex(eax, 0), eax);
109*2b54f0dbSXin Li break;
110*2b54f0dbSXin Li }
111*2b54f0dbSXin Li }
112*2b54f0dbSXin Li
113*2b54f0dbSXin Li const uint32_t max_extended_index = cpuid(UINT32_C(0x80000000)).eax;
114*2b54f0dbSXin Li for (uint32_t eax = UINT32_C(0x80000000); eax <= max_extended_index; eax++) {
115*2b54f0dbSXin Li switch (eax) {
116*2b54f0dbSXin Li case UINT32_C(0x80000000):
117*2b54f0dbSXin Li print_cpuid_vendor(cpuid(eax), eax);
118*2b54f0dbSXin Li break;
119*2b54f0dbSXin Li case UINT32_C(0x80000002):
120*2b54f0dbSXin Li case UINT32_C(0x80000003):
121*2b54f0dbSXin Li case UINT32_C(0x80000004):
122*2b54f0dbSXin Li print_cpuid_brand_string(cpuid(eax), eax);
123*2b54f0dbSXin Li break;
124*2b54f0dbSXin Li default:
125*2b54f0dbSXin Li print_cpuid(cpuidex(eax, 0), eax);
126*2b54f0dbSXin Li }
127*2b54f0dbSXin Li }
128*2b54f0dbSXin Li }
129