2 * Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2002, Carlos Hasan.
5 * Distributed under the terms of the MIT license.
18 // TODO: -disable_cpu_sn option is not yet implemented
19 // TODO: most of this file should go into an architecture dependent source file
20 #if defined(__INTEL__) || defined(__x86_64__)
22 struct cache_description
{
24 const char *description
;
25 } static sIntelCacheDescriptions
[] = {
26 {0x01, "Instruction TLB: 4k-byte pages, 4-way set associative, 32 entries"},
27 {0x02, "Instruction TLB: 4M-byte pages, fully associative, 2 entries"},
28 {0x03, "Data TLB: 4k-byte pages, 4-way set associative, 64 entries"},
29 {0x04, "Data TLB: 4M-byte pages, 4-way set associative, 8 entries"},
30 {0x05, "Data TLB: 4M-byte pages, 4-way set associative, 32 entries"},
31 {0x06, "L1 inst cache: 8 KB, 4-way set associative, 32 bytes/line"},
32 {0x08, "L1 inst cache: 16 KB, 4-way set associative, 32 bytes/line"},
33 {0x0A, "L1 data cache: 8 KB, 2-way set associative, 32 bytes/line"},
34 {0x0C, "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"},
35 {0x0D, "L1 data cache: 16 KB, 4-way set associative, 64-bytes/line, ECC"},
36 {0x0E, "L1 data cache, 24 KB, 6-way set associative, 64-bytes/line"},
37 {0x10, /* IA-64 */ "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"},
38 {0x15, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 32 bytes/line"},
39 {0x1A, /* IA-64 */ "L2 cache: 96 KB, 6-way set associative, 64 bytes/line"},
40 {0x21, "L2 cache: 256 KB (MLC), 8-way set associative, 64-bytes/line"},
41 {0x22, "L3 cache: 512 KB, 4-way set associative (!), 64 bytes/line, dual-sectored"},
42 {0x23, "L3 cache: 1 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
43 {0x25, "L3 cache: 2 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
44 {0x29, "L3 cache: 4 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
45 {0x2c, "L1 data cache: 32 KB, 8-way set associative, 64 bytes/line"},
46 {0x30, "L1 inst cache: 32 KB, 8-way set associative, 64 bytes/line"},
47 {0x39, "L2 cache: 128 KB, 4-way set associative, 64 bytes/line, sectored"},
48 {0x3A, "L2 cache: 192 KB, 4-way set associative, 64 bytes/line, sectored"},
49 {0x3B, "L2 cache: 128 KB, 2-way set associative, 64 bytes/line, sectored"},
50 {0x3C, "L2 cache: 256 KB, 4-way set associative, 64 bytes/line, sectored"},
51 {0x3D, "L2 cache: 384 KB, 6-way set associative, 64 bytes/line, sectored"},
52 {0x3E, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line, sectored"},
53 {0x40, NULL
/*"No integrated L2 cache (P6 core) or L3 cache (P4 core)"*/},
54 // this one is separately handled
55 {0x41, "L2 cache: 128 KB, 4-way set associative, 32 bytes/line"},
56 {0x42, "L2 cache: 256 KB, 4-way set associative, 32 bytes/line"},
57 {0x43, "L2 cache: 512 KB, 4-way set associative, 32 bytes/line"},
58 {0x44, "L2 cache: 1024 KB, 4-way set associative, 32 bytes/line"},
59 {0x45, "L2 cache: 2048 KB, 4-way set associative, 32 bytes/line"},
60 {0x46, "L3 cache: 4096 KB, 4-way set associative, 64 bytes/line"},
61 {0x47, "L3 cache: 8192 KB, 8-way set associative, 64 bytes/line"},
62 {0x48, "L2 cache: 3072 KB, 12-way set associative, 64 bytes/line, unified on-die"},
63 // 0x49 requires special handling, either 4M L3 (Xeon MP, 0F06; otherwise 4M L2
64 {0x4A, "L3 cache: 6144 KB, 12-way set associative, 64 bytes/line"},
65 {0x4B, "L3 cache: 8192 KB, 16-way set associative, 64 bytes/line"},
66 {0x4C, "L3 cache: 12288 KB, 12-way set associative, 64 bytes/line"},
67 {0x4D, "L3 cache: 16384 KB, 16-way set associative, 64 bytes/line"},
68 {0x4E, "L2 cache: 6144 KB, 24-way set associative, 64 bytes/line"},
69 {0x4F, "Inst TLB, 4K-bytes pages, 32 entries"},
70 {0x50, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 64 entries"},
71 {0x51, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 128 entries"},
72 {0x52, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 256 entries"},
73 {0x55, "Inst TLB: 2M/4M-bytes pages, fully associative, 7 entries"},
74 {0x56, "L1 Data TLB: 4M-bytes pages, 4-way set associative, 16 entries"},
75 {0x57, "L1 Data TLB: 4K-bytes pages, 4-way set associative, 16 entries"},
76 {0x59, "L0 Data TLB: 4K-bytes pages, fully associative, 16 entries"},
77 {0x5A, "L0 Data TLB: 2M/4M-bytes pages, 4-way set associative, 32 entries"},
78 {0x5B, "Data TLB: 4K/4M-bytes pages, fully associative, 64 entries"},
79 {0x5C, "Data TLB: 4K/4M-bytes pages, fully associative, 128 entries"},
80 {0x5D, "Data TLB: 4K/4M-bytes pages, fully associative, 256 entries"},
81 {0x63, "Data TLB: 2M/4M-bytes pages, 4-way set associative, 32 entries"},
82 {0x66, "L1 data cache: 8 KB, 4-way set associative, 64 bytes/line, sectored"},
83 {0x67, "L1 data cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"},
84 {0x68, "L1 data cache: 32 KB, 4-way set associative, 64 bytes/line, sectored"},
85 {0x70, "Inst trace cache: 12K µOPs, 8-way set associative"},
86 {0x71, "Inst trace cache: 16K µOPs, 8-way set associative"},
87 {0x72, "Inst trace cache: 32K µOPs, 8-way set associative"},
88 {0x76, "Code TLB: 2M/4M pages, fully, 8 entries"},
89 {0x77, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"},
90 {0x79, "L2 cache: 128 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
91 {0x7A, "L2 cache: 256 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
92 {0x7B, "L2 cache: 512 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
93 {0x7C, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
94 {0x7D, "L2 cache: 2048 KB, 8-way set associative, 64 bytes/line"},
95 {0x7E, /* IA-64 */ "L2 cache: 256 KB, 8-way set associative, 128 bytes/line, sectored"},
96 {0x7F, "L2 cache: 512 KB, 2-way set associative, 64 bytes/line"},
97 {0x81, "L2 cache: 128 KB, 8-way set associative, 32 bytes/line"},
98 {0x82, "L2 cache: 256 KB, 8-way set associative, 32 bytes/line"},
99 {0x83, "L2 cache: 512 KB, 8-way set associative, 32 bytes/line"},
100 {0x84, "L2 cache: 1024 KB, 8-way set associative, 32 bytes/line"},
101 {0x85, "L2 cache: 2048 KB, 8-way set associative, 32 bytes/line"},
102 {0x86, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line"},
103 {0x87, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line"},
104 {0x88, /* IA-64 */ "L3 cache: 2 MB, 4-way set associative, 64 bytes/line"},
105 {0x89, /* IA-64 */ "L3 cache: 4 MB, 4-way set associative, 64 bytes/line"},
106 {0x8A, /* IA-64 */ "L3 cache: 8 MB, 4-way set associative, 64 bytes/line"},
107 {0x8D, /* IA-64 */ "L3 cache: 3 MB, 12-way set associative, 128 bytes/line"},
108 {0x90, /* IA-64 */ "Inst TLB: 4K-256Mbytes pages, fully associative, 64 entries"},
109 {0x96, /* IA-64 */ "L1 data TLB: 4K-256M bytes pages, fully associative, 32 entries"},
110 {0x9B, /* IA-64 */ "L2 data TLB: 4K-256M bytes pages, fully associative, 96 entries"},
111 // {0x70, "Cyrix specific: Code and data TLB: 4k-bytes pages, 4-way set associative, 32 entries"},
112 // {0x74, "Cyrix specific: ???"},
113 // {0x77, "Cyrix specific: ???"},
114 {0x80, /* Cyrix specific */ "L1 cache: 16 KB, 4-way set associative, 16 bytes/line"},
115 // {0x82, "Cyrix specific: ???"},
116 // {0x84, "Cyrix specific: ???"},
117 {0xB0, "Inst TLB: 4K-bytes pages, 4-way set associative, 128 entries"},
118 {0xB1, "Inst TLB: 2M-bytes pages, 4-way set associative, 8 entries OR 4M, 4-way, 4 entries"},
119 // Intel doesn't give any details how to determine which of the two options is the case
120 // as per Intel Application Note 485, November 2008.
121 {0xB2, "Inst TLB: 4K-bytes pages, 4-way set associative, 64 entries"},
122 {0xB3, "Data TLB: 4K-bytes pages, 4-way set associative, 128 entries"},
123 {0xB4, "Data TLB: 4K-bytes pages, 4-way set associative, 256 entries"},
124 {0xB5, "Code TLB: 4K-bytes pages, 8-way set associative, 64 entries"},
125 {0xB6, "Code TLB: 4K-bytes pages, 8-way set associative, 128 entries"},
126 {0xBA, "Data TLB, 4K-bytes pages, 4-way set associative, 64 entries"},
127 {0xC0, "Data TLB, 4K-4M bytes pages, 4-way set associative, 8 entries"},
128 {0xC3, "Shared 2nd-level TLB: 4K/2M, 6-way set associative, 1536 entries"},
129 {0xCA, "Shared 2nd-level TLB: 4K, 4-way set associative, 512 entries"},
130 {0xD0, "L3 cache: 512 KB, 4-way set associative, 64-bytes/line"},
131 {0xD1, "L3 cache: 1024 KB, 4-way set associative, 64-bytes/line"},
132 {0xD2, "L3 cache: 2048 KB, 4-way set associative, 64-bytes/line"},
133 {0xD6, "L3 cache: 1024 KB, 8-way set associative, 64-bytes/line"},
134 {0xD7, "L3 cache: 2048 KB, 8-way set associative, 64-bytes/line"},
135 {0xD8, "L3 cache: 4096 KB, 8-way set associative, 64-bytes/line"},
136 {0xDC, "L3 cache: 2048 KB, 12-way set associative, 64-bytes/line"},
137 {0xDD, "L3 cache: 4096 KB, 12-way set associative, 64-bytes/line"},
138 {0xDE, "L3 cache: 8192 KB, 12-way set associative, 64-bytes/line"},
139 {0xE2, "L3 cache: 2048 KB, 16-way set associative, 64-bytes/line"},
140 {0xE3, "L3 cache: 4096 KB, 16-way set associative, 64-bytes/line"},
141 {0xE4, "L3 cache: 8192 KB, 16-way set associative, 64-bytes/line"},
142 {0xF0, "64-byte Prefetching"},
143 {0xF1, "128-byte Prefetching"},
144 {0xFF, "TODO: Query standard level 0000_0004h instead"},
150 static const char *kFeatures
[32] = {
151 "FPU", "VME", "DE", "PSE",
152 "TSC", "MSR", "PAE", "MCE",
153 "CX8", "APIC", NULL
, "SEP",
154 "MTRR", "PGE", "MCA", "CMOV",
155 "PAT", "PSE36", "PSN", "CFLUSH",
156 NULL
, "DS", "ACPI", "MMX",
157 "FXSTR", "SSE", "SSE2", "SS",
158 "HTT", "TM", NULL
, "PBE",
161 /* CPU Extended features */
162 static const char *kExtendedFeatures
[32] = {
163 "SSE3", "PCLMULDQ", "DTES64", "MONITOR", "DS-CPL", "VMX", "SMX", "EST",
164 "TM2", "SSSE3", "CNTXT-ID", NULL
, "FMA", "CX16", "xTPR", "PDCM",
165 NULL
, "PCID", "DCA", "SSE4.1", "SSE4.2", "x2APIC", "MOVEB", "POPCNT",
166 "TSC-DEADLINE", "AES", "XSAVE", "OSXSAVE", "AVX", "F16C", "RDRND",
171 /* AMD Extended features leaf 0x80000001 */
172 static const char *kAMDExtFeatures
[32] = {
173 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
174 NULL
, NULL
, NULL
, "SCE", NULL
, NULL
, NULL
, NULL
,
175 NULL
, NULL
, NULL
, NULL
, "NX", NULL
, "AMD-MMX", NULL
,
176 "FXSR", "FFXSR", NULL
, "RDTSCP", NULL
, "64", "3DNow+", "3DNow!"
180 /* AMD Extended features leaf 0x80000007 */
181 static const char *kAMDExtFeaturesPower
[32] = {
182 "TS", "FID", "VID", "TTP", "TM", "STC", "MUL100", "HWPS",
183 "ITSC", "CPB", "EFRO", "PFI", "PA", NULL
, NULL
, NULL
,
184 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
185 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
189 /* AMD Extended features leaf 0x80000008 */
190 static const char *kAMDExtFeaturesTwo
[32] = {
191 "CLZERO", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
192 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
193 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
194 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
199 print_intel_cache_descriptors(enum cpu_vendor vendor
, uint32 model
,
202 uint8 cacheDescriptors
[15]; // Max
207 // put valid values into array
208 if ((info
->regs
.eax
& 0x80000000) == 0) {
209 // eax is valid, include values
210 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
211 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
212 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
216 if ((info
->regs
.ebx
& 0x80000000) == 0) {
217 // ebx is valid, include values
218 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
219 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
220 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
221 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
225 if ((info
->regs
.edx
& 0x80000000) == 0) {
226 // edx is valid, include values
227 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
228 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
229 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
230 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
234 if ((info
->regs
.ecx
& 0x80000000) == 0) {
235 // ecx is valid, include values
236 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
237 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
238 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
239 cacheDescriptors
[maxDesc
++] = info
->eax_2
.cache_descriptors
[i
++];
244 for (int i
= 0; i
< maxDesc
; i
++) {
245 // ignore NULL descriptors
246 if (cacheDescriptors
[i
] == 0)
250 for (j
= 0; sIntelCacheDescriptions
[j
].code
; j
++) {
251 if (cacheDescriptors
[i
] == sIntelCacheDescriptions
[j
].code
) {
252 if (cacheDescriptors
[i
] == 0x40) {
253 printf("\tNo integrated L%u cache\n",
254 ((model
>> 8) & 0xf) == 0xf
255 && vendor
== B_CPU_VENDOR_INTEL
? 3 : 2);
257 printf("\t%s\n", sIntelCacheDescriptions
[j
].description
);
262 // Reached the end without finding a descriptor
263 if (sIntelCacheDescriptions
[j
].code
== 0)
264 printf("\tUnknown cache descriptor 0x%02x\n", cacheDescriptors
[i
]);
269 #endif // __INTEL__ || __x86_64__
273 print_TLB(uint32 reg
, const char *pages
)
277 const char *name
[2] = { "Inst TLB", "Data TLB" };
279 entries
[0] = (reg
& 0xff);
280 ways
[0] = ((reg
>> 8) & 0xff);
281 entries
[1] = ((reg
>> 16) & 0xff);
282 ways
[1] = ((reg
>> 24) & 0xff);
284 for (int num
= 0; num
< 2; num
++) {
285 printf("\t%s: %s%s%u entries, ", name
[num
],
286 pages
? pages
: "", pages
? " pages, " : "", entries
[num
]);
288 if (ways
[num
] == 0xff)
289 printf("fully associative\n");
291 printf("%u-way set associative\n", ways
[num
]);
297 print_level2_cache(uint32 reg
, const char *name
)
299 uint32 size
= (reg
>> 16) & 0xffff;
300 uint32 ways
= (reg
>> 12) & 0xf;
301 uint32 linesPerTag
= (reg
>> 8) & 0xf;
302 // intel does not define this
303 uint32 lineSize
= reg
& 0xff;
305 printf("\t%s: %" B_PRIu32
" KB, ", name
, size
);
307 printf("fully associative, ");
308 else if (ways
== 0x1)
309 printf("direct-mapped, ");
311 printf("%lu-way set associative, ", 1UL << (ways
/ 2));
312 printf("%" B_PRIu32
" lines/tag, %" B_PRIu32
" bytes/line\n", linesPerTag
,
318 print_level1_cache(uint32 reg
, const char *name
)
320 uint32 size
= (reg
>> 24) & 0xff;
321 uint32 ways
= (reg
>> 16) & 0xff;
322 uint32 linesPerTag
= (reg
>> 8) & 0xff;
323 uint32 lineSize
= reg
& 0xff;
325 printf("\t%s: %" B_PRIu32
" KB, ", name
, size
);
327 printf("fully associative, ");
329 printf("%" B_PRIu32
"-way set associative, ", ways
);
330 printf("%" B_PRIu32
" lines/tag, %" B_PRIu32
" bytes/line\n", linesPerTag
,
335 #if defined(__INTEL__) || defined(__x86_64__)
338 print_cache_desc(int32 cpu
)
341 get_cpuid(&info
, 0x80000005, cpu
);
346 print_TLB(info
.regs
.eax
, info
.regs
.ebx
? "2M/4M-byte" : NULL
);
348 print_TLB(info
.regs
.ebx
, info
.regs
.eax
? "4K-byte" : NULL
);
350 print_level1_cache(info
.regs
.ecx
, "L1 inst cache");
351 print_level1_cache(info
.regs
.edx
, "L1 data cache");
353 get_cpuid(&info
, 0x80000006, cpu
);
354 print_level2_cache(info
.regs
.ecx
, "L2 cache");
359 print_intel_cache_desc(int32 cpu
)
363 // A second parameters needs to be passed to CPUID which determines the
364 // cache level to query
365 get_cpuid(&info
, 0x00000004, cpu
);
369 uint32 type
= info
.regs
.eax
& 0xf;
370 uint32 level
= (info
.regs
.eax
& 0x70) >> 4;
371 bool isFullyAssoc
= info
.regs
.eax
& 0x100;
373 uint32 lineSize
= (info
.regs
.ebx
& 0xfff) + 1;
374 uint32 linesPerTag
= ((info
.regs
.ebx
& 0x3ff000) >> 12) + 1;
375 uint32 ways
= ((info
.regs
.ebx
& 0xffc00000) >> 22) + 1;
377 uint32 sets
= info
.regs
.ecx
;
379 printf("\tL%" B_PRId32
" ",level
);
382 case 1: printf("Data cache "); break;
383 case 2: printf("Inst cache "); break;
384 case 3: printf("Unified cache "); break;
389 printf("fully associative, ");
391 printf("%" B_PRIu32
"-way set associative, ", ways
);
392 printf("%" B_PRIu32
" lines/tag, %" B_PRIu32
" bytes/line\n", linesPerTag
,
395 get_cpuid(&info
, 0x80000006, cpu
);
396 print_level2_cache(sets
, "L2 cache");
401 print_transmeta_features(uint32 features
)
403 if (features
& (1 << 16))
404 printf("\t\tFCMOV\n");
407 #endif // __INTEL__ || __x86_64__
411 print_features(const char** table
, uint32 features
)
415 for (int32 i
= 0; i
< 32; i
++) {
416 if ((features
& (1UL << i
)) && table
[i
] != NULL
) {
417 printf("%s%s", found
== 0 ? "\t\t" : " ", table
[i
]);
419 if (found
> 0 && (found
% 16) == 0) {
431 #if defined(__INTEL__) || defined(__x86_64__)
434 print_processor_signature(enum cpu_vendor vendor
, cpuid_info
*info
)
436 printf("\tSignature: 0x%1" B_PRIx32
"%1" B_PRIx32
"0%1" B_PRIx32
437 "%1" B_PRIx32
"%1" B_PRIx32
"; ", info
->eax_1
.extended_family
,
438 info
->eax_1
.extended_model
, info
->eax_1
.family
,
439 info
->eax_1
.model
, info
->eax_1
.stepping
);
440 if (vendor
== B_CPU_VENDOR_AMD
) {
441 printf("Type %" B_PRIu32
", family %" B_PRIu32
", model %" B_PRIu32
442 ", stepping %" B_PRIu32
"\n",
444 info
->eax_1
.family
+ (info
->eax_1
.family
== 0xf
445 ? info
->eax_1
.extended_family
: 0),
446 info
->eax_1
.model
+ (info
->eax_1
.model
== 0xf
447 ? info
->eax_1
.extended_model
<< 4 : 0),
448 info
->eax_1
.stepping
);
449 } else if (vendor
== B_CPU_VENDOR_INTEL
) {
450 // model calculation is different for INTEL
451 printf("Type %" B_PRIu32
", family %" B_PRIu32
", model %" B_PRIu32
452 ", stepping %" B_PRIu32
"\n",
454 info
->eax_1
.family
+ (info
->eax_1
.family
== 0xf
455 ? info
->eax_1
.extended_family
: 0),
457 + ((info
->eax_1
.family
== 0xf || info
->eax_1
.family
== 0x6)
458 ? info
->eax_1
.extended_model
<< 4 : 0),
459 info
->eax_1
.stepping
);
463 #endif // __INTEL__ || __x86_64__
467 dump_platform(system_info
*info
)
469 cpu_topology_node_info root
;
471 get_cpu_topology_info(&root
, &count
);
473 const char* platform
;
474 switch (root
.data
.root
.platform
) {
476 platform
= "IntelArchitecture";
480 platform
= "IntelArchitecture (64 bit)";
484 platform
= "unknown";
488 printf("%s\n", platform
);
492 #if defined(__INTEL__) || defined(__x86_64__)
495 dump_cpu(enum cpu_vendor vendor
, uint32 model
, int32 cpu
)
498 // http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
499 // http://www.sandpile.org/ia32/cpuid.htm
500 // http://www.sandpile.org/x86/cpuid.htm
501 // http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/TN13.pdf (Duron erratum)
504 if (get_cpuid(&baseInfo
, 0, cpu
) != B_OK
) {
505 // this CPU doesn't support cpuid
509 int32 maxStandardFunction
= baseInfo
.eax_0
.max_eax
;
510 if (maxStandardFunction
>= 500) {
511 // old Pentium sample chips has cpu signature here
512 maxStandardFunction
= 0;
518 get_cpuid(&cpuInfo
, 0x80000000, cpu
);
520 // Extended cpuid is only supported if max_eax is greater than the
522 int32 maxExtendedFunction
= 0;
523 if (cpuInfo
.eax_0
.max_eax
> 0x80000000)
524 maxExtendedFunction
= cpuInfo
.eax_0
.max_eax
& 0xff;
526 if (maxExtendedFunction
>=4 ) {
530 memset(buffer
, 0, sizeof(buffer
));
532 for (int32 i
= 0; i
< 3; i
++) {
534 get_cpuid(&nameInfo
, 0x80000002 + i
, cpu
);
536 memcpy(name
, &nameInfo
.regs
.eax
, 4);
537 memcpy(name
+ 4, &nameInfo
.regs
.ebx
, 4);
538 memcpy(name
+ 8, &nameInfo
.regs
.ecx
, 4);
539 memcpy(name
+ 12, &nameInfo
.regs
.edx
, 4);
543 // cut off leading spaces (names are right aligned)
545 while (name
[0] == ' ')
548 // the BIOS may not have set the processor name
550 printf("CPU #%" B_PRId32
": \"%s\"\n", cpu
, name
);
552 // Intel CPUs don't seem to have the genuine vendor field
553 printf("CPU #%" B_PRId32
": %.12s\n", cpu
,
554 vendor
== B_CPU_VENDOR_INTEL
?
555 baseInfo
.eax_0
.vendor_id
: cpuInfo
.eax_0
.vendor_id
);
558 printf("CPU #%" B_PRId32
": %.12s\n", cpu
, baseInfo
.eax_0
.vendor_id
);
559 if (maxStandardFunction
== 0)
563 get_cpuid(&cpuInfo
, 1, cpu
);
564 print_processor_signature(vendor
, &cpuInfo
);
565 printf("\tFeatures: 0x%08" B_PRIx32
"\n", cpuInfo
.eax_1
.features
);
566 print_features(kFeatures
, cpuInfo
.eax_1
.features
);
568 if (maxStandardFunction
>= 1) {
569 /* Extended features */
570 printf("\tExtended Features (0x00000001): 0x%08" B_PRIx32
"\n",
571 cpuInfo
.eax_1
.extended_features
);
572 print_features(kExtendedFeatures
, cpuInfo
.eax_1
.extended_features
);
575 /* Extended CPUID Information */
576 if (maxExtendedFunction
>= 1) {
577 get_cpuid(&cpuInfo
, 0x80000001, cpu
);
578 if (vendor
== B_CPU_VENDOR_INTEL
|| vendor
== B_CPU_VENDOR_AMD
) {
579 // 0x80000001 EDX has overlap of 64,ED,SY/SE between amd and intel
580 printf("\tExtended Features (0x80000001): 0x%08" B_PRIx32
"\n",
581 cpuInfo
.eax_1
.features
);
582 print_features(kAMDExtFeatures
, cpuInfo
.regs
.edx
);
585 if (vendor
== B_CPU_VENDOR_AMD
) {
586 if (maxExtendedFunction
>= 7) {
587 get_cpuid(&cpuInfo
, 0x80000007, cpu
);
588 printf("\tExtended Features (0x80000007): 0x%08" B_PRIx32
"\n",
590 print_features(kAMDExtFeaturesPower
, cpuInfo
.regs
.edx
);
592 if (maxExtendedFunction
>= 8) {
593 get_cpuid(&cpuInfo
, 0x80000008, cpu
);
594 printf("\tExtended Features (0x80000008): 0x%08" B_PRIx32
"\n",
596 print_features(kAMDExtFeaturesTwo
, cpuInfo
.regs
.ebx
);
598 } else if (vendor
== B_CPU_VENDOR_TRANSMETA
)
599 print_transmeta_features(cpuInfo
.regs
.edx
);
602 /* Cache/TLB descriptors */
603 if (maxExtendedFunction
>= 5) {
604 if (!strncmp(baseInfo
.eax_0
.vendor_id
, "CyrixInstead", 12)) {
605 get_cpuid(&cpuInfo
, 0x00000002, cpu
);
606 print_intel_cache_descriptors(vendor
, model
, &cpuInfo
);
607 } else if (vendor
== B_CPU_VENDOR_INTEL
) {
608 // Intel does not support extended function 5 (but it does 6 hmm)
609 print_intel_cache_desc(cpu
);
611 print_cache_desc(cpu
);
615 if (maxStandardFunction
>= 2) {
617 get_cpuid(&cpuInfo
, 2, cpu
);
619 if (cpuInfo
.eax_2
.call_num
> 0)
620 print_intel_cache_descriptors(vendor
, model
, &cpuInfo
);
621 } while (cpuInfo
.eax_2
.call_num
> 1);
625 if (maxStandardFunction
>= 3) {
626 cpuid_info flagsInfo
;
627 get_cpuid(&flagsInfo
, 1, cpu
);
629 if (flagsInfo
.eax_1
.features
& (1UL << 18)) {
630 get_cpuid(&cpuInfo
, 3, cpu
);
631 printf("Serial number: %04" B_PRIx32
"-%04" B_PRIx32
"-%04" B_PRIx32
632 "-%04" B_PRIx32
"-%04" B_PRIx32
"-%04" B_PRIx32
"\n",
633 flagsInfo
.eax_1
.features
>> 16,
634 flagsInfo
.eax_1
.features
& 0xffff,
635 cpuInfo
.regs
.edx
>> 16, cpuInfo
.regs
.edx
& 0xffff,
636 cpuInfo
.regs
.ecx
>> 16, cpuInfo
.regs
.edx
& 0xffff);
643 #endif // __INTEL__ || __x86_64__
647 dump_cpus(system_info
*info
)
649 uint32 topologyNodeCount
= 0;
650 cpu_topology_node_info
* topology
= NULL
;
651 get_cpu_topology_info(NULL
, &topologyNodeCount
);
652 if (topologyNodeCount
!= 0)
653 topology
= new cpu_topology_node_info
[topologyNodeCount
];
654 get_cpu_topology_info(topology
, &topologyNodeCount
);
656 enum cpu_platform platform
= B_CPU_UNKNOWN
;
657 enum cpu_vendor cpuVendor
= B_CPU_VENDOR_UNKNOWN
;
659 uint64 frequency
= 0;
660 for (uint32 i
= 0; i
< topologyNodeCount
; i
++) {
661 switch (topology
[i
].type
) {
662 case B_TOPOLOGY_ROOT
:
663 platform
= topology
[i
].data
.root
.platform
;
666 case B_TOPOLOGY_PACKAGE
:
667 cpuVendor
= topology
[i
].data
.package
.vendor
;
670 case B_TOPOLOGY_CORE
:
671 cpuModel
= topology
[i
].data
.core
.model
;
672 frequency
= topology
[i
].data
.core
.default_frequency
;
681 const char *vendor
= get_cpu_vendor_string(cpuVendor
);
682 const char *model
= get_cpu_model_string(platform
, cpuVendor
, cpuModel
);
683 char modelString
[32];
685 if (model
== NULL
&& vendor
== NULL
)
687 else if (model
== NULL
) {
689 snprintf(modelString
, 32, "(Unknown %" B_PRIx32
")", cpuModel
);
692 printf("%" B_PRId32
" %s%s%s, revision %04" B_PRIx32
" running at %"
695 vendor
? vendor
: "", vendor
? " " : "", model
,
697 frequency
/ 1000000);
699 #if defined(__INTEL__) || defined(__x86_64__)
700 for (uint32 cpu
= 0; cpu
< info
->cpu_count
; cpu
++)
701 dump_cpu(cpuVendor
, cpuModel
, cpu
);
702 #endif // __INTEL__ || __x86_64__
707 dump_mem(system_info
*info
)
709 printf("%10" B_PRIu64
" bytes free (used/max %10" B_PRIu64
" / %10"
711 B_PAGE_SIZE
* (uint64
)(info
->max_pages
- info
->used_pages
),
712 B_PAGE_SIZE
* (uint64
)info
->used_pages
,
713 B_PAGE_SIZE
* (uint64
)info
->max_pages
);
714 printf(" (cached %10" B_PRIu64
")\n",
715 B_PAGE_SIZE
* (uint64
)info
->cached_pages
);
720 dump_sem(system_info
*info
)
722 printf("%10" B_PRId32
" semaphores free (used/max %10" B_PRId32
" / %10"
724 info
->max_sems
- info
->used_sems
,
725 info
->used_sems
, info
->max_sems
);
730 dump_ports(system_info
*info
)
732 printf("%10" B_PRId32
" ports free (used/max %10" B_PRId32
" / %10"
734 info
->max_ports
- info
->used_ports
,
735 info
->used_ports
, info
->max_ports
);
740 dump_thread(system_info
*info
)
742 printf("%10" B_PRId32
" threads free (used/max %10" B_PRId32
" / %10"
744 info
->max_threads
- info
->used_threads
,
745 info
->used_threads
, info
->max_threads
);
750 dump_team(system_info
*info
)
752 printf("%10" B_PRId32
" teams free (used/max %10" B_PRId32
" / %10"
754 info
->max_teams
- info
->used_teams
,
755 info
->used_teams
, info
->max_teams
);
760 dump_kinfo(system_info
*info
)
762 printf("Kernel name: %s built on: %s %s version 0x%" B_PRIx64
"\n",
764 info
->kernel_build_date
, info
->kernel_build_time
,
765 info
->kernel_version
);
770 dump_system_info(system_info
*info
)
783 main(int argc
, char *argv
[])
785 if (!is_computer_on()) {
786 printf("The computer is not on! No info available\n");
791 if (get_system_info(&info
) != B_OK
) {
792 printf("Error getting system information!\n");
797 dump_system_info(&info
);
799 for (int i
= 1; i
< argc
; i
++) {
800 const char *opt
= argv
[i
];
801 if (strncmp(opt
, "-id", strlen(opt
)) == 0) {
802 /* note: the original also assumes this option on "sysinfo -" */
803 printf("%#.8x %#.8x\n", 0,0);
804 } else if (strncmp(opt
, "-cpu", strlen(opt
)) == 0) {
806 } else if (strncmp(opt
, "-mem", strlen(opt
)) == 0) {
808 } else if (strncmp(opt
, "-semaphores", strlen(opt
)) == 0) {
810 } else if (strncmp(opt
, "-ports", strlen(opt
)) == 0) {
812 } else if (strncmp(opt
, "-threads", strlen(opt
)) == 0) {
814 } else if (strncmp(opt
, "-teams", strlen(opt
)) == 0) {
816 } else if (strncmp(opt
, "-kinfo", strlen(opt
)) == 0) {
818 } else if (strncmp(opt
, "-platform", strlen(opt
)) == 0) {
819 dump_platform(&info
);
820 } else if (strncmp(opt
, "-disable_cpu_sn", strlen(opt
)) == 0) {
821 /* TODO: printf("CPU #%d serial number: old state: %s, new state: %s\n", ... ); */
822 fprintf(stderr
, "Sorry, not yet implemented\n");
824 const char *name
= strrchr(argv
[0], '/');
830 fprintf(stderr
, "Usage:\n");
831 fprintf(stderr
, " %s [-id|-cpu|-mem|-semaphore|-ports|-threads|-teams|-platform|-disable_cpu_sn|-kinfo]\n", name
);