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