11f5facdbSJerome Duval /* 2f1cbaf5cSAxel Dörfler * Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de. 3f1cbaf5cSAxel Dörfler * Copyright 2002, Carlos Hasan. 41f5facdbSJerome Duval * 51f5facdbSJerome Duval * Distributed under the terms of the MIT license. 61f5facdbSJerome Duval */ 71f5facdbSJerome Duval 81f5facdbSJerome Duval 91f5facdbSJerome Duval #include <OS.h> 101f5facdbSJerome Duval 111f5facdbSJerome Duval #include <stdio.h> 121f5facdbSJerome Duval #include <stdlib.h> 131f5facdbSJerome Duval #include <string.h> 141f5facdbSJerome Duval 151f5facdbSJerome Duval #include <cpu_type.h> 161f5facdbSJerome Duval 171f5facdbSJerome Duval 18f1cbaf5cSAxel Dörfler // TODO: -disable_cpu_sn option is not yet implemented 19f1cbaf5cSAxel Dörfler // TODO: most of this file should go into an architecture dependent source file 20533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 211f5facdbSJerome Duval 221f5facdbSJerome Duval struct cache_description { 231f5facdbSJerome Duval uint8 code; 241f5facdbSJerome Duval const char *description; 251f5facdbSJerome Duval } static sIntelCacheDescriptions[] = { 261f5facdbSJerome Duval {0x01, "Instruction TLB: 4k-byte pages, 4-way set associative, 32 entries"}, 271f5facdbSJerome Duval {0x02, "Instruction TLB: 4M-byte pages, fully associative, 2 entries"}, 281f5facdbSJerome Duval {0x03, "Data TLB: 4k-byte pages, 4-way set associative, 64 entries"}, 291f5facdbSJerome Duval {0x04, "Data TLB: 4M-byte pages, 4-way set associative, 8 entries"}, 301f5facdbSJerome Duval {0x05, "Data TLB: 4M-byte pages, 4-way set associative, 32 entries"}, 311f5facdbSJerome Duval {0x06, "L1 inst cache: 8 KB, 4-way set associative, 32 bytes/line"}, 321f5facdbSJerome Duval {0x08, "L1 inst cache: 16 KB, 4-way set associative, 32 bytes/line"}, 331f5facdbSJerome Duval {0x0A, "L1 data cache: 8 KB, 2-way set associative, 32 bytes/line"}, 341f5facdbSJerome Duval {0x0C, "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"}, 351f5facdbSJerome Duval {0x0D, "L1 data cache: 16 KB, 4-way set associative, 64-bytes/line, ECC"}, 361f5facdbSJerome Duval {0x0E, "L1 data cache, 24 KB, 6-way set associative, 64-bytes/line"}, 371f5facdbSJerome Duval {0x10, /* IA-64 */ "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"}, 381f5facdbSJerome Duval {0x15, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 32 bytes/line"}, 391f5facdbSJerome Duval {0x1A, /* IA-64 */ "L2 cache: 96 KB, 6-way set associative, 64 bytes/line"}, 401f5facdbSJerome Duval {0x21, "L2 cache: 256 KB (MLC), 8-way set associative, 64-bytes/line"}, 411f5facdbSJerome Duval {0x22, "L3 cache: 512 KB, 4-way set associative (!), 64 bytes/line, dual-sectored"}, 421f5facdbSJerome Duval {0x23, "L3 cache: 1 MB, 8-way set associative, 64 bytes/line, dual-sectored"}, 431f5facdbSJerome Duval {0x25, "L3 cache: 2 MB, 8-way set associative, 64 bytes/line, dual-sectored"}, 441f5facdbSJerome Duval {0x29, "L3 cache: 4 MB, 8-way set associative, 64 bytes/line, dual-sectored"}, 451f5facdbSJerome Duval {0x2c, "L1 data cache: 32 KB, 8-way set associative, 64 bytes/line"}, 461f5facdbSJerome Duval {0x30, "L1 inst cache: 32 KB, 8-way set associative, 64 bytes/line"}, 471f5facdbSJerome Duval {0x39, "L2 cache: 128 KB, 4-way set associative, 64 bytes/line, sectored"}, 481f5facdbSJerome Duval {0x3A, "L2 cache: 192 KB, 4-way set associative, 64 bytes/line, sectored"}, 491f5facdbSJerome Duval {0x3B, "L2 cache: 128 KB, 2-way set associative, 64 bytes/line, sectored"}, 501f5facdbSJerome Duval {0x3C, "L2 cache: 256 KB, 4-way set associative, 64 bytes/line, sectored"}, 511f5facdbSJerome Duval {0x3D, "L2 cache: 384 KB, 6-way set associative, 64 bytes/line, sectored"}, 521f5facdbSJerome Duval {0x3E, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line, sectored"}, 531f5facdbSJerome Duval {0x40, NULL /*"No integrated L2 cache (P6 core) or L3 cache (P4 core)"*/}, 541f5facdbSJerome Duval // this one is separately handled 551f5facdbSJerome Duval {0x41, "L2 cache: 128 KB, 4-way set associative, 32 bytes/line"}, 561f5facdbSJerome Duval {0x42, "L2 cache: 256 KB, 4-way set associative, 32 bytes/line"}, 571f5facdbSJerome Duval {0x43, "L2 cache: 512 KB, 4-way set associative, 32 bytes/line"}, 581f5facdbSJerome Duval {0x44, "L2 cache: 1024 KB, 4-way set associative, 32 bytes/line"}, 591f5facdbSJerome Duval {0x45, "L2 cache: 2048 KB, 4-way set associative, 32 bytes/line"}, 601f5facdbSJerome Duval {0x46, "L3 cache: 4096 KB, 4-way set associative, 64 bytes/line"}, 611f5facdbSJerome Duval {0x47, "L3 cache: 8192 KB, 8-way set associative, 64 bytes/line"}, 621f5facdbSJerome Duval {0x48, "L2 cache: 3072 KB, 12-way set associative, 64 bytes/line, unified on-die"}, 631f5facdbSJerome Duval // 0x49 requires special handling, either 4M L3 (Xeon MP, 0F06; otherwise 4M L2 641f5facdbSJerome Duval {0x4A, "L3 cache: 6144 KB, 12-way set associative, 64 bytes/line"}, 651f5facdbSJerome Duval {0x4B, "L3 cache: 8192 KB, 16-way set associative, 64 bytes/line"}, 661f5facdbSJerome Duval {0x4C, "L3 cache: 12288 KB, 12-way set associative, 64 bytes/line"}, 671f5facdbSJerome Duval {0x4D, "L3 cache: 16384 KB, 16-way set associative, 64 bytes/line"}, 681f5facdbSJerome Duval {0x4E, "L2 cache: 6144 KB, 24-way set associative, 64 bytes/line"}, 691f5facdbSJerome Duval {0x4F, "Inst TLB, 4K-bytes pages, 32 entries"}, 701f5facdbSJerome Duval {0x50, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 64 entries"}, 711f5facdbSJerome Duval {0x51, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 128 entries"}, 721f5facdbSJerome Duval {0x52, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 256 entries"}, 731f5facdbSJerome Duval {0x55, "Inst TLB: 2M/4M-bytes pages, fully associative, 7 entries"}, 741f5facdbSJerome Duval {0x56, "L1 Data TLB: 4M-bytes pages, 4-way set associative, 16 entries"}, 751f5facdbSJerome Duval {0x57, "L1 Data TLB: 4K-bytes pages, 4-way set associative, 16 entries"}, 761f5facdbSJerome Duval {0x59, "L0 Data TLB, 4K-bytes pages, fully associative, 16 entries"}, 771f5facdbSJerome Duval {0x5A, "Data TLB: 2M/4M-bytes pages, 4-way set associative, 32 entries"}, 781f5facdbSJerome Duval {0x5B, "Data TLB: 4K/4M-bytes pages, fully associative, 64 entries"}, 791f5facdbSJerome Duval {0x5C, "Data TLB: 4K/4M-bytes pages, fully associative, 128 entries"}, 801f5facdbSJerome Duval {0x5D, "Data TLB: 4K/4M-bytes pages, fully associative, 256 entries"}, 811f5facdbSJerome Duval {0x66, "L1 data cache: 8 KB, 4-way set associative, 64 bytes/line, sectored"}, 821f5facdbSJerome Duval {0x67, "L1 data cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"}, 831f5facdbSJerome Duval {0x68, "L1 data cache: 32 KB, 4-way set associative, 64 bytes/line, sectored"}, 841f5facdbSJerome Duval {0x70, "Inst trace cache: 12K µOPs, 8-way set associative"}, 851f5facdbSJerome Duval {0x71, "Inst trace cache: 16K µOPs, 8-way set associative"}, 861f5facdbSJerome Duval {0x72, "Inst trace cache: 32K µOPs, 8-way set associative"}, 871f5facdbSJerome Duval {0x77, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"}, 881f5facdbSJerome Duval {0x79, "L2 cache: 128 KB, 8-way set associative, 64 bytes/line, dual-sectored"}, 891f5facdbSJerome Duval {0x7A, "L2 cache: 256 KB, 8-way set associative, 64 bytes/line, dual-sectored"}, 901f5facdbSJerome Duval {0x7B, "L2 cache: 512 KB, 8-way set associative, 64 bytes/line, dual-sectored"}, 911f5facdbSJerome Duval {0x7C, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line, dual-sectored"}, 921f5facdbSJerome Duval {0x7D, "L2 cache: 2048 KB, 8-way set associative, 64 bytes/line"}, 931f5facdbSJerome Duval {0x7E, /* IA-64 */ "L2 cache: 256 KB, 8-way set associative, 128 bytes/line, sectored"}, 941f5facdbSJerome Duval {0x7F, "L2 cache: 512 KB, 2-way set associative, 64 bytes/line"}, 951f5facdbSJerome Duval {0x81, "L2 cache: 128 KB, 8-way set associative, 32 bytes/line"}, 961f5facdbSJerome Duval {0x82, "L2 cache: 256 KB, 8-way set associative, 32 bytes/line"}, 971f5facdbSJerome Duval {0x83, "L2 cache: 512 KB, 8-way set associative, 32 bytes/line"}, 981f5facdbSJerome Duval {0x84, "L2 cache: 1024 KB, 8-way set associative, 32 bytes/line"}, 991f5facdbSJerome Duval {0x85, "L2 cache: 2048 KB, 8-way set associative, 32 bytes/line"}, 1001f5facdbSJerome Duval {0x86, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line"}, 1011f5facdbSJerome Duval {0x87, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line"}, 1021f5facdbSJerome Duval {0x88, /* IA-64 */ "L3 cache: 2 MB, 4-way set associative, 64 bytes/line"}, 1031f5facdbSJerome Duval {0x89, /* IA-64 */ "L3 cache: 4 MB, 4-way set associative, 64 bytes/line"}, 1041f5facdbSJerome Duval {0x8A, /* IA-64 */ "L3 cache: 8 MB, 4-way set associative, 64 bytes/line"}, 1051f5facdbSJerome Duval {0x8D, /* IA-64 */ "L3 cache: 3 MB, 12-way set associative, 128 bytes/line"}, 1061f5facdbSJerome Duval {0x90, /* IA-64 */ "Inst TLB: 4K-256Mbytes pages, fully associative, 64 entries"}, 1071f5facdbSJerome Duval {0x96, /* IA-64 */ "L1 data TLB: 4K-256M bytes pages, fully associative, 32 entries"}, 1081f5facdbSJerome Duval {0x9B, /* IA-64 */ "L2 data TLB: 4K-256M bytes pages, fully associative, 96 entries"}, 1091f5facdbSJerome Duval // {0x70, "Cyrix specific: Code and data TLB: 4k-bytes pages, 4-way set associative, 32 entries"}, 1101f5facdbSJerome Duval // {0x74, "Cyrix specific: ???"}, 1111f5facdbSJerome Duval // {0x77, "Cyrix specific: ???"}, 1121f5facdbSJerome Duval {0x80, /* Cyrix specific */ "L1 cache: 16 KB, 4-way set associative, 16 bytes/line"}, 1131f5facdbSJerome Duval // {0x82, "Cyrix specific: ???"}, 1141f5facdbSJerome Duval // {0x84, "Cyrix specific: ???"}, 1151f5facdbSJerome Duval {0xB0, "Inst TLB: 4K-bytes pages, 4-way set associative, 128 entries"}, 1161f5facdbSJerome Duval {0xB1, "Inst TLB: 2M-bytes pages, 4-way set associative, 8 entries OR 4M, 4-way, 4 entries"}, 1171f5facdbSJerome Duval // Intel doesn't give any details how to determine which of the two options is the case 1181f5facdbSJerome Duval // as per Intel Application Note 485, November 2008. 1191f5facdbSJerome Duval {0xB2, "Inst TLB: 4K-bytes pages, 4-way set associative, 64 entries"}, 1201f5facdbSJerome Duval {0xB3, "Data TLB: 4K-bytes pages, 4-way set associative, 128 entries"}, 1211f5facdbSJerome Duval {0xB4, "Data TLB: 4K-bytes pages, 4-way set associative, 256 entries"}, 1221f5facdbSJerome Duval {0xBA, "Data TLB, 4K-bytes pages, 4-way set associative, 64 entries"}, 1231f5facdbSJerome Duval {0xC0, "Data TLB, 4K-4M bytes pages, 4-way set associative, 8 entries"}, 1241f5facdbSJerome Duval {0xCA, "Shared 2nd-level TLB: 4K, 4-way set associative, 512 entries"}, 1251f5facdbSJerome Duval {0xD0, "L3 cache: 512 KB, 4-way set associative, 64-bytes/line"}, 1261f5facdbSJerome Duval {0xD1, "L3 cache: 1024 KB, 4-way set associative, 64-bytes/line"}, 1271f5facdbSJerome Duval {0xD2, "L3 cache: 2048 KB, 4-way set associative, 64-bytes/line"}, 1281f5facdbSJerome Duval {0xD6, "L3 cache: 1024 KB, 8-way set associative, 64-bytes/line"}, 1291f5facdbSJerome Duval {0xD7, "L3 cache: 2048 KB, 8-way set associative, 64-bytes/line"}, 1301f5facdbSJerome Duval {0xD8, "L3 cache: 4096 KB, 8-way set associative, 64-bytes/line"}, 1311f5facdbSJerome Duval {0xDC, "L3 cache: 2048 KB, 12-way set associative, 64-bytes/line"}, 1321f5facdbSJerome Duval {0xDD, "L3 cache: 4096 KB, 12-way set associative, 64-bytes/line"}, 1331f5facdbSJerome Duval {0xDE, "L3 cache: 8192 KB, 12-way set associative, 64-bytes/line"}, 1341f5facdbSJerome Duval {0xE2, "L3 cache: 2048 KB, 16-way set associative, 64-bytes/line"}, 1351f5facdbSJerome Duval {0xE3, "L3 cache: 4096 KB, 16-way set associative, 64-bytes/line"}, 1361f5facdbSJerome Duval {0xE4, "L3 cache: 8192 KB, 16-way set associative, 64-bytes/line"}, 1371f5facdbSJerome Duval {0xF0, "64-byte Prefetching"}, 1381f5facdbSJerome Duval {0xF1, "128-byte Prefetching"}, 1391f5facdbSJerome Duval {0, NULL} 1401f5facdbSJerome Duval }; 1411f5facdbSJerome Duval 1421f5facdbSJerome Duval 1431f5facdbSJerome Duval static void 144*1bc7045fSPawel Dziepak print_intel_cache_descriptors(enum cpu_vendor vendor, uint32 model, 145*1bc7045fSPawel Dziepak cpuid_info *info) 1461f5facdbSJerome Duval { 1471f5facdbSJerome Duval uint8 cacheDescriptors[15]; // Max 1481f5facdbSJerome Duval 1491f5facdbSJerome Duval int maxDesc = 0; 1501f5facdbSJerome Duval int i = 0; 1511f5facdbSJerome Duval 1521f5facdbSJerome Duval // put valid values into array 1531f5facdbSJerome Duval if ((info->regs.eax & 0x80000000) == 0) { 1541f5facdbSJerome Duval // eax is valid, include values 1551f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1561f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1571f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1581f5facdbSJerome Duval } else { 1591f5facdbSJerome Duval i += 3; 1601f5facdbSJerome Duval } 1611f5facdbSJerome Duval if ((info->regs.ebx & 0x80000000) == 0) { 1621f5facdbSJerome Duval // ebx is valid, include values 1631f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1641f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1651f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1661f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1671f5facdbSJerome Duval } else { 1681f5facdbSJerome Duval i += 4; 1691f5facdbSJerome Duval } 1701f5facdbSJerome Duval if ((info->regs.edx & 0x80000000) == 0) { 1711f5facdbSJerome Duval // edx is valid, include values 1721f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1731f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1741f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1751f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1761f5facdbSJerome Duval } else { 1771f5facdbSJerome Duval i += 4; 1781f5facdbSJerome Duval } 1791f5facdbSJerome Duval if ((info->regs.ecx & 0x80000000) == 0) { 1801f5facdbSJerome Duval // ecx is valid, include values 1811f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1821f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1831f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1841f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1851f5facdbSJerome Duval } 1861f5facdbSJerome Duval 1871f5facdbSJerome Duval putchar('\n'); 1881f5facdbSJerome Duval 1891f5facdbSJerome Duval for (int i = 0; i < maxDesc; i++) { 1901f5facdbSJerome Duval // ignore NULL descriptors 1911f5facdbSJerome Duval if (cacheDescriptors[i] == 0) 1921f5facdbSJerome Duval continue; 1931f5facdbSJerome Duval 1941f5facdbSJerome Duval int j; 1951f5facdbSJerome Duval for (j = 0; sIntelCacheDescriptions[j].code; j++) { 1961f5facdbSJerome Duval if (cacheDescriptors[i] == sIntelCacheDescriptions[j].code) { 1971f5facdbSJerome Duval if (cacheDescriptors[i] == 0x40) { 1981f5facdbSJerome Duval printf("\tNo integrated L%u cache\n", 199*1bc7045fSPawel Dziepak ((model >> 8) & 0xf) == 0xf 200*1bc7045fSPawel Dziepak && vendor == B_CPU_VENDOR_INTEL ? 3 : 2); 2011f5facdbSJerome Duval } else 2021f5facdbSJerome Duval printf("\t%s\n", sIntelCacheDescriptions[j].description); 2031f5facdbSJerome Duval break; 2041f5facdbSJerome Duval } 2051f5facdbSJerome Duval } 2061f5facdbSJerome Duval 2071f5facdbSJerome Duval // Reached the end without finding a descriptor 2081f5facdbSJerome Duval if (sIntelCacheDescriptions[j].code == 0) 2091f5facdbSJerome Duval printf("\tUnknown cache descriptor 0x%02x\n", cacheDescriptors[i]); 2101f5facdbSJerome Duval } 2111f5facdbSJerome Duval } 2121f5facdbSJerome Duval 213*1bc7045fSPawel Dziepak 214533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 2151f5facdbSJerome Duval 2161f5facdbSJerome Duval 2171f5facdbSJerome Duval static void 2181f5facdbSJerome Duval print_TLB(uint32 reg, const char *pages) 2191f5facdbSJerome Duval { 2201f5facdbSJerome Duval int entries[2]; 2211f5facdbSJerome Duval int ways[2]; 2221f5facdbSJerome Duval const char *name[2] = { "Inst TLB", "Data TLB" }; 2231f5facdbSJerome Duval 2241f5facdbSJerome Duval entries[0] = (reg & 0xff); 2251f5facdbSJerome Duval ways[0] = ((reg >> 8) & 0xff); 2261f5facdbSJerome Duval entries[1] = ((reg >> 16) & 0xff); 2271f5facdbSJerome Duval ways[1] = ((reg >> 24) & 0xff); 2281f5facdbSJerome Duval 2291f5facdbSJerome Duval for (int num = 0; num < 2; num++) { 2301f5facdbSJerome Duval printf("\t%s: %s%s%u entries, ", name[num], 2311f5facdbSJerome Duval pages ? pages : "", pages ? " pages, " : "", entries[num]); 2321f5facdbSJerome Duval 2331f5facdbSJerome Duval if (ways[num] == 0xff) 2341f5facdbSJerome Duval printf("fully associative\n"); 2351f5facdbSJerome Duval else 2361f5facdbSJerome Duval printf("%u-way set associative\n", ways[num]); 2371f5facdbSJerome Duval } 2381f5facdbSJerome Duval } 2391f5facdbSJerome Duval 2401f5facdbSJerome Duval 2411f5facdbSJerome Duval static void 2421f5facdbSJerome Duval print_level2_cache(uint32 reg, const char *name) 2431f5facdbSJerome Duval { 2441f5facdbSJerome Duval uint32 size = (reg >> 16) & 0xffff; 2451f5facdbSJerome Duval uint32 ways = (reg >> 12) & 0xf; 246f1cbaf5cSAxel Dörfler uint32 linesPerTag = (reg >> 8) & 0xf; 247f1cbaf5cSAxel Dörfler // intel does not define this 2481f5facdbSJerome Duval uint32 lineSize = reg & 0xff; 2491f5facdbSJerome Duval 250533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size); 2511f5facdbSJerome Duval if (ways == 0xf) 2521f5facdbSJerome Duval printf("fully associative, "); 2531f5facdbSJerome Duval else if (ways == 0x1) 2541f5facdbSJerome Duval printf("direct-mapped, "); 2551f5facdbSJerome Duval else 2561f5facdbSJerome Duval printf("%lu-way set associative, ", 1UL << (ways / 2)); 257533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 258533f3bb4SAlex Smith lineSize); 2591f5facdbSJerome Duval } 2601f5facdbSJerome Duval 2611f5facdbSJerome Duval 2621f5facdbSJerome Duval static void 2631f5facdbSJerome Duval print_level1_cache(uint32 reg, const char *name) 2641f5facdbSJerome Duval { 2651f5facdbSJerome Duval uint32 size = (reg >> 24) & 0xff; 2661f5facdbSJerome Duval uint32 ways = (reg >> 16) & 0xff; 2671f5facdbSJerome Duval uint32 linesPerTag = (reg >> 8) & 0xff; 2681f5facdbSJerome Duval uint32 lineSize = reg & 0xff; 2691f5facdbSJerome Duval 270533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size); 2711f5facdbSJerome Duval if (ways == 0xff) 2721f5facdbSJerome Duval printf("fully associative, "); 2731f5facdbSJerome Duval else 274533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways); 275533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 276533f3bb4SAlex Smith lineSize); 2771f5facdbSJerome Duval } 2781f5facdbSJerome Duval 2791f5facdbSJerome Duval 280533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 2811f5facdbSJerome Duval 2821f5facdbSJerome Duval static void 2831f5facdbSJerome Duval print_cache_desc(int32 cpu) 2841f5facdbSJerome Duval { 2851f5facdbSJerome Duval cpuid_info info; 2861f5facdbSJerome Duval get_cpuid(&info, 0x80000005, cpu); 2871f5facdbSJerome Duval 2881f5facdbSJerome Duval putchar('\n'); 2891f5facdbSJerome Duval 2901f5facdbSJerome Duval if (info.regs.eax) 2911f5facdbSJerome Duval print_TLB(info.regs.eax, info.regs.ebx ? "2M/4M-byte" : NULL); 2921f5facdbSJerome Duval if (info.regs.ebx) 2931f5facdbSJerome Duval print_TLB(info.regs.ebx, info.regs.eax ? "4K-byte" : NULL); 2941f5facdbSJerome Duval 2951f5facdbSJerome Duval print_level1_cache(info.regs.ecx, "L1 inst cache"); 2961f5facdbSJerome Duval print_level1_cache(info.regs.edx, "L1 data cache"); 2971f5facdbSJerome Duval 2981f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu); 2991f5facdbSJerome Duval print_level2_cache(info.regs.ecx, "L2 cache"); 3001f5facdbSJerome Duval } 3011f5facdbSJerome Duval 302f1cbaf5cSAxel Dörfler 3031f5facdbSJerome Duval static void 3041f5facdbSJerome Duval print_intel_cache_desc(int32 cpu) 3051f5facdbSJerome Duval { 3061f5facdbSJerome Duval cpuid_info info; 3071f5facdbSJerome Duval 308f1cbaf5cSAxel Dörfler // A second parameters needs to be passed to CPUID which determines the 309f1cbaf5cSAxel Dörfler // cache level to query 3101f5facdbSJerome Duval get_cpuid(&info, 0x00000004, cpu); 3111f5facdbSJerome Duval 3121f5facdbSJerome Duval putchar('\n'); 3131f5facdbSJerome Duval 3141f5facdbSJerome Duval uint32 type = info.regs.eax & 0xf; 3151f5facdbSJerome Duval uint32 level = (info.regs.eax & 0x70) >> 4; 3161f5facdbSJerome Duval bool isFullyAssoc = info.regs.eax & 0x100; 3171f5facdbSJerome Duval 3181f5facdbSJerome Duval uint32 lineSize = (info.regs.ebx & 0xfff) + 1; 3191f5facdbSJerome Duval uint32 linesPerTag = ((info.regs.ebx & 0x3ff000) >> 12) + 1; 3201f5facdbSJerome Duval uint32 ways = ((info.regs.ebx & 0xffc00000) >> 22) + 1; 3211f5facdbSJerome Duval 3221f5facdbSJerome Duval uint32 sets = info.regs.ecx; 3231f5facdbSJerome Duval 324533f3bb4SAlex Smith printf("\tL%" B_PRId32 " ",level); 3251f5facdbSJerome Duval 3261f5facdbSJerome Duval switch (type) { 3271f5facdbSJerome Duval case 1: printf("Data cache "); break; 3281f5facdbSJerome Duval case 2: printf("Inst cache "); break; 3291f5facdbSJerome Duval case 3: printf("Unified cache "); break; 3301f5facdbSJerome Duval default: break; 3311f5facdbSJerome Duval } 3321f5facdbSJerome Duval 3331f5facdbSJerome Duval if (isFullyAssoc) 3341f5facdbSJerome Duval printf("fully associative, "); 3351f5facdbSJerome Duval else 336533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways); 337533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 338533f3bb4SAlex Smith lineSize); 3391f5facdbSJerome Duval 3401f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu); 3411f5facdbSJerome Duval print_level2_cache(sets, "L2 cache"); 3421f5facdbSJerome Duval } 3431f5facdbSJerome Duval 3441f5facdbSJerome Duval 3451f5facdbSJerome Duval static void 3461f5facdbSJerome Duval print_transmeta_features(uint32 features) 3471f5facdbSJerome Duval { 3481f5facdbSJerome Duval if (features & (1 << 16)) 3491f5facdbSJerome Duval printf("\t\tFCMOV\n"); 3501f5facdbSJerome Duval } 3511f5facdbSJerome Duval 352533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 3531f5facdbSJerome Duval 3541f5facdbSJerome Duval 3551f5facdbSJerome Duval static void 3561f5facdbSJerome Duval print_amd_power_management_features(uint32 features) 3571f5facdbSJerome Duval { 3581f5facdbSJerome Duval static const char *kFeatures[6] = { 3591f5facdbSJerome Duval "TS", "FID", "VID", "TTP", "TM", "STC", 3601f5facdbSJerome Duval }; 3611f5facdbSJerome Duval int32 found = 4; 3621f5facdbSJerome Duval 3631f5facdbSJerome Duval printf("\tPower Management Features:"); 3641f5facdbSJerome Duval 3651f5facdbSJerome Duval for (int32 i = 0; i < 6; i++) { 3661f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 3671f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 3681f5facdbSJerome Duval found++; 3691f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 3701f5facdbSJerome Duval putchar('\n'); 3711f5facdbSJerome Duval found = 0; 3721f5facdbSJerome Duval } 3731f5facdbSJerome Duval } 3741f5facdbSJerome Duval } 3751f5facdbSJerome Duval 3761f5facdbSJerome Duval if (found != 0) 3771f5facdbSJerome Duval putchar('\n'); 3781f5facdbSJerome Duval } 3791f5facdbSJerome Duval 3801f5facdbSJerome Duval 3811f5facdbSJerome Duval static void 3821f5facdbSJerome Duval print_amd_features(uint32 features) 3831f5facdbSJerome Duval { 3841f5facdbSJerome Duval static const char *kFeatures[32] = { 3851f5facdbSJerome Duval NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3861f5facdbSJerome Duval NULL, NULL, NULL, "SCE", NULL, NULL, NULL, NULL, 3871f5facdbSJerome Duval NULL, NULL, NULL, NULL, "NX", NULL, "AMD-MMX", NULL, 3881f5facdbSJerome Duval NULL, "FFXSTR", NULL, "RDTSCP", NULL, "64", "3DNow+", "3DNow!" 3891f5facdbSJerome Duval }; 3901f5facdbSJerome Duval int32 found = 0; 3911f5facdbSJerome Duval 3921f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 3931f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 3941f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 3951f5facdbSJerome Duval found++; 3961f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 3971f5facdbSJerome Duval putchar('\n'); 3981f5facdbSJerome Duval found = 0; 3991f5facdbSJerome Duval } 4001f5facdbSJerome Duval } 4011f5facdbSJerome Duval } 4021f5facdbSJerome Duval 4031f5facdbSJerome Duval if (found != 0) 4041f5facdbSJerome Duval putchar('\n'); 4051f5facdbSJerome Duval } 4061f5facdbSJerome Duval 4071f5facdbSJerome Duval 4081f5facdbSJerome Duval static void 4091f5facdbSJerome Duval print_extended_features(uint32 features) 4101f5facdbSJerome Duval { 4111f5facdbSJerome Duval static const char *kFeatures[32] = { 4121f5facdbSJerome Duval "SSE3", "PCLMULDQ", "DTES64", "MONITOR", "DS-CPL", "VMX", "SMX", "EST", 4138bf3802fSDavid Höppner "TM2", "SSSE3", "CNTXT-ID", NULL, "FMA", "CX16", "xTPR", "PDCM", 4148bf3802fSDavid Höppner NULL, "PCID", "DCA", "SSE4.1", "SSE4.2", "x2APIC", "MOVEB", "POPCNT", 4158bf3802fSDavid Höppner "TSC-DEADLINE", "AES", "XSAVE", "OSXSAVE", "AVX", "F16C", "RDRND", 4168bf3802fSDavid Höppner "HYPERVISOR" 4171f5facdbSJerome Duval }; 4181f5facdbSJerome Duval int32 found = 0; 4191f5facdbSJerome Duval 4201f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 4211f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 4221f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 4231f5facdbSJerome Duval found++; 4241f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 4251f5facdbSJerome Duval putchar('\n'); 4261f5facdbSJerome Duval found = 0; 4271f5facdbSJerome Duval } 4281f5facdbSJerome Duval } 4291f5facdbSJerome Duval } 4301f5facdbSJerome Duval 4311f5facdbSJerome Duval if (found != 0) 4321f5facdbSJerome Duval putchar('\n'); 4331f5facdbSJerome Duval } 4341f5facdbSJerome Duval 4351f5facdbSJerome Duval 4361f5facdbSJerome Duval static void 4371f5facdbSJerome Duval print_features(uint32 features) 4381f5facdbSJerome Duval { 4391f5facdbSJerome Duval static const char *kFeatures[32] = { 4401f5facdbSJerome Duval "FPU", "VME", "DE", "PSE", 4411f5facdbSJerome Duval "TSC", "MSR", "PAE", "MCE", 4421f5facdbSJerome Duval "CX8", "APIC", NULL, "SEP", 4431f5facdbSJerome Duval "MTRR", "PGE", "MCA", "CMOV", 4441f5facdbSJerome Duval "PAT", "PSE36", "PSN", "CFLUSH", 4451f5facdbSJerome Duval NULL, "DS", "ACPI", "MMX", 4461f5facdbSJerome Duval "FXSTR", "SSE", "SSE2", "SS", 4471f5facdbSJerome Duval "HTT", "TM", NULL, "PBE", 4481f5facdbSJerome Duval }; 4491f5facdbSJerome Duval int32 found = 0; 4501f5facdbSJerome Duval 4511f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 4521f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 4531f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 4541f5facdbSJerome Duval found++; 4551f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 4561f5facdbSJerome Duval putchar('\n'); 4571f5facdbSJerome Duval found = 0; 4581f5facdbSJerome Duval } 4591f5facdbSJerome Duval } 4601f5facdbSJerome Duval } 4611f5facdbSJerome Duval 4621f5facdbSJerome Duval if (found != 0) 4631f5facdbSJerome Duval putchar('\n'); 4641f5facdbSJerome Duval } 4651f5facdbSJerome Duval 4661f5facdbSJerome Duval 467533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 4681f5facdbSJerome Duval 4691f5facdbSJerome Duval static void 470*1bc7045fSPawel Dziepak print_processor_signature(enum cpu_vendor vendor, cpuid_info *info, 471f1cbaf5cSAxel Dörfler const char *prefix) 4721f5facdbSJerome Duval { 4731f5facdbSJerome Duval 474*1bc7045fSPawel Dziepak if (vendor == B_CPU_VENDOR_AMD) { 47511c9f9a1SAlex Smith printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32 47611c9f9a1SAlex Smith ", stepping %" B_PRIu32 ", features 0x%08" B_PRIx32 "\n", 4771f5facdbSJerome Duval prefix ? prefix : "", prefix && prefix[0] ? "t" : "T", 4781f5facdbSJerome Duval info->eax_1.type, 479f1cbaf5cSAxel Dörfler info->eax_1.family + (info->eax_1.family == 0xf 480f1cbaf5cSAxel Dörfler ? info->eax_1.extended_family : 0), 481f1cbaf5cSAxel Dörfler info->eax_1.model + (info->eax_1.model == 0xf 482f1cbaf5cSAxel Dörfler ? info->eax_1.extended_model << 4 : 0), 4831f5facdbSJerome Duval info->eax_1.stepping, 4841f5facdbSJerome Duval info->eax_1.features); 485*1bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_INTEL) { 4861f5facdbSJerome Duval // model calculation is different for INTEL 48711c9f9a1SAlex Smith printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32 48811c9f9a1SAlex Smith ", stepping %" B_PRIu32 ", features 0x%08" B_PRIx32 "\n", 4891f5facdbSJerome Duval prefix ? prefix : "", prefix && prefix[0] ? "t" : "T", 4901f5facdbSJerome Duval info->eax_1.type, 491f1cbaf5cSAxel Dörfler info->eax_1.family + (info->eax_1.family == 0xf 492f1cbaf5cSAxel Dörfler ? info->eax_1.extended_family : 0), 493f1cbaf5cSAxel Dörfler info->eax_1.model 494f1cbaf5cSAxel Dörfler + ((info->eax_1.family == 0xf || info->eax_1.family == 0x6) 495f1cbaf5cSAxel Dörfler ? info->eax_1.extended_model << 4 : 0), 4961f5facdbSJerome Duval info->eax_1.stepping, 4971f5facdbSJerome Duval info->eax_1.features); 4981f5facdbSJerome Duval } 4991f5facdbSJerome Duval } 5001f5facdbSJerome Duval 501533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 5021f5facdbSJerome Duval 5031f5facdbSJerome Duval 5041f5facdbSJerome Duval static void 5051f5facdbSJerome Duval dump_platform(system_info *info) 5061f5facdbSJerome Duval { 507*1bc7045fSPawel Dziepak cpu_topology_node_info root; 508*1bc7045fSPawel Dziepak uint32 count = 1; 509*1bc7045fSPawel Dziepak get_cpu_topology_info(&root, &count); 510*1bc7045fSPawel Dziepak 511*1bc7045fSPawel Dziepak const char* platform; 512*1bc7045fSPawel Dziepak switch (root.data.root.platform) { 513*1bc7045fSPawel Dziepak case B_CPU_x86: 514*1bc7045fSPawel Dziepak platform = "IntelArchitecture"; 515*1bc7045fSPawel Dziepak break; 516*1bc7045fSPawel Dziepak 517*1bc7045fSPawel Dziepak case B_CPU_x86_64: 518*1bc7045fSPawel Dziepak platform = "IntelArchitecture (64 bit)"; 519*1bc7045fSPawel Dziepak break; 520*1bc7045fSPawel Dziepak 521*1bc7045fSPawel Dziepak default: 522*1bc7045fSPawel Dziepak platform = "unknown"; 523*1bc7045fSPawel Dziepak break; 524*1bc7045fSPawel Dziepak } 525*1bc7045fSPawel Dziepak 526*1bc7045fSPawel Dziepak printf("%s\n", platform); 5271f5facdbSJerome Duval } 5281f5facdbSJerome Duval 5291f5facdbSJerome Duval 530533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 5311f5facdbSJerome Duval 5321f5facdbSJerome Duval static void 533*1bc7045fSPawel Dziepak dump_cpu(enum cpu_vendor vendor, uint32 model, int32 cpu) 5341f5facdbSJerome Duval { 535f1cbaf5cSAxel Dörfler // References: 536f1cbaf5cSAxel Dörfler // http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html 537f1cbaf5cSAxel Dörfler // http://www.sandpile.org/ia32/cpuid.htm 538f1cbaf5cSAxel Dörfler // http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/TN13.pdf (Duron erratum) 5391f5facdbSJerome Duval 5401f5facdbSJerome Duval cpuid_info baseInfo; 5411f5facdbSJerome Duval if (get_cpuid(&baseInfo, 0, cpu) != B_OK) { 5421f5facdbSJerome Duval // this CPU doesn't support cpuid 5431f5facdbSJerome Duval return; 5441f5facdbSJerome Duval } 5451f5facdbSJerome Duval 5461f5facdbSJerome Duval int32 maxStandardFunction = baseInfo.eax_0.max_eax; 547f1cbaf5cSAxel Dörfler if (maxStandardFunction >= 500) { 548f1cbaf5cSAxel Dörfler // old Pentium sample chips has cpu signature here 549f1cbaf5cSAxel Dörfler maxStandardFunction = 0; 550f1cbaf5cSAxel Dörfler } 5511f5facdbSJerome Duval 552f1cbaf5cSAxel Dörfler // Extended cpuid 5531f5facdbSJerome Duval 5541f5facdbSJerome Duval cpuid_info cpuInfo; 5551f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000000, cpu); 5561f5facdbSJerome Duval 557f1cbaf5cSAxel Dörfler // Extended cpuid is only supported if max_eax is greater than the 558f1cbaf5cSAxel Dörfler // service id 5591f5facdbSJerome Duval int32 maxExtendedFunction = 0; 5601f5facdbSJerome Duval if (cpuInfo.eax_0.max_eax > 0x80000000) 5611f5facdbSJerome Duval maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff; 5621f5facdbSJerome Duval 5631f5facdbSJerome Duval if (maxExtendedFunction >=4 ) { 5641f5facdbSJerome Duval char buffer[49]; 5651f5facdbSJerome Duval char *name = buffer; 5661f5facdbSJerome Duval 5671f5facdbSJerome Duval memset(buffer, 0, sizeof(buffer)); 5681f5facdbSJerome Duval 5691f5facdbSJerome Duval for (int32 i = 0; i < 3; i++) { 5701f5facdbSJerome Duval cpuid_info nameInfo; 5711f5facdbSJerome Duval get_cpuid(&nameInfo, 0x80000002 + i, cpu); 5721f5facdbSJerome Duval 5731f5facdbSJerome Duval memcpy(name, &nameInfo.regs.eax, 4); 5741f5facdbSJerome Duval memcpy(name + 4, &nameInfo.regs.ebx, 4); 5751f5facdbSJerome Duval memcpy(name + 8, &nameInfo.regs.ecx, 4); 5761f5facdbSJerome Duval memcpy(name + 12, &nameInfo.regs.edx, 4); 5771f5facdbSJerome Duval name += 16; 5781f5facdbSJerome Duval } 5791f5facdbSJerome Duval 5801f5facdbSJerome Duval // cut off leading spaces (names are right aligned) 5811f5facdbSJerome Duval name = buffer; 5821f5facdbSJerome Duval while (name[0] == ' ') 5831f5facdbSJerome Duval name++; 5841f5facdbSJerome Duval 5851f5facdbSJerome Duval // the BIOS may not have set the processor name 5861f5facdbSJerome Duval if (name[0]) 587533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": \"%s\"\n", cpu, name); 5881f5facdbSJerome Duval else { 5891f5facdbSJerome Duval // Intel CPUs don't seem to have the genuine vendor field 590533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": %.12s\n", cpu, 591*1bc7045fSPawel Dziepak vendor == B_CPU_VENDOR_INTEL ? 5921f5facdbSJerome Duval baseInfo.eax_0.vendor_id : cpuInfo.eax_0.vendor_id); 5931f5facdbSJerome Duval } 5941f5facdbSJerome Duval } else { 595533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": %.12s\n", cpu, baseInfo.eax_0.vendor_id); 5961f5facdbSJerome Duval if (maxStandardFunction == 0) 5971f5facdbSJerome Duval return; 5981f5facdbSJerome Duval } 5991f5facdbSJerome Duval 6001f5facdbSJerome Duval get_cpuid(&cpuInfo, 1, cpu); 601*1bc7045fSPawel Dziepak print_processor_signature(vendor, &cpuInfo, NULL); 6021f5facdbSJerome Duval print_features(cpuInfo.eax_1.features); 6031f5facdbSJerome Duval 6041f5facdbSJerome Duval if (maxStandardFunction >= 1) { 6051f5facdbSJerome Duval /* Extended features */ 606533f3bb4SAlex Smith printf("\tExtended Intel: 0x%08" B_PRIx32 "\n", cpuInfo.eax_1.extended_features); 6071f5facdbSJerome Duval print_extended_features(cpuInfo.eax_1.extended_features); 6081f5facdbSJerome Duval } 6091f5facdbSJerome Duval 6101f5facdbSJerome Duval /* Extended CPUID */ 6111f5facdbSJerome Duval if (maxExtendedFunction >= 1) { 6121f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000001, cpu); 613*1bc7045fSPawel Dziepak print_processor_signature(vendor, &cpuInfo, "Extended AMD: "); 6141f5facdbSJerome Duval 615*1bc7045fSPawel Dziepak if (vendor == B_CPU_VENDOR_AMD || vendor == B_CPU_VENDOR_INTEL) { 6161f5facdbSJerome Duval print_amd_features(cpuInfo.regs.edx); 6171f5facdbSJerome Duval if (maxExtendedFunction >= 7) { 6181f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000007, cpu); 6191f5facdbSJerome Duval print_amd_power_management_features(cpuInfo.regs.edx); 6201f5facdbSJerome Duval } 621*1bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_TRANSMETA) 6221f5facdbSJerome Duval print_transmeta_features(cpuInfo.regs.edx); 6231f5facdbSJerome Duval } 6241f5facdbSJerome Duval 6251f5facdbSJerome Duval /* Cache/TLB descriptors */ 6261f5facdbSJerome Duval if (maxExtendedFunction >= 5) { 6271f5facdbSJerome Duval if (!strncmp(baseInfo.eax_0.vendor_id, "CyrixInstead", 12)) { 6281f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x00000002, cpu); 629*1bc7045fSPawel Dziepak print_intel_cache_descriptors(vendor, model, &cpuInfo); 630*1bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_INTEL) { 6311f5facdbSJerome Duval // Intel does not support extended function 5 (but it does 6 hmm) 6321f5facdbSJerome Duval print_intel_cache_desc(cpu); 6331f5facdbSJerome Duval } else { 6341f5facdbSJerome Duval print_cache_desc(cpu); 6351f5facdbSJerome Duval } 6361f5facdbSJerome Duval } 6371f5facdbSJerome Duval 6381f5facdbSJerome Duval if (maxStandardFunction >= 2) { 6391f5facdbSJerome Duval do { 6401f5facdbSJerome Duval get_cpuid(&cpuInfo, 2, cpu); 6411f5facdbSJerome Duval 6421f5facdbSJerome Duval if (cpuInfo.eax_2.call_num > 0) 643*1bc7045fSPawel Dziepak print_intel_cache_descriptors(vendor, model, &cpuInfo); 6441f5facdbSJerome Duval } while (cpuInfo.eax_2.call_num > 1); 6451f5facdbSJerome Duval } 6461f5facdbSJerome Duval 6471f5facdbSJerome Duval /* Serial number */ 6481f5facdbSJerome Duval if (maxStandardFunction >= 3) { 6491f5facdbSJerome Duval cpuid_info flagsInfo; 6501f5facdbSJerome Duval get_cpuid(&flagsInfo, 1, cpu); 6511f5facdbSJerome Duval 6521f5facdbSJerome Duval if (flagsInfo.eax_1.features & (1UL << 18)) { 6531f5facdbSJerome Duval get_cpuid(&cpuInfo, 3, cpu); 654533f3bb4SAlex Smith printf("Serial number: %04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 655533f3bb4SAlex Smith "-%04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 "\n", 656f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features >> 16, 657f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features & 0xffff, 6581f5facdbSJerome Duval cpuInfo.regs.edx >> 16, cpuInfo.regs.edx & 0xffff, 6591f5facdbSJerome Duval cpuInfo.regs.ecx >> 16, cpuInfo.regs.edx & 0xffff); 6601f5facdbSJerome Duval } 6611f5facdbSJerome Duval } 6621f5facdbSJerome Duval 6631f5facdbSJerome Duval putchar('\n'); 6641f5facdbSJerome Duval } 6651f5facdbSJerome Duval 666533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 6671f5facdbSJerome Duval 6681f5facdbSJerome Duval 6691f5facdbSJerome Duval static void 6701f5facdbSJerome Duval dump_cpus(system_info *info) 6711f5facdbSJerome Duval { 672*1bc7045fSPawel Dziepak uint32 topologyNodeCount = 0; 673*1bc7045fSPawel Dziepak cpu_topology_node_info* topology = NULL; 674*1bc7045fSPawel Dziepak get_cpu_topology_info(NULL, &topologyNodeCount); 675*1bc7045fSPawel Dziepak if (topologyNodeCount != 0) 676*1bc7045fSPawel Dziepak topology = new cpu_topology_node_info[topologyNodeCount]; 677*1bc7045fSPawel Dziepak get_cpu_topology_info(topology, &topologyNodeCount); 678*1bc7045fSPawel Dziepak 679*1bc7045fSPawel Dziepak enum cpu_platform platform = B_CPU_UNKNOWN; 680*1bc7045fSPawel Dziepak enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN; 681*1bc7045fSPawel Dziepak uint32 cpuModel = 0; 682*1bc7045fSPawel Dziepak uint64 frequency = 0; 683*1bc7045fSPawel Dziepak for (uint32 i = 0; i < topologyNodeCount; i++) { 684*1bc7045fSPawel Dziepak switch (topology[i].type) { 685*1bc7045fSPawel Dziepak case B_TOPOLOGY_ROOT: 686*1bc7045fSPawel Dziepak platform = topology[i].data.root.platform; 687*1bc7045fSPawel Dziepak break; 688*1bc7045fSPawel Dziepak 689*1bc7045fSPawel Dziepak case B_TOPOLOGY_PACKAGE: 690*1bc7045fSPawel Dziepak cpuVendor = topology[i].data.package.vendor; 691*1bc7045fSPawel Dziepak break; 692*1bc7045fSPawel Dziepak 693*1bc7045fSPawel Dziepak case B_TOPOLOGY_CORE: 694*1bc7045fSPawel Dziepak cpuModel = topology[i].data.core.model; 695*1bc7045fSPawel Dziepak frequency = topology[i].data.core.default_frequency; 696*1bc7045fSPawel Dziepak break; 697*1bc7045fSPawel Dziepak 698*1bc7045fSPawel Dziepak default: 699*1bc7045fSPawel Dziepak break; 700*1bc7045fSPawel Dziepak } 701*1bc7045fSPawel Dziepak } 702*1bc7045fSPawel Dziepak delete[] topology; 703*1bc7045fSPawel Dziepak 704*1bc7045fSPawel Dziepak const char *vendor = get_cpu_vendor_string(cpuVendor); 705*1bc7045fSPawel Dziepak const char *model = get_cpu_model_string(platform, cpuVendor, cpuModel); 7061f5facdbSJerome Duval char modelString[32]; 7071f5facdbSJerome Duval 7081f5facdbSJerome Duval if (model == NULL && vendor == NULL) 7091f5facdbSJerome Duval model = "(Unknown)"; 7101f5facdbSJerome Duval else if (model == NULL) { 7111f5facdbSJerome Duval model = modelString; 712*1bc7045fSPawel Dziepak snprintf(modelString, 32, "(Unknown %" B_PRIx32 ")", cpuModel); 7131f5facdbSJerome Duval } 7141f5facdbSJerome Duval 715533f3bb4SAlex Smith printf("%" B_PRId32 " %s%s%s, revision %04" B_PRIx32 " running at %" 716*1bc7045fSPawel Dziepak B_PRIu64 "MHz\n\n", 7171f5facdbSJerome Duval info->cpu_count, 7181f5facdbSJerome Duval vendor ? vendor : "", vendor ? " " : "", model, 719*1bc7045fSPawel Dziepak cpuModel, 720*1bc7045fSPawel Dziepak frequency / 1000000); 7211f5facdbSJerome Duval 722533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 723*1bc7045fSPawel Dziepak for (uint32 cpu = 0; cpu < info->cpu_count; cpu++) 724*1bc7045fSPawel Dziepak dump_cpu(cpuVendor, cpuModel, cpu); 725533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 7261f5facdbSJerome Duval } 7271f5facdbSJerome Duval 7281f5facdbSJerome Duval 7291f5facdbSJerome Duval static void 7301f5facdbSJerome Duval dump_mem(system_info *info) 7311f5facdbSJerome Duval { 732d1a2f637SAlex Smith printf("%10" B_PRIu64 " bytes free (used/max %10" B_PRIu64 " / %10" 733d1a2f637SAlex Smith B_PRIu64 ")\n", 734d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)(info->max_pages - info->used_pages), 735d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->used_pages, 736d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->max_pages); 737d1a2f637SAlex Smith printf(" (cached %10" B_PRIu64 ")\n", 738d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->cached_pages); 7391f5facdbSJerome Duval } 7401f5facdbSJerome Duval 7411f5facdbSJerome Duval 7421f5facdbSJerome Duval static void 7431f5facdbSJerome Duval dump_sem(system_info *info) 7441f5facdbSJerome Duval { 745533f3bb4SAlex Smith printf("%10" B_PRId32 " semaphores free (used/max %10" B_PRId32 " / %10" 746533f3bb4SAlex Smith B_PRId32 ")\n", 7471f5facdbSJerome Duval info->max_sems - info->used_sems, 7481f5facdbSJerome Duval info->used_sems, info->max_sems); 7491f5facdbSJerome Duval } 7501f5facdbSJerome Duval 7511f5facdbSJerome Duval 7521f5facdbSJerome Duval static void 7531f5facdbSJerome Duval dump_ports(system_info *info) 7541f5facdbSJerome Duval { 755533f3bb4SAlex Smith printf("%10" B_PRId32 " ports free (used/max %10" B_PRId32 " / %10" 756533f3bb4SAlex Smith B_PRId32 ")\n", 7571f5facdbSJerome Duval info->max_ports - info->used_ports, 7581f5facdbSJerome Duval info->used_ports, info->max_ports); 7591f5facdbSJerome Duval } 7601f5facdbSJerome Duval 7611f5facdbSJerome Duval 7621f5facdbSJerome Duval static void 7631f5facdbSJerome Duval dump_thread(system_info *info) 7641f5facdbSJerome Duval { 765533f3bb4SAlex Smith printf("%10" B_PRId32 " threads free (used/max %10" B_PRId32 " / %10" 766533f3bb4SAlex Smith B_PRId32 ")\n", 7671f5facdbSJerome Duval info->max_threads - info->used_threads, 7681f5facdbSJerome Duval info->used_threads, info->max_threads); 7691f5facdbSJerome Duval } 7701f5facdbSJerome Duval 7711f5facdbSJerome Duval 7721f5facdbSJerome Duval static void 7731f5facdbSJerome Duval dump_team(system_info *info) 7741f5facdbSJerome Duval { 775533f3bb4SAlex Smith printf("%10" B_PRId32 " teams free (used/max %10" B_PRId32 " / %10" 776533f3bb4SAlex Smith B_PRId32 ")\n", 7771f5facdbSJerome Duval info->max_teams - info->used_teams, 7781f5facdbSJerome Duval info->used_teams, info->max_teams); 7791f5facdbSJerome Duval } 7801f5facdbSJerome Duval 7811f5facdbSJerome Duval 7821f5facdbSJerome Duval static void 7831f5facdbSJerome Duval dump_kinfo(system_info *info) 7841f5facdbSJerome Duval { 785533f3bb4SAlex Smith printf("Kernel name: %s built on: %s %s version 0x%" B_PRIx64 "\n", 7861f5facdbSJerome Duval info->kernel_name, 7871f5facdbSJerome Duval info->kernel_build_date, info->kernel_build_time, 7881f5facdbSJerome Duval info->kernel_version ); 7891f5facdbSJerome Duval } 7901f5facdbSJerome Duval 7911f5facdbSJerome Duval 7921f5facdbSJerome Duval static void 7931f5facdbSJerome Duval dump_system_info(system_info *info) 7941f5facdbSJerome Duval { 7951f5facdbSJerome Duval dump_kinfo(info); 7961f5facdbSJerome Duval dump_cpus(info); 7971f5facdbSJerome Duval dump_mem(info); 7981f5facdbSJerome Duval dump_sem(info); 7991f5facdbSJerome Duval dump_ports(info); 8001f5facdbSJerome Duval dump_thread(info); 8011f5facdbSJerome Duval dump_team(info); 8021f5facdbSJerome Duval } 8031f5facdbSJerome Duval 8041f5facdbSJerome Duval 8051f5facdbSJerome Duval int 8061f5facdbSJerome Duval main(int argc, char *argv[]) 8071f5facdbSJerome Duval { 8081f5facdbSJerome Duval if (!is_computer_on()) { 8091f5facdbSJerome Duval printf("The computer is not on! No info available\n"); 8101f5facdbSJerome Duval exit(EXIT_FAILURE); 8111f5facdbSJerome Duval } 8121f5facdbSJerome Duval 8131f5facdbSJerome Duval system_info info; 8141f5facdbSJerome Duval if (get_system_info(&info) != B_OK) { 8151f5facdbSJerome Duval printf("Error getting system information!\n"); 8161f5facdbSJerome Duval return 1; 8171f5facdbSJerome Duval } 8181f5facdbSJerome Duval 8191f5facdbSJerome Duval if (argc <= 1) { 8201f5facdbSJerome Duval dump_system_info(&info); 8211f5facdbSJerome Duval } else { 8221f5facdbSJerome Duval for (int i = 1; i < argc; i++) { 8231f5facdbSJerome Duval const char *opt = argv[i]; 8241f5facdbSJerome Duval if (strncmp(opt, "-id", strlen(opt)) == 0) { 8251f5facdbSJerome Duval /* note: the original also assumes this option on "sysinfo -" */ 826*1bc7045fSPawel Dziepak printf("%#.8x %#.8x\n", 0,0); 8271f5facdbSJerome Duval } else if (strncmp(opt, "-cpu", strlen(opt)) == 0) { 8281f5facdbSJerome Duval dump_cpus(&info); 8291f5facdbSJerome Duval } else if (strncmp(opt, "-mem", strlen(opt)) == 0) { 8301f5facdbSJerome Duval dump_mem(&info); 8311f5facdbSJerome Duval } else if (strncmp(opt, "-semaphores", strlen(opt)) == 0) { 8321f5facdbSJerome Duval dump_sem(&info); 8331f5facdbSJerome Duval } else if (strncmp(opt, "-ports", strlen(opt)) == 0) { 8341f5facdbSJerome Duval dump_ports(&info); 8351f5facdbSJerome Duval } else if (strncmp(opt, "-threads", strlen(opt)) == 0) { 8361f5facdbSJerome Duval dump_thread(&info); 8371f5facdbSJerome Duval } else if (strncmp(opt, "-teams", strlen(opt)) == 0) { 8381f5facdbSJerome Duval dump_team(&info); 8391f5facdbSJerome Duval } else if (strncmp(opt, "-kinfo", strlen(opt)) == 0) { 8401f5facdbSJerome Duval dump_kinfo(&info); 8411f5facdbSJerome Duval } else if (strncmp(opt, "-platform", strlen(opt)) == 0) { 8421f5facdbSJerome Duval dump_platform(&info); 8431f5facdbSJerome Duval } else if (strncmp(opt, "-disable_cpu_sn", strlen(opt)) == 0) { 8441f5facdbSJerome Duval /* TODO: printf("CPU #%d serial number: old state: %s, new state: %s\n", ... ); */ 8451f5facdbSJerome Duval fprintf(stderr, "Sorry, not yet implemented\n"); 8461f5facdbSJerome Duval } else { 8471f5facdbSJerome Duval const char *name = strrchr(argv[0], '/'); 8481f5facdbSJerome Duval if (name == NULL) 8491f5facdbSJerome Duval name = argv[0]; 8501f5facdbSJerome Duval else 8511f5facdbSJerome Duval name++; 8521f5facdbSJerome Duval 8531f5facdbSJerome Duval fprintf(stderr, "Usage:\n"); 8541f5facdbSJerome Duval fprintf(stderr, " %s [-id|-cpu|-mem|-semaphore|-ports|-threads|-teams|-platform|-disable_cpu_sn|-kinfo]\n", name); 8551f5facdbSJerome Duval return 0; 8561f5facdbSJerome Duval } 8571f5facdbSJerome Duval } 8581f5facdbSJerome Duval } 8591f5facdbSJerome Duval return 0; 8601f5facdbSJerome Duval } 861