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 1441f5facdbSJerome Duval print_intel_cache_descriptors(enum cpu_types type, cpuid_info *info) 1451f5facdbSJerome Duval { 1461f5facdbSJerome Duval uint8 cacheDescriptors[15]; // Max 1471f5facdbSJerome Duval 1481f5facdbSJerome Duval int maxDesc = 0; 1491f5facdbSJerome Duval int i = 0; 1501f5facdbSJerome Duval 1511f5facdbSJerome Duval // put valid values into array 1521f5facdbSJerome Duval if ((info->regs.eax & 0x80000000) == 0) { 1531f5facdbSJerome Duval // eax is valid, include values 1541f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1551f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1561f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 1571f5facdbSJerome Duval } else { 1581f5facdbSJerome Duval i += 3; 1591f5facdbSJerome Duval } 1601f5facdbSJerome Duval if ((info->regs.ebx & 0x80000000) == 0) { 1611f5facdbSJerome Duval // ebx is valid, include values 1621f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 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 } else { 1671f5facdbSJerome Duval i += 4; 1681f5facdbSJerome Duval } 1691f5facdbSJerome Duval if ((info->regs.edx & 0x80000000) == 0) { 1701f5facdbSJerome Duval // edx is valid, include values 1711f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 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 } else { 1761f5facdbSJerome Duval i += 4; 1771f5facdbSJerome Duval } 1781f5facdbSJerome Duval if ((info->regs.ecx & 0x80000000) == 0) { 1791f5facdbSJerome Duval // ecx is valid, include values 1801f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++]; 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 } 1851f5facdbSJerome Duval 1861f5facdbSJerome Duval putchar('\n'); 1871f5facdbSJerome Duval 1881f5facdbSJerome Duval for (int i = 0; i < maxDesc; i++) { 1891f5facdbSJerome Duval // ignore NULL descriptors 1901f5facdbSJerome Duval if (cacheDescriptors[i] == 0) 1911f5facdbSJerome Duval continue; 1921f5facdbSJerome Duval 1931f5facdbSJerome Duval int j; 1941f5facdbSJerome Duval for (j = 0; sIntelCacheDescriptions[j].code; j++) { 1951f5facdbSJerome Duval if (cacheDescriptors[i] == sIntelCacheDescriptions[j].code) { 1961f5facdbSJerome Duval if (cacheDescriptors[i] == 0x40) { 1971f5facdbSJerome Duval printf("\tNo integrated L%u cache\n", 1981f5facdbSJerome Duval type >= B_CPU_INTEL_PENTIUM_IV 199f1cbaf5cSAxel Dörfler && (type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86 200f1cbaf5cSAxel Dörfler ? 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 213533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 2141f5facdbSJerome Duval 2151f5facdbSJerome Duval 2161f5facdbSJerome Duval static void 2171f5facdbSJerome Duval print_TLB(uint32 reg, const char *pages) 2181f5facdbSJerome Duval { 2191f5facdbSJerome Duval int entries[2]; 2201f5facdbSJerome Duval int ways[2]; 2211f5facdbSJerome Duval const char *name[2] = { "Inst TLB", "Data TLB" }; 2221f5facdbSJerome Duval 2231f5facdbSJerome Duval entries[0] = (reg & 0xff); 2241f5facdbSJerome Duval ways[0] = ((reg >> 8) & 0xff); 2251f5facdbSJerome Duval entries[1] = ((reg >> 16) & 0xff); 2261f5facdbSJerome Duval ways[1] = ((reg >> 24) & 0xff); 2271f5facdbSJerome Duval 2281f5facdbSJerome Duval for (int num = 0; num < 2; num++) { 2291f5facdbSJerome Duval printf("\t%s: %s%s%u entries, ", name[num], 2301f5facdbSJerome Duval pages ? pages : "", pages ? " pages, " : "", entries[num]); 2311f5facdbSJerome Duval 2321f5facdbSJerome Duval if (ways[num] == 0xff) 2331f5facdbSJerome Duval printf("fully associative\n"); 2341f5facdbSJerome Duval else 2351f5facdbSJerome Duval printf("%u-way set associative\n", ways[num]); 2361f5facdbSJerome Duval } 2371f5facdbSJerome Duval } 2381f5facdbSJerome Duval 2391f5facdbSJerome Duval 2401f5facdbSJerome Duval static void 2411f5facdbSJerome Duval print_level2_cache(uint32 reg, const char *name) 2421f5facdbSJerome Duval { 2431f5facdbSJerome Duval uint32 size = (reg >> 16) & 0xffff; 2441f5facdbSJerome Duval uint32 ways = (reg >> 12) & 0xf; 245f1cbaf5cSAxel Dörfler uint32 linesPerTag = (reg >> 8) & 0xf; 246f1cbaf5cSAxel Dörfler // intel does not define this 2471f5facdbSJerome Duval uint32 lineSize = reg & 0xff; 2481f5facdbSJerome Duval 249533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size); 2501f5facdbSJerome Duval if (ways == 0xf) 2511f5facdbSJerome Duval printf("fully associative, "); 2521f5facdbSJerome Duval else if (ways == 0x1) 2531f5facdbSJerome Duval printf("direct-mapped, "); 2541f5facdbSJerome Duval else 2551f5facdbSJerome Duval printf("%lu-way set associative, ", 1UL << (ways / 2)); 256533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 257533f3bb4SAlex Smith lineSize); 2581f5facdbSJerome Duval } 2591f5facdbSJerome Duval 2601f5facdbSJerome Duval 2611f5facdbSJerome Duval static void 2621f5facdbSJerome Duval print_level1_cache(uint32 reg, const char *name) 2631f5facdbSJerome Duval { 2641f5facdbSJerome Duval uint32 size = (reg >> 24) & 0xff; 2651f5facdbSJerome Duval uint32 ways = (reg >> 16) & 0xff; 2661f5facdbSJerome Duval uint32 linesPerTag = (reg >> 8) & 0xff; 2671f5facdbSJerome Duval uint32 lineSize = reg & 0xff; 2681f5facdbSJerome Duval 269533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size); 2701f5facdbSJerome Duval if (ways == 0xff) 2711f5facdbSJerome Duval printf("fully associative, "); 2721f5facdbSJerome Duval else 273533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways); 274533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 275533f3bb4SAlex Smith lineSize); 2761f5facdbSJerome Duval } 2771f5facdbSJerome Duval 2781f5facdbSJerome Duval 279533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 2801f5facdbSJerome Duval 2811f5facdbSJerome Duval static void 2821f5facdbSJerome Duval print_cache_desc(int32 cpu) 2831f5facdbSJerome Duval { 2841f5facdbSJerome Duval cpuid_info info; 2851f5facdbSJerome Duval get_cpuid(&info, 0x80000005, cpu); 2861f5facdbSJerome Duval 2871f5facdbSJerome Duval putchar('\n'); 2881f5facdbSJerome Duval 2891f5facdbSJerome Duval if (info.regs.eax) 2901f5facdbSJerome Duval print_TLB(info.regs.eax, info.regs.ebx ? "2M/4M-byte" : NULL); 2911f5facdbSJerome Duval if (info.regs.ebx) 2921f5facdbSJerome Duval print_TLB(info.regs.ebx, info.regs.eax ? "4K-byte" : NULL); 2931f5facdbSJerome Duval 2941f5facdbSJerome Duval print_level1_cache(info.regs.ecx, "L1 inst cache"); 2951f5facdbSJerome Duval print_level1_cache(info.regs.edx, "L1 data cache"); 2961f5facdbSJerome Duval 2971f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu); 2981f5facdbSJerome Duval print_level2_cache(info.regs.ecx, "L2 cache"); 2991f5facdbSJerome Duval } 3001f5facdbSJerome Duval 301f1cbaf5cSAxel Dörfler 3021f5facdbSJerome Duval static void 3031f5facdbSJerome Duval print_intel_cache_desc(int32 cpu) 3041f5facdbSJerome Duval { 3051f5facdbSJerome Duval cpuid_info info; 3061f5facdbSJerome Duval 307f1cbaf5cSAxel Dörfler // A second parameters needs to be passed to CPUID which determines the 308f1cbaf5cSAxel Dörfler // cache level to query 3091f5facdbSJerome Duval get_cpuid(&info, 0x00000004, cpu); 3101f5facdbSJerome Duval 3111f5facdbSJerome Duval putchar('\n'); 3121f5facdbSJerome Duval 3131f5facdbSJerome Duval uint32 type = info.regs.eax & 0xf; 3141f5facdbSJerome Duval uint32 level = (info.regs.eax & 0x70) >> 4; 3151f5facdbSJerome Duval bool isFullyAssoc = info.regs.eax & 0x100; 3161f5facdbSJerome Duval 3171f5facdbSJerome Duval uint32 lineSize = (info.regs.ebx & 0xfff) + 1; 3181f5facdbSJerome Duval uint32 linesPerTag = ((info.regs.ebx & 0x3ff000) >> 12) + 1; 3191f5facdbSJerome Duval uint32 ways = ((info.regs.ebx & 0xffc00000) >> 22) + 1; 3201f5facdbSJerome Duval 3211f5facdbSJerome Duval uint32 sets = info.regs.ecx; 3221f5facdbSJerome Duval 323533f3bb4SAlex Smith printf("\tL%" B_PRId32 " ",level); 3241f5facdbSJerome Duval 3251f5facdbSJerome Duval switch (type) { 3261f5facdbSJerome Duval case 1: printf("Data cache "); break; 3271f5facdbSJerome Duval case 2: printf("Inst cache "); break; 3281f5facdbSJerome Duval case 3: printf("Unified cache "); break; 3291f5facdbSJerome Duval default: break; 3301f5facdbSJerome Duval } 3311f5facdbSJerome Duval 3321f5facdbSJerome Duval if (isFullyAssoc) 3331f5facdbSJerome Duval printf("fully associative, "); 3341f5facdbSJerome Duval else 335533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways); 336533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, 337533f3bb4SAlex Smith lineSize); 3381f5facdbSJerome Duval 3391f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu); 3401f5facdbSJerome Duval print_level2_cache(sets, "L2 cache"); 3411f5facdbSJerome Duval } 3421f5facdbSJerome Duval 3431f5facdbSJerome Duval 3441f5facdbSJerome Duval static void 3451f5facdbSJerome Duval print_transmeta_features(uint32 features) 3461f5facdbSJerome Duval { 3471f5facdbSJerome Duval if (features & (1 << 16)) 3481f5facdbSJerome Duval printf("\t\tFCMOV\n"); 3491f5facdbSJerome Duval } 3501f5facdbSJerome Duval 351533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 3521f5facdbSJerome Duval 3531f5facdbSJerome Duval 3541f5facdbSJerome Duval static void 3551f5facdbSJerome Duval print_amd_power_management_features(uint32 features) 3561f5facdbSJerome Duval { 3571f5facdbSJerome Duval static const char *kFeatures[6] = { 3581f5facdbSJerome Duval "TS", "FID", "VID", "TTP", "TM", "STC", 3591f5facdbSJerome Duval }; 3601f5facdbSJerome Duval int32 found = 4; 3611f5facdbSJerome Duval 3621f5facdbSJerome Duval printf("\tPower Management Features:"); 3631f5facdbSJerome Duval 3641f5facdbSJerome Duval for (int32 i = 0; i < 6; i++) { 3651f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 3661f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 3671f5facdbSJerome Duval found++; 3681f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 3691f5facdbSJerome Duval putchar('\n'); 3701f5facdbSJerome Duval found = 0; 3711f5facdbSJerome Duval } 3721f5facdbSJerome Duval } 3731f5facdbSJerome Duval } 3741f5facdbSJerome Duval 3751f5facdbSJerome Duval if (found != 0) 3761f5facdbSJerome Duval putchar('\n'); 3771f5facdbSJerome Duval } 3781f5facdbSJerome Duval 3791f5facdbSJerome Duval 3801f5facdbSJerome Duval static void 3811f5facdbSJerome Duval print_amd_features(uint32 features) 3821f5facdbSJerome Duval { 3831f5facdbSJerome Duval static const char *kFeatures[32] = { 3841f5facdbSJerome Duval NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 3851f5facdbSJerome Duval NULL, NULL, NULL, "SCE", NULL, NULL, NULL, NULL, 3861f5facdbSJerome Duval NULL, NULL, NULL, NULL, "NX", NULL, "AMD-MMX", NULL, 3871f5facdbSJerome Duval NULL, "FFXSTR", NULL, "RDTSCP", NULL, "64", "3DNow+", "3DNow!" 3881f5facdbSJerome Duval }; 3891f5facdbSJerome Duval int32 found = 0; 3901f5facdbSJerome Duval 3911f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 3921f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 3931f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 3941f5facdbSJerome Duval found++; 3951f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 3961f5facdbSJerome Duval putchar('\n'); 3971f5facdbSJerome Duval found = 0; 3981f5facdbSJerome Duval } 3991f5facdbSJerome Duval } 4001f5facdbSJerome Duval } 4011f5facdbSJerome Duval 4021f5facdbSJerome Duval if (found != 0) 4031f5facdbSJerome Duval putchar('\n'); 4041f5facdbSJerome Duval } 4051f5facdbSJerome Duval 4061f5facdbSJerome Duval 4071f5facdbSJerome Duval static void 4081f5facdbSJerome Duval print_extended_features(uint32 features) 4091f5facdbSJerome Duval { 4101f5facdbSJerome Duval static const char *kFeatures[32] = { 4111f5facdbSJerome Duval "SSE3", "PCLMULDQ", "DTES64", "MONITOR", "DS-CPL", "VMX", "SMX", "EST", 4121f5facdbSJerome Duval "TM2", "SSSE3", "CNTXT-ID", NULL, NULL, "CX16", "xTPR", "PDCM", 4131f5facdbSJerome Duval NULL, NULL, "DCA", "SSE4.1", "SSE4.2", "x2APIC", "MOVEB", "POPCNT", 4141f5facdbSJerome Duval NULL, "AES", "XSAVE", "OSXSAVE", NULL, NULL, NULL, NULL 4151f5facdbSJerome Duval }; 4161f5facdbSJerome Duval int32 found = 0; 4171f5facdbSJerome Duval 4181f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 4191f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 4201f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 4211f5facdbSJerome Duval found++; 4221f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 4231f5facdbSJerome Duval putchar('\n'); 4241f5facdbSJerome Duval found = 0; 4251f5facdbSJerome Duval } 4261f5facdbSJerome Duval } 4271f5facdbSJerome Duval } 4281f5facdbSJerome Duval 4291f5facdbSJerome Duval if (found != 0) 4301f5facdbSJerome Duval putchar('\n'); 4311f5facdbSJerome Duval } 4321f5facdbSJerome Duval 4331f5facdbSJerome Duval 4341f5facdbSJerome Duval static void 4351f5facdbSJerome Duval print_features(uint32 features) 4361f5facdbSJerome Duval { 4371f5facdbSJerome Duval static const char *kFeatures[32] = { 4381f5facdbSJerome Duval "FPU", "VME", "DE", "PSE", 4391f5facdbSJerome Duval "TSC", "MSR", "PAE", "MCE", 4401f5facdbSJerome Duval "CX8", "APIC", NULL, "SEP", 4411f5facdbSJerome Duval "MTRR", "PGE", "MCA", "CMOV", 4421f5facdbSJerome Duval "PAT", "PSE36", "PSN", "CFLUSH", 4431f5facdbSJerome Duval NULL, "DS", "ACPI", "MMX", 4441f5facdbSJerome Duval "FXSTR", "SSE", "SSE2", "SS", 4451f5facdbSJerome Duval "HTT", "TM", NULL, "PBE", 4461f5facdbSJerome Duval }; 4471f5facdbSJerome Duval int32 found = 0; 4481f5facdbSJerome Duval 4491f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) { 4501f5facdbSJerome Duval if ((features & (1UL << i)) && kFeatures[i] != NULL) { 4511f5facdbSJerome Duval printf("%s%s", found == 0 ? "\t\t" : " ", kFeatures[i]); 4521f5facdbSJerome Duval found++; 4531f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) { 4541f5facdbSJerome Duval putchar('\n'); 4551f5facdbSJerome Duval found = 0; 4561f5facdbSJerome Duval } 4571f5facdbSJerome Duval } 4581f5facdbSJerome Duval } 4591f5facdbSJerome Duval 4601f5facdbSJerome Duval if (found != 0) 4611f5facdbSJerome Duval putchar('\n'); 4621f5facdbSJerome Duval } 4631f5facdbSJerome Duval 4641f5facdbSJerome Duval 465533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 4661f5facdbSJerome Duval 4671f5facdbSJerome Duval static void 468f1cbaf5cSAxel Dörfler print_processor_signature(system_info *sys_info, cpuid_info *info, 469f1cbaf5cSAxel Dörfler const char *prefix) 4701f5facdbSJerome Duval { 4711f5facdbSJerome Duval 4721f5facdbSJerome Duval if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86) { 473*11c9f9a1SAlex Smith 474*11c9f9a1SAlex Smith printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32 475*11c9f9a1SAlex Smith ", stepping %" B_PRIu32 ", features 0x%08" B_PRIx32 "\n", 4761f5facdbSJerome Duval prefix ? prefix : "", prefix && prefix[0] ? "t" : "T", 4771f5facdbSJerome Duval info->eax_1.type, 478f1cbaf5cSAxel Dörfler info->eax_1.family + (info->eax_1.family == 0xf 479f1cbaf5cSAxel Dörfler ? info->eax_1.extended_family : 0), 480f1cbaf5cSAxel Dörfler info->eax_1.model + (info->eax_1.model == 0xf 481f1cbaf5cSAxel Dörfler ? info->eax_1.extended_model << 4 : 0), 4821f5facdbSJerome Duval info->eax_1.stepping, 4831f5facdbSJerome Duval info->eax_1.features); 484f1cbaf5cSAxel Dörfler } else if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) 485f1cbaf5cSAxel Dörfler == B_CPU_INTEL_x86) { 4861f5facdbSJerome Duval // model calculation is different for INTEL 487*11c9f9a1SAlex Smith printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32 488*11c9f9a1SAlex 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 { 5071f5facdbSJerome Duval printf("%s\n", 5081f5facdbSJerome Duval info->platform_type == B_AT_CLONE_PLATFORM ? "IntelArchitecture" : 5091f5facdbSJerome Duval info->platform_type == B_MAC_PLATFORM ? "Macintosh" : 5101f5facdbSJerome Duval info->platform_type == B_BEBOX_PLATFORM ? "BeBox" : "unknown"); 5111f5facdbSJerome Duval } 5121f5facdbSJerome Duval 5131f5facdbSJerome Duval 514533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 5151f5facdbSJerome Duval 5161f5facdbSJerome Duval static void 5171f5facdbSJerome Duval dump_cpu(system_info *info, int32 cpu) 5181f5facdbSJerome Duval { 519f1cbaf5cSAxel Dörfler // References: 520f1cbaf5cSAxel Dörfler // http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html 521f1cbaf5cSAxel Dörfler // http://www.sandpile.org/ia32/cpuid.htm 522f1cbaf5cSAxel Dörfler // http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/TN13.pdf (Duron erratum) 5231f5facdbSJerome Duval 5241f5facdbSJerome Duval cpuid_info baseInfo; 5251f5facdbSJerome Duval if (get_cpuid(&baseInfo, 0, cpu) != B_OK) { 5261f5facdbSJerome Duval // this CPU doesn't support cpuid 5271f5facdbSJerome Duval return; 5281f5facdbSJerome Duval } 5291f5facdbSJerome Duval 5301f5facdbSJerome Duval int32 maxStandardFunction = baseInfo.eax_0.max_eax; 531f1cbaf5cSAxel Dörfler if (maxStandardFunction >= 500) { 532f1cbaf5cSAxel Dörfler // old Pentium sample chips has cpu signature here 533f1cbaf5cSAxel Dörfler maxStandardFunction = 0; 534f1cbaf5cSAxel Dörfler } 5351f5facdbSJerome Duval 536f1cbaf5cSAxel Dörfler // Extended cpuid 5371f5facdbSJerome Duval 5381f5facdbSJerome Duval cpuid_info cpuInfo; 5391f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000000, cpu); 5401f5facdbSJerome Duval 541f1cbaf5cSAxel Dörfler // Extended cpuid is only supported if max_eax is greater than the 542f1cbaf5cSAxel Dörfler // service id 5431f5facdbSJerome Duval int32 maxExtendedFunction = 0; 5441f5facdbSJerome Duval if (cpuInfo.eax_0.max_eax > 0x80000000) 5451f5facdbSJerome Duval maxExtendedFunction = cpuInfo.eax_0.max_eax & 0xff; 5461f5facdbSJerome Duval 5471f5facdbSJerome Duval if (maxExtendedFunction >=4 ) { 5481f5facdbSJerome Duval char buffer[49]; 5491f5facdbSJerome Duval char *name = buffer; 5501f5facdbSJerome Duval 5511f5facdbSJerome Duval memset(buffer, 0, sizeof(buffer)); 5521f5facdbSJerome Duval 5531f5facdbSJerome Duval for (int32 i = 0; i < 3; i++) { 5541f5facdbSJerome Duval cpuid_info nameInfo; 5551f5facdbSJerome Duval get_cpuid(&nameInfo, 0x80000002 + i, cpu); 5561f5facdbSJerome Duval 5571f5facdbSJerome Duval memcpy(name, &nameInfo.regs.eax, 4); 5581f5facdbSJerome Duval memcpy(name + 4, &nameInfo.regs.ebx, 4); 5591f5facdbSJerome Duval memcpy(name + 8, &nameInfo.regs.ecx, 4); 5601f5facdbSJerome Duval memcpy(name + 12, &nameInfo.regs.edx, 4); 5611f5facdbSJerome Duval name += 16; 5621f5facdbSJerome Duval } 5631f5facdbSJerome Duval 5641f5facdbSJerome Duval // cut off leading spaces (names are right aligned) 5651f5facdbSJerome Duval name = buffer; 5661f5facdbSJerome Duval while (name[0] == ' ') 5671f5facdbSJerome Duval name++; 5681f5facdbSJerome Duval 5691f5facdbSJerome Duval // the BIOS may not have set the processor name 5701f5facdbSJerome Duval if (name[0]) 571533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": \"%s\"\n", cpu, name); 5721f5facdbSJerome Duval else { 5731f5facdbSJerome Duval // Intel CPUs don't seem to have the genuine vendor field 574533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": %.12s\n", cpu, 5751f5facdbSJerome Duval (info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86 ? 5761f5facdbSJerome Duval baseInfo.eax_0.vendor_id : cpuInfo.eax_0.vendor_id); 5771f5facdbSJerome Duval } 5781f5facdbSJerome Duval } else { 579533f3bb4SAlex Smith printf("CPU #%" B_PRId32 ": %.12s\n", cpu, baseInfo.eax_0.vendor_id); 5801f5facdbSJerome Duval if (maxStandardFunction == 0) 5811f5facdbSJerome Duval return; 5821f5facdbSJerome Duval } 5831f5facdbSJerome Duval 5841f5facdbSJerome Duval get_cpuid(&cpuInfo, 1, cpu); 5851f5facdbSJerome Duval print_processor_signature(info, &cpuInfo, NULL); 5861f5facdbSJerome Duval print_features(cpuInfo.eax_1.features); 5871f5facdbSJerome Duval 5881f5facdbSJerome Duval if (maxStandardFunction >= 1) { 5891f5facdbSJerome Duval /* Extended features */ 590533f3bb4SAlex Smith printf("\tExtended Intel: 0x%08" B_PRIx32 "\n", cpuInfo.eax_1.extended_features); 5911f5facdbSJerome Duval print_extended_features(cpuInfo.eax_1.extended_features); 5921f5facdbSJerome Duval } 5931f5facdbSJerome Duval 5941f5facdbSJerome Duval /* Extended CPUID */ 5951f5facdbSJerome Duval if (maxExtendedFunction >= 1) { 5961f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000001, cpu); 5971f5facdbSJerome Duval print_processor_signature(info, &cpuInfo, "Extended AMD: "); 5981f5facdbSJerome Duval 5991f5facdbSJerome Duval if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86 6001f5facdbSJerome Duval || (info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) { 6011f5facdbSJerome Duval print_amd_features(cpuInfo.regs.edx); 6021f5facdbSJerome Duval if (maxExtendedFunction >= 7) { 6031f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000007, cpu); 6041f5facdbSJerome Duval print_amd_power_management_features(cpuInfo.regs.edx); 6051f5facdbSJerome Duval } 606f1cbaf5cSAxel Dörfler } else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) 607f1cbaf5cSAxel Dörfler == B_CPU_TRANSMETA_x86) 6081f5facdbSJerome Duval print_transmeta_features(cpuInfo.regs.edx); 6091f5facdbSJerome Duval } 6101f5facdbSJerome Duval 6111f5facdbSJerome Duval /* Cache/TLB descriptors */ 6121f5facdbSJerome Duval if (maxExtendedFunction >= 5) { 6131f5facdbSJerome Duval if (!strncmp(baseInfo.eax_0.vendor_id, "CyrixInstead", 12)) { 6141f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x00000002, cpu); 6151f5facdbSJerome Duval print_intel_cache_descriptors(info->cpu_type, &cpuInfo); 616f1cbaf5cSAxel Dörfler } else if ((info->cpu_type & B_CPU_x86_VENDOR_MASK) 617f1cbaf5cSAxel Dörfler == B_CPU_INTEL_x86) { 6181f5facdbSJerome Duval // Intel does not support extended function 5 (but it does 6 hmm) 6191f5facdbSJerome Duval print_intel_cache_desc(cpu); 6201f5facdbSJerome Duval } else { 6211f5facdbSJerome Duval print_cache_desc(cpu); 6221f5facdbSJerome Duval } 6231f5facdbSJerome Duval } 6241f5facdbSJerome Duval 6251f5facdbSJerome Duval if (maxStandardFunction >= 2) { 6261f5facdbSJerome Duval do { 6271f5facdbSJerome Duval get_cpuid(&cpuInfo, 2, cpu); 6281f5facdbSJerome Duval 6291f5facdbSJerome Duval if (cpuInfo.eax_2.call_num > 0) 6301f5facdbSJerome Duval print_intel_cache_descriptors(info->cpu_type, &cpuInfo); 6311f5facdbSJerome Duval } while (cpuInfo.eax_2.call_num > 1); 6321f5facdbSJerome Duval } 6331f5facdbSJerome Duval 6341f5facdbSJerome Duval /* Serial number */ 6351f5facdbSJerome Duval if (maxStandardFunction >= 3) { 6361f5facdbSJerome Duval cpuid_info flagsInfo; 6371f5facdbSJerome Duval get_cpuid(&flagsInfo, 1, cpu); 6381f5facdbSJerome Duval 6391f5facdbSJerome Duval if (flagsInfo.eax_1.features & (1UL << 18)) { 6401f5facdbSJerome Duval get_cpuid(&cpuInfo, 3, cpu); 641533f3bb4SAlex Smith printf("Serial number: %04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 642533f3bb4SAlex Smith "-%04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 "\n", 643f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features >> 16, 644f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features & 0xffff, 6451f5facdbSJerome Duval cpuInfo.regs.edx >> 16, cpuInfo.regs.edx & 0xffff, 6461f5facdbSJerome Duval cpuInfo.regs.ecx >> 16, cpuInfo.regs.edx & 0xffff); 6471f5facdbSJerome Duval } 6481f5facdbSJerome Duval } 6491f5facdbSJerome Duval 6501f5facdbSJerome Duval putchar('\n'); 6511f5facdbSJerome Duval } 6521f5facdbSJerome Duval 653533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 6541f5facdbSJerome Duval 6551f5facdbSJerome Duval 6561f5facdbSJerome Duval static void 6571f5facdbSJerome Duval dump_cpus(system_info *info) 6581f5facdbSJerome Duval { 6591f5facdbSJerome Duval const char *vendor = get_cpu_vendor_string(info->cpu_type); 6601f5facdbSJerome Duval const char *model = get_cpu_model_string(info); 6611f5facdbSJerome Duval char modelString[32]; 6621f5facdbSJerome Duval 6631f5facdbSJerome Duval if (model == NULL && vendor == NULL) 6641f5facdbSJerome Duval model = "(Unknown)"; 6651f5facdbSJerome Duval else if (model == NULL) { 6661f5facdbSJerome Duval model = modelString; 6671f5facdbSJerome Duval snprintf(modelString, 32, "(Unknown %x)", info->cpu_type); 6681f5facdbSJerome Duval } 6691f5facdbSJerome Duval 670533f3bb4SAlex Smith printf("%" B_PRId32 " %s%s%s, revision %04" B_PRIx32 " running at %" 671533f3bb4SAlex Smith B_PRId64 "MHz (ID: 0x%08" B_PRIx32 " 0x%08" B_PRIx32 ")\n\n", 6721f5facdbSJerome Duval info->cpu_count, 6731f5facdbSJerome Duval vendor ? vendor : "", vendor ? " " : "", model, 6741f5facdbSJerome Duval info->cpu_revision, 6751f5facdbSJerome Duval info->cpu_clock_speed / 1000000, 6761f5facdbSJerome Duval info->id[0], info->id[1]); 6771f5facdbSJerome Duval 678533f3bb4SAlex Smith #if defined(__INTEL__) || defined(__x86_64__) 6791f5facdbSJerome Duval for (int32 cpu = 0; cpu < info->cpu_count; cpu++) 6801f5facdbSJerome Duval dump_cpu(info, cpu); 681533f3bb4SAlex Smith #endif // __INTEL__ || __x86_64__ 6821f5facdbSJerome Duval } 6831f5facdbSJerome Duval 6841f5facdbSJerome Duval 6851f5facdbSJerome Duval static void 6861f5facdbSJerome Duval dump_mem(system_info *info) 6871f5facdbSJerome Duval { 688533f3bb4SAlex Smith printf("%10" B_PRIu32 " bytes free (used/max %10" B_PRIu32 " / %10" 689533f3bb4SAlex Smith B_PRIu32 ")\n", 6901f5facdbSJerome Duval B_PAGE_SIZE * (uint32)(info->max_pages - info->used_pages), 6911f5facdbSJerome Duval B_PAGE_SIZE * (uint32)info->used_pages, 6921f5facdbSJerome Duval B_PAGE_SIZE * (uint32)info->max_pages); 693533f3bb4SAlex Smith printf(" (cached %10" B_PRIu32 ")\n", 6941f5facdbSJerome Duval B_PAGE_SIZE * (uint32)info->cached_pages); 6951f5facdbSJerome Duval } 6961f5facdbSJerome Duval 6971f5facdbSJerome Duval 6981f5facdbSJerome Duval static void 6991f5facdbSJerome Duval dump_sem(system_info *info) 7001f5facdbSJerome Duval { 701533f3bb4SAlex Smith printf("%10" B_PRId32 " semaphores free (used/max %10" B_PRId32 " / %10" 702533f3bb4SAlex Smith B_PRId32 ")\n", 7031f5facdbSJerome Duval info->max_sems - info->used_sems, 7041f5facdbSJerome Duval info->used_sems, info->max_sems); 7051f5facdbSJerome Duval } 7061f5facdbSJerome Duval 7071f5facdbSJerome Duval 7081f5facdbSJerome Duval static void 7091f5facdbSJerome Duval dump_ports(system_info *info) 7101f5facdbSJerome Duval { 711533f3bb4SAlex Smith printf("%10" B_PRId32 " ports free (used/max %10" B_PRId32 " / %10" 712533f3bb4SAlex Smith B_PRId32 ")\n", 7131f5facdbSJerome Duval info->max_ports - info->used_ports, 7141f5facdbSJerome Duval info->used_ports, info->max_ports); 7151f5facdbSJerome Duval } 7161f5facdbSJerome Duval 7171f5facdbSJerome Duval 7181f5facdbSJerome Duval static void 7191f5facdbSJerome Duval dump_thread(system_info *info) 7201f5facdbSJerome Duval { 721533f3bb4SAlex Smith printf("%10" B_PRId32 " threads free (used/max %10" B_PRId32 " / %10" 722533f3bb4SAlex Smith B_PRId32 ")\n", 7231f5facdbSJerome Duval info->max_threads - info->used_threads, 7241f5facdbSJerome Duval info->used_threads, info->max_threads); 7251f5facdbSJerome Duval } 7261f5facdbSJerome Duval 7271f5facdbSJerome Duval 7281f5facdbSJerome Duval static void 7291f5facdbSJerome Duval dump_team(system_info *info) 7301f5facdbSJerome Duval { 731533f3bb4SAlex Smith printf("%10" B_PRId32 " teams free (used/max %10" B_PRId32 " / %10" 732533f3bb4SAlex Smith B_PRId32 ")\n", 7331f5facdbSJerome Duval info->max_teams - info->used_teams, 7341f5facdbSJerome Duval info->used_teams, info->max_teams); 7351f5facdbSJerome Duval } 7361f5facdbSJerome Duval 7371f5facdbSJerome Duval 7381f5facdbSJerome Duval static void 7391f5facdbSJerome Duval dump_kinfo(system_info *info) 7401f5facdbSJerome Duval { 741533f3bb4SAlex Smith printf("Kernel name: %s built on: %s %s version 0x%" B_PRIx64 "\n", 7421f5facdbSJerome Duval info->kernel_name, 7431f5facdbSJerome Duval info->kernel_build_date, info->kernel_build_time, 7441f5facdbSJerome Duval info->kernel_version ); 7451f5facdbSJerome Duval } 7461f5facdbSJerome Duval 7471f5facdbSJerome Duval 7481f5facdbSJerome Duval static void 7491f5facdbSJerome Duval dump_system_info(system_info *info) 7501f5facdbSJerome Duval { 7511f5facdbSJerome Duval dump_kinfo(info); 7521f5facdbSJerome Duval dump_cpus(info); 7531f5facdbSJerome Duval dump_mem(info); 7541f5facdbSJerome Duval dump_sem(info); 7551f5facdbSJerome Duval dump_ports(info); 7561f5facdbSJerome Duval dump_thread(info); 7571f5facdbSJerome Duval dump_team(info); 7581f5facdbSJerome Duval } 7591f5facdbSJerome Duval 7601f5facdbSJerome Duval 7611f5facdbSJerome Duval int 7621f5facdbSJerome Duval main(int argc, char *argv[]) 7631f5facdbSJerome Duval { 7641f5facdbSJerome Duval if (!is_computer_on()) { 7651f5facdbSJerome Duval printf("The computer is not on! No info available\n"); 7661f5facdbSJerome Duval exit(EXIT_FAILURE); 7671f5facdbSJerome Duval } 7681f5facdbSJerome Duval 7691f5facdbSJerome Duval system_info info; 7701f5facdbSJerome Duval if (get_system_info(&info) != B_OK) { 7711f5facdbSJerome Duval printf("Error getting system information!\n"); 7721f5facdbSJerome Duval return 1; 7731f5facdbSJerome Duval } 7741f5facdbSJerome Duval 7751f5facdbSJerome Duval if (argc <= 1) { 7761f5facdbSJerome Duval dump_system_info(&info); 7771f5facdbSJerome Duval } else { 7781f5facdbSJerome Duval for (int i = 1; i < argc; i++) { 7791f5facdbSJerome Duval const char *opt = argv[i]; 7801f5facdbSJerome Duval if (strncmp(opt, "-id", strlen(opt)) == 0) { 7811f5facdbSJerome Duval /* note: the original also assumes this option on "sysinfo -" */ 782533f3bb4SAlex Smith printf("0x%.8" B_PRIx32 " 0x%.8" B_PRIx32 "\n", info.id[0], 783533f3bb4SAlex Smith info.id[1]); 7841f5facdbSJerome Duval } else if (strncmp(opt, "-cpu", strlen(opt)) == 0) { 7851f5facdbSJerome Duval dump_cpus(&info); 7861f5facdbSJerome Duval } else if (strncmp(opt, "-mem", strlen(opt)) == 0) { 7871f5facdbSJerome Duval dump_mem(&info); 7881f5facdbSJerome Duval } else if (strncmp(opt, "-semaphores", strlen(opt)) == 0) { 7891f5facdbSJerome Duval dump_sem(&info); 7901f5facdbSJerome Duval } else if (strncmp(opt, "-ports", strlen(opt)) == 0) { 7911f5facdbSJerome Duval dump_ports(&info); 7921f5facdbSJerome Duval } else if (strncmp(opt, "-threads", strlen(opt)) == 0) { 7931f5facdbSJerome Duval dump_thread(&info); 7941f5facdbSJerome Duval } else if (strncmp(opt, "-teams", strlen(opt)) == 0) { 7951f5facdbSJerome Duval dump_team(&info); 7961f5facdbSJerome Duval } else if (strncmp(opt, "-kinfo", strlen(opt)) == 0) { 7971f5facdbSJerome Duval dump_kinfo(&info); 7981f5facdbSJerome Duval } else if (strncmp(opt, "-platform", strlen(opt)) == 0) { 7991f5facdbSJerome Duval dump_platform(&info); 8001f5facdbSJerome Duval } else if (strncmp(opt, "-disable_cpu_sn", strlen(opt)) == 0) { 8011f5facdbSJerome Duval /* TODO: printf("CPU #%d serial number: old state: %s, new state: %s\n", ... ); */ 8021f5facdbSJerome Duval fprintf(stderr, "Sorry, not yet implemented\n"); 8031f5facdbSJerome Duval } else { 8041f5facdbSJerome Duval const char *name = strrchr(argv[0], '/'); 8051f5facdbSJerome Duval if (name == NULL) 8061f5facdbSJerome Duval name = argv[0]; 8071f5facdbSJerome Duval else 8081f5facdbSJerome Duval name++; 8091f5facdbSJerome Duval 8101f5facdbSJerome Duval fprintf(stderr, "Usage:\n"); 8111f5facdbSJerome Duval fprintf(stderr, " %s [-id|-cpu|-mem|-semaphore|-ports|-threads|-teams|-platform|-disable_cpu_sn|-kinfo]\n", name); 8121f5facdbSJerome Duval return 0; 8131f5facdbSJerome Duval } 8141f5facdbSJerome Duval } 8151f5facdbSJerome Duval } 8161f5facdbSJerome Duval return 0; 8171f5facdbSJerome Duval } 818