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