• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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], &regs.ebx, sizeof(regs.ebx));
31 		memcpy(&vendor_id[4], &regs.edx, sizeof(regs.edx));
32 		memcpy(&vendor_id[8], &regs.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], &regs.eax, sizeof(regs.eax));
48 	memcpy(&brand_string[4], &regs.ebx, sizeof(regs.ebx));
49 	memcpy(&brand_string[8], &regs.ecx, sizeof(regs.ecx));
50 	memcpy(&brand_string[12], &regs.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