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
205ffbe7d7SAugustin Cavalier #if defined(__i386__) || 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"},
333987287dSRob Gill {0x09, "L1 inst cache: 43 KB, 4-way set associative, 32 bytes/line"},
341f5facdbSJerome Duval {0x0A, "L1 data cache: 8 KB, 2-way set associative, 32 bytes/line"},
353987287dSRob Gill {0x0B, "Code TLB: 4M-byte pages, 4-way set associative, 4 entries"},
361f5facdbSJerome Duval {0x0C, "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"},
371f5facdbSJerome Duval {0x0D, "L1 data cache: 16 KB, 4-way set associative, 64-bytes/line, ECC"},
381f5facdbSJerome Duval {0x0E, "L1 data cache, 24 KB, 6-way set associative, 64-bytes/line"},
391f5facdbSJerome Duval {0x10, /* IA-64 */ "L1 data cache: 16 KB, 4-way set associative, 32 bytes/line"},
401f5facdbSJerome Duval {0x15, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 32 bytes/line"},
411f5facdbSJerome Duval {0x1A, /* IA-64 */ "L2 cache: 96 KB, 6-way set associative, 64 bytes/line"},
423987287dSRob Gill {0x1D, "L2 cache: 128 KB, 2-way set associative, 64 bytes/line"},
431f5facdbSJerome Duval {0x21, "L2 cache: 256 KB (MLC), 8-way set associative, 64-bytes/line"},
441f5facdbSJerome Duval {0x22, "L3 cache: 512 KB, 4-way set associative (!), 64 bytes/line, dual-sectored"},
451f5facdbSJerome Duval {0x23, "L3 cache: 1 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
463987287dSRob Gill {0x24, "L2 cache: 1 MB, 8-way set associative, 64 bytes/line"},
471f5facdbSJerome Duval {0x25, "L3 cache: 2 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
481f5facdbSJerome Duval {0x29, "L3 cache: 4 MB, 8-way set associative, 64 bytes/line, dual-sectored"},
491f5facdbSJerome Duval {0x2c, "L1 data cache: 32 KB, 8-way set associative, 64 bytes/line"},
501f5facdbSJerome Duval {0x30, "L1 inst cache: 32 KB, 8-way set associative, 64 bytes/line"},
511f5facdbSJerome Duval {0x39, "L2 cache: 128 KB, 4-way set associative, 64 bytes/line, sectored"},
521f5facdbSJerome Duval {0x3A, "L2 cache: 192 KB, 4-way set associative, 64 bytes/line, sectored"},
531f5facdbSJerome Duval {0x3B, "L2 cache: 128 KB, 2-way set associative, 64 bytes/line, sectored"},
541f5facdbSJerome Duval {0x3C, "L2 cache: 256 KB, 4-way set associative, 64 bytes/line, sectored"},
551f5facdbSJerome Duval {0x3D, "L2 cache: 384 KB, 6-way set associative, 64 bytes/line, sectored"},
561f5facdbSJerome Duval {0x3E, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line, sectored"},
571f5facdbSJerome Duval {0x40, NULL /*"No integrated L2 cache (P6 core) or L3 cache (P4 core)"*/},
581f5facdbSJerome Duval // this one is separately handled
591f5facdbSJerome Duval {0x41, "L2 cache: 128 KB, 4-way set associative, 32 bytes/line"},
601f5facdbSJerome Duval {0x42, "L2 cache: 256 KB, 4-way set associative, 32 bytes/line"},
611f5facdbSJerome Duval {0x43, "L2 cache: 512 KB, 4-way set associative, 32 bytes/line"},
621f5facdbSJerome Duval {0x44, "L2 cache: 1024 KB, 4-way set associative, 32 bytes/line"},
631f5facdbSJerome Duval {0x45, "L2 cache: 2048 KB, 4-way set associative, 32 bytes/line"},
641f5facdbSJerome Duval {0x46, "L3 cache: 4096 KB, 4-way set associative, 64 bytes/line"},
651f5facdbSJerome Duval {0x47, "L3 cache: 8192 KB, 8-way set associative, 64 bytes/line"},
661f5facdbSJerome Duval {0x48, "L2 cache: 3072 KB, 12-way set associative, 64 bytes/line, unified on-die"},
671f5facdbSJerome Duval // 0x49 requires special handling, either 4M L3 (Xeon MP, 0F06; otherwise 4M L2
681f5facdbSJerome Duval {0x4A, "L3 cache: 6144 KB, 12-way set associative, 64 bytes/line"},
691f5facdbSJerome Duval {0x4B, "L3 cache: 8192 KB, 16-way set associative, 64 bytes/line"},
701f5facdbSJerome Duval {0x4C, "L3 cache: 12288 KB, 12-way set associative, 64 bytes/line"},
711f5facdbSJerome Duval {0x4D, "L3 cache: 16384 KB, 16-way set associative, 64 bytes/line"},
721f5facdbSJerome Duval {0x4E, "L2 cache: 6144 KB, 24-way set associative, 64 bytes/line"},
731f5facdbSJerome Duval {0x4F, "Inst TLB, 4K-bytes pages, 32 entries"},
741f5facdbSJerome Duval {0x50, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 64 entries"},
751f5facdbSJerome Duval {0x51, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 128 entries"},
761f5facdbSJerome Duval {0x52, "Inst TLB: 4K/4M/2M-bytes pages, fully associative, 256 entries"},
771f5facdbSJerome Duval {0x55, "Inst TLB: 2M/4M-bytes pages, fully associative, 7 entries"},
781f5facdbSJerome Duval {0x56, "L1 Data TLB: 4M-bytes pages, 4-way set associative, 16 entries"},
791f5facdbSJerome Duval {0x57, "L1 Data TLB: 4K-bytes pages, 4-way set associative, 16 entries"},
8085f64f90SAlexander von Gluck IV {0x59, "L0 Data TLB: 4K-bytes pages, fully associative, 16 entries"},
8185f64f90SAlexander von Gluck IV {0x5A, "L0 Data TLB: 2M/4M-bytes pages, 4-way set associative, 32 entries"},
821f5facdbSJerome Duval {0x5B, "Data TLB: 4K/4M-bytes pages, fully associative, 64 entries"},
831f5facdbSJerome Duval {0x5C, "Data TLB: 4K/4M-bytes pages, fully associative, 128 entries"},
841f5facdbSJerome Duval {0x5D, "Data TLB: 4K/4M-bytes pages, fully associative, 256 entries"},
853987287dSRob Gill {0x60, "L1 data cache: 16 KB, 8-way set associative, 64 bytes/line, sectored"},
863987287dSRob Gill {0x61, "Code TLB: 4K pages, fully associative, 48 entries"},
8785f64f90SAlexander von Gluck IV {0x63, "Data TLB: 2M/4M-bytes pages, 4-way set associative, 32 entries"},
883987287dSRob Gill {0x64, "Data TLB: 4K pages, 4-way set associative, 512 entries"},
891f5facdbSJerome Duval {0x66, "L1 data cache: 8 KB, 4-way set associative, 64 bytes/line, sectored"},
901f5facdbSJerome Duval {0x67, "L1 data cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"},
911f5facdbSJerome Duval {0x68, "L1 data cache: 32 KB, 4-way set associative, 64 bytes/line, sectored"},
923987287dSRob Gill {0x6A, "L0 Data TLB: 4K pages, 8-way set associative, 64 entries"},
933987287dSRob Gill {0x6B, "Data TLB: 4K pages, 8-way set associative, 256 entries"},
943987287dSRob Gill {0x6C, "Data TLB: 2M/4M pages, 8-way set associative, 128 entries"},
953987287dSRob Gill {0x6D, "Data TLB: 1G pages, fully associative, 16 entries"},
963987287dSRob Gill // {0x70, "Cyrix specific: Code and data TLB: 4k-bytes pages, 4-way set associative, 32 entries"},
971f5facdbSJerome Duval {0x70, "Inst trace cache: 12K µOPs, 8-way set associative"},
981f5facdbSJerome Duval {0x71, "Inst trace cache: 16K µOPs, 8-way set associative"},
991f5facdbSJerome Duval {0x72, "Inst trace cache: 32K µOPs, 8-way set associative"},
1003987287dSRob Gill {0x73, "Inst trace cache: 64K µOPs, 8-way set associative"},
1013987287dSRob Gill // {0x74, "Cyrix specific: ???"},
1023987287dSRob Gill {0x76, "Code TLB: 2M/4M pages, fully associative, 8 entries"},
1031f5facdbSJerome Duval {0x77, /* IA-64 */ "L1 inst cache: 16 KB, 4-way set associative, 64 bytes/line, sectored"},
1043987287dSRob Gill // {0x77, "Cyrix specific: ???"},
1053987287dSRob Gill {0x78, "L2 cache: 1024 KB, 4-way set associative, 64 bytes/line"},
1061f5facdbSJerome Duval {0x79, "L2 cache: 128 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
1071f5facdbSJerome Duval {0x7A, "L2 cache: 256 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
1081f5facdbSJerome Duval {0x7B, "L2 cache: 512 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
1091f5facdbSJerome Duval {0x7C, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line, dual-sectored"},
1101f5facdbSJerome Duval {0x7D, "L2 cache: 2048 KB, 8-way set associative, 64 bytes/line"},
1111f5facdbSJerome Duval {0x7E, /* IA-64 */ "L2 cache: 256 KB, 8-way set associative, 128 bytes/line, sectored"},
1121f5facdbSJerome Duval {0x7F, "L2 cache: 512 KB, 2-way set associative, 64 bytes/line"},
1133987287dSRob Gill {0x80, /* Cyrix specific */ "L1 cache: 16 KB, 4-way set associative, 16 bytes/line"},
1141f5facdbSJerome Duval {0x81, "L2 cache: 128 KB, 8-way set associative, 32 bytes/line"},
1151f5facdbSJerome Duval {0x82, "L2 cache: 256 KB, 8-way set associative, 32 bytes/line"},
1163987287dSRob Gill // {0x82, "Cyrix specific: ???"},
1171f5facdbSJerome Duval {0x83, "L2 cache: 512 KB, 8-way set associative, 32 bytes/line"},
1181f5facdbSJerome Duval {0x84, "L2 cache: 1024 KB, 8-way set associative, 32 bytes/line"},
1193987287dSRob Gill // {0x84, "Cyrix specific: ???"},
1201f5facdbSJerome Duval {0x85, "L2 cache: 2048 KB, 8-way set associative, 32 bytes/line"},
1211f5facdbSJerome Duval {0x86, "L2 cache: 512 KB, 4-way set associative, 64 bytes/line"},
1221f5facdbSJerome Duval {0x87, "L2 cache: 1024 KB, 8-way set associative, 64 bytes/line"},
1231f5facdbSJerome Duval {0x88, /* IA-64 */ "L3 cache: 2 MB, 4-way set associative, 64 bytes/line"},
1241f5facdbSJerome Duval {0x89, /* IA-64 */ "L3 cache: 4 MB, 4-way set associative, 64 bytes/line"},
1251f5facdbSJerome Duval {0x8A, /* IA-64 */ "L3 cache: 8 MB, 4-way set associative, 64 bytes/line"},
1261f5facdbSJerome Duval {0x8D, /* IA-64 */ "L3 cache: 3 MB, 12-way set associative, 128 bytes/line"},
1271f5facdbSJerome Duval {0x90, /* IA-64 */ "Inst TLB: 4K-256Mbytes pages, fully associative, 64 entries"},
1281f5facdbSJerome Duval {0x96, /* IA-64 */ "L1 data TLB: 4K-256M bytes pages, fully associative, 32 entries"},
1291f5facdbSJerome Duval {0x9B, /* IA-64 */ "L2 data TLB: 4K-256M bytes pages, fully associative, 96 entries"},
1303987287dSRob Gill {0xA0, "Data TLB: 4K-bytes pages, fully associative, 32 entries"},
1311f5facdbSJerome Duval {0xB0, "Inst TLB: 4K-bytes pages, 4-way set associative, 128 entries"},
1321f5facdbSJerome Duval {0xB1, "Inst TLB: 2M-bytes pages, 4-way set associative, 8 entries OR 4M, 4-way, 4 entries"},
1331f5facdbSJerome Duval // Intel doesn't give any details how to determine which of the two options is the case
1341f5facdbSJerome Duval // as per Intel Application Note 485, November 2008.
1351f5facdbSJerome Duval {0xB2, "Inst TLB: 4K-bytes pages, 4-way set associative, 64 entries"},
1361f5facdbSJerome Duval {0xB3, "Data TLB: 4K-bytes pages, 4-way set associative, 128 entries"},
1371f5facdbSJerome Duval {0xB4, "Data TLB: 4K-bytes pages, 4-way set associative, 256 entries"},
13885f64f90SAlexander von Gluck IV {0xB5, "Code TLB: 4K-bytes pages, 8-way set associative, 64 entries"},
13985f64f90SAlexander von Gluck IV {0xB6, "Code TLB: 4K-bytes pages, 8-way set associative, 128 entries"},
1401f5facdbSJerome Duval {0xBA, "Data TLB, 4K-bytes pages, 4-way set associative, 64 entries"},
1411f5facdbSJerome Duval {0xC0, "Data TLB, 4K-4M bytes pages, 4-way set associative, 8 entries"},
1423987287dSRob Gill {0xC1, "L2 cache: 4K/2M bytes pages, 8-way set associative, 1024 entries"},
1433987287dSRob Gill {0xC2, "Data TLB, 2M/4M bytes pages, 4-way set associative, 16 entries"},
14485f64f90SAlexander von Gluck IV {0xC3, "Shared 2nd-level TLB: 4K/2M, 6-way set associative, 1536 entries"},
1453987287dSRob Gill {0xC4, "Data TLB, 2M/4M bytes pages, 4-way set associative, 32 entries"},
1461f5facdbSJerome Duval {0xCA, "Shared 2nd-level TLB: 4K, 4-way set associative, 512 entries"},
1471f5facdbSJerome Duval {0xD0, "L3 cache: 512 KB, 4-way set associative, 64-bytes/line"},
1481f5facdbSJerome Duval {0xD1, "L3 cache: 1024 KB, 4-way set associative, 64-bytes/line"},
1491f5facdbSJerome Duval {0xD2, "L3 cache: 2048 KB, 4-way set associative, 64-bytes/line"},
1501f5facdbSJerome Duval {0xD6, "L3 cache: 1024 KB, 8-way set associative, 64-bytes/line"},
1511f5facdbSJerome Duval {0xD7, "L3 cache: 2048 KB, 8-way set associative, 64-bytes/line"},
1521f5facdbSJerome Duval {0xD8, "L3 cache: 4096 KB, 8-way set associative, 64-bytes/line"},
1531f5facdbSJerome Duval {0xDC, "L3 cache: 2048 KB, 12-way set associative, 64-bytes/line"},
1541f5facdbSJerome Duval {0xDD, "L3 cache: 4096 KB, 12-way set associative, 64-bytes/line"},
1551f5facdbSJerome Duval {0xDE, "L3 cache: 8192 KB, 12-way set associative, 64-bytes/line"},
1561f5facdbSJerome Duval {0xE2, "L3 cache: 2048 KB, 16-way set associative, 64-bytes/line"},
1571f5facdbSJerome Duval {0xE3, "L3 cache: 4096 KB, 16-way set associative, 64-bytes/line"},
1581f5facdbSJerome Duval {0xE4, "L3 cache: 8192 KB, 16-way set associative, 64-bytes/line"},
1593987287dSRob Gill {0xEA, "L3 cache: 12288 KB, 24-way set associative, 64-bytes/line"},
1603987287dSRob Gill {0xEB, "L3 cache: 18432 KB, 24-way set associative, 64-bytes/line"},
1613987287dSRob Gill {0xEC, "L3 cache: 24576 KB, 24-way set associative, 64-bytes/line"},
1621f5facdbSJerome Duval {0xF0, "64-byte Prefetching"},
1631f5facdbSJerome Duval {0xF1, "128-byte Prefetching"},
1643987287dSRob Gill {0xFF, NULL}, // print_intel_cache_desc() will query level 0000_0004h
1651f5facdbSJerome Duval {0, NULL}
1661f5facdbSJerome Duval };
1671f5facdbSJerome Duval
1681f5facdbSJerome Duval
16985f64f90SAlexander von Gluck IV /* CPU Features */
17085f64f90SAlexander von Gluck IV static const char *kFeatures[32] = {
17185f64f90SAlexander von Gluck IV "FPU", "VME", "DE", "PSE",
17285f64f90SAlexander von Gluck IV "TSC", "MSR", "PAE", "MCE",
17385f64f90SAlexander von Gluck IV "CX8", "APIC", NULL, "SEP",
17485f64f90SAlexander von Gluck IV "MTRR", "PGE", "MCA", "CMOV",
17585f64f90SAlexander von Gluck IV "PAT", "PSE36", "PSN", "CFLUSH",
17685f64f90SAlexander von Gluck IV NULL, "DS", "ACPI", "MMX",
17785f64f90SAlexander von Gluck IV "FXSTR", "SSE", "SSE2", "SS",
1783987287dSRob Gill "HTT", "TM", "IA64", "PBE",
17985f64f90SAlexander von Gluck IV };
18085f64f90SAlexander von Gluck IV
18185f64f90SAlexander von Gluck IV /* CPU Extended features */
18285f64f90SAlexander von Gluck IV static const char *kExtendedFeatures[32] = {
18385f64f90SAlexander von Gluck IV "SSE3", "PCLMULDQ", "DTES64", "MONITOR", "DS-CPL", "VMX", "SMX", "EST",
1843987287dSRob Gill "TM2", "SSSE3", "CNTXT-ID", "SDBG", "FMA", "CX16", "xTPR", "PDCM",
18585f64f90SAlexander von Gluck IV NULL, "PCID", "DCA", "SSE4.1", "SSE4.2", "x2APIC", "MOVEB", "POPCNT",
18685f64f90SAlexander von Gluck IV "TSC-DEADLINE", "AES", "XSAVE", "OSXSAVE", "AVX", "F16C", "RDRND",
18785f64f90SAlexander von Gluck IV "HYPERVISOR"
18885f64f90SAlexander von Gluck IV };
18985f64f90SAlexander von Gluck IV
19085f64f90SAlexander von Gluck IV
19185f64f90SAlexander von Gluck IV /* AMD Extended features leaf 0x80000001 */
19285f64f90SAlexander von Gluck IV static const char *kAMDExtFeatures[32] = {
19385f64f90SAlexander von Gluck IV NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
19485f64f90SAlexander von Gluck IV NULL, NULL, NULL, "SCE", NULL, NULL, NULL, NULL,
1953987287dSRob Gill NULL, NULL, NULL, "MP", "NX", NULL, "AMD-MMX", NULL,
1963987287dSRob Gill "FXSR", "FFXSR", "GBPAGES", "RDTSCP", NULL, "64", "3DNow+", "3DNow!"
19785f64f90SAlexander von Gluck IV };
19885f64f90SAlexander von Gluck IV
19985f64f90SAlexander von Gluck IV
20085f64f90SAlexander von Gluck IV /* AMD Extended features leaf 0x80000007 */
20185f64f90SAlexander von Gluck IV static const char *kAMDExtFeaturesPower[32] = {
20285f64f90SAlexander von Gluck IV "TS", "FID", "VID", "TTP", "TM", "STC", "MUL100", "HWPS",
20385f64f90SAlexander von Gluck IV "ITSC", "CPB", "EFRO", "PFI", "PA", NULL, NULL, NULL,
20485f64f90SAlexander von Gluck IV NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
20585f64f90SAlexander von Gluck IV NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
20685f64f90SAlexander von Gluck IV };
20785f64f90SAlexander von Gluck IV
20885f64f90SAlexander von Gluck IV
20985f64f90SAlexander von Gluck IV /* AMD Extended features leaf 0x80000008 */
21085f64f90SAlexander von Gluck IV static const char *kAMDExtFeaturesTwo[32] = {
2113987287dSRob Gill "CLZERO", "IRPERF", "XSAVEPTR", NULL, NULL, NULL, NULL, NULL,
2123987287dSRob Gill NULL, NULL, NULL, NULL, "AMD_IBPB", NULL, "AMD_IBRS", "AMD_STIBP",
21385f64f90SAlexander von Gluck IV NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2143987287dSRob Gill "AMD_SSBD", "VIRT_SSBD", "AMD_SSB_NO", NULL, NULL, NULL, NULL, NULL
21585f64f90SAlexander von Gluck IV };
21685f64f90SAlexander von Gluck IV
21785f64f90SAlexander von Gluck IV
2181f5facdbSJerome Duval static void
print_intel_cache_descriptors(enum cpu_vendor vendor,uint32 model,cpuid_info * info)2191bc7045fSPawel Dziepak print_intel_cache_descriptors(enum cpu_vendor vendor, uint32 model,
2201bc7045fSPawel Dziepak cpuid_info *info)
2211f5facdbSJerome Duval {
2221f5facdbSJerome Duval uint8 cacheDescriptors[15]; // Max
2231f5facdbSJerome Duval
2241f5facdbSJerome Duval int maxDesc = 0;
2251f5facdbSJerome Duval int i = 0;
2261f5facdbSJerome Duval
2271f5facdbSJerome Duval // put valid values into array
2281f5facdbSJerome Duval if ((info->regs.eax & 0x80000000) == 0) {
2291f5facdbSJerome Duval // eax is valid, include values
2301f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2311f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2321f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2331f5facdbSJerome Duval } else {
2341f5facdbSJerome Duval i += 3;
2351f5facdbSJerome Duval }
2361f5facdbSJerome Duval if ((info->regs.ebx & 0x80000000) == 0) {
2371f5facdbSJerome Duval // ebx is valid, include values
2381f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2391f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2401f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2411f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2421f5facdbSJerome Duval } else {
2431f5facdbSJerome Duval i += 4;
2441f5facdbSJerome Duval }
2451f5facdbSJerome Duval if ((info->regs.edx & 0x80000000) == 0) {
2461f5facdbSJerome Duval // edx is valid, include values
2471f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2481f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2491f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2501f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2511f5facdbSJerome Duval } else {
2521f5facdbSJerome Duval i += 4;
2531f5facdbSJerome Duval }
2541f5facdbSJerome Duval if ((info->regs.ecx & 0x80000000) == 0) {
2551f5facdbSJerome Duval // ecx is valid, include values
2561f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2571f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2581f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2591f5facdbSJerome Duval cacheDescriptors[maxDesc++] = info->eax_2.cache_descriptors[i++];
2601f5facdbSJerome Duval }
2611f5facdbSJerome Duval
2621f5facdbSJerome Duval putchar('\n');
2631f5facdbSJerome Duval
2641f5facdbSJerome Duval for (int i = 0; i < maxDesc; i++) {
2651f5facdbSJerome Duval // ignore NULL descriptors
2661f5facdbSJerome Duval if (cacheDescriptors[i] == 0)
2671f5facdbSJerome Duval continue;
2681f5facdbSJerome Duval
2691f5facdbSJerome Duval int j;
2701f5facdbSJerome Duval for (j = 0; sIntelCacheDescriptions[j].code; j++) {
2711f5facdbSJerome Duval if (cacheDescriptors[i] == sIntelCacheDescriptions[j].code) {
2721f5facdbSJerome Duval if (cacheDescriptors[i] == 0x40) {
2731f5facdbSJerome Duval printf("\tNo integrated L%u cache\n",
2741bc7045fSPawel Dziepak ((model >> 8) & 0xf) == 0xf
2751bc7045fSPawel Dziepak && vendor == B_CPU_VENDOR_INTEL ? 3 : 2);
2763987287dSRob Gill } else if (cacheDescriptors[i] == 0xff) {
2773987287dSRob Gill break;
2781f5facdbSJerome Duval } else
2791f5facdbSJerome Duval printf("\t%s\n", sIntelCacheDescriptions[j].description);
2801f5facdbSJerome Duval break;
2811f5facdbSJerome Duval }
2821f5facdbSJerome Duval }
2831f5facdbSJerome Duval
2841f5facdbSJerome Duval // Reached the end without finding a descriptor
2851f5facdbSJerome Duval if (sIntelCacheDescriptions[j].code == 0)
2861f5facdbSJerome Duval printf("\tUnknown cache descriptor 0x%02x\n", cacheDescriptors[i]);
2871f5facdbSJerome Duval }
2881f5facdbSJerome Duval }
2891f5facdbSJerome Duval
2901bc7045fSPawel Dziepak
2915ffbe7d7SAugustin Cavalier #endif // __i386__ || __x86_64__
2921f5facdbSJerome Duval
2931f5facdbSJerome Duval
2941f5facdbSJerome Duval static void
print_TLB(uint32 reg,const char * pages)2951f5facdbSJerome Duval print_TLB(uint32 reg, const char *pages)
2961f5facdbSJerome Duval {
2971f5facdbSJerome Duval int entries[2];
2981f5facdbSJerome Duval int ways[2];
2991f5facdbSJerome Duval const char *name[2] = { "Inst TLB", "Data TLB" };
3001f5facdbSJerome Duval
3011f5facdbSJerome Duval entries[0] = (reg & 0xff);
3021f5facdbSJerome Duval ways[0] = ((reg >> 8) & 0xff);
3031f5facdbSJerome Duval entries[1] = ((reg >> 16) & 0xff);
3041f5facdbSJerome Duval ways[1] = ((reg >> 24) & 0xff);
3051f5facdbSJerome Duval
3061f5facdbSJerome Duval for (int num = 0; num < 2; num++) {
3071f5facdbSJerome Duval printf("\t%s: %s%s%u entries, ", name[num],
3081f5facdbSJerome Duval pages ? pages : "", pages ? " pages, " : "", entries[num]);
3091f5facdbSJerome Duval
3101f5facdbSJerome Duval if (ways[num] == 0xff)
3111f5facdbSJerome Duval printf("fully associative\n");
3121f5facdbSJerome Duval else
3131f5facdbSJerome Duval printf("%u-way set associative\n", ways[num]);
3141f5facdbSJerome Duval }
3151f5facdbSJerome Duval }
3161f5facdbSJerome Duval
3171f5facdbSJerome Duval
3181f5facdbSJerome Duval static void
print_level2_cache(uint32 reg,const char * name)3191f5facdbSJerome Duval print_level2_cache(uint32 reg, const char *name)
3201f5facdbSJerome Duval {
3211f5facdbSJerome Duval uint32 size = (reg >> 16) & 0xffff;
3221f5facdbSJerome Duval uint32 ways = (reg >> 12) & 0xf;
323f1cbaf5cSAxel Dörfler uint32 linesPerTag = (reg >> 8) & 0xf;
324f1cbaf5cSAxel Dörfler // intel does not define this
3251f5facdbSJerome Duval uint32 lineSize = reg & 0xff;
3261f5facdbSJerome Duval
327533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size);
3281f5facdbSJerome Duval if (ways == 0xf)
3291f5facdbSJerome Duval printf("fully associative, ");
3301f5facdbSJerome Duval else if (ways == 0x1)
3311f5facdbSJerome Duval printf("direct-mapped, ");
3321f5facdbSJerome Duval else
3331f5facdbSJerome Duval printf("%lu-way set associative, ", 1UL << (ways / 2));
334533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag,
335533f3bb4SAlex Smith lineSize);
3361f5facdbSJerome Duval }
3371f5facdbSJerome Duval
3381f5facdbSJerome Duval
3391f5facdbSJerome Duval static void
print_level1_cache(uint32 reg,const char * name)3401f5facdbSJerome Duval print_level1_cache(uint32 reg, const char *name)
3411f5facdbSJerome Duval {
3421f5facdbSJerome Duval uint32 size = (reg >> 24) & 0xff;
3431f5facdbSJerome Duval uint32 ways = (reg >> 16) & 0xff;
3441f5facdbSJerome Duval uint32 linesPerTag = (reg >> 8) & 0xff;
3451f5facdbSJerome Duval uint32 lineSize = reg & 0xff;
3461f5facdbSJerome Duval
347533f3bb4SAlex Smith printf("\t%s: %" B_PRIu32 " KB, ", name, size);
3481f5facdbSJerome Duval if (ways == 0xff)
3491f5facdbSJerome Duval printf("fully associative, ");
3501f5facdbSJerome Duval else
351533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways);
352533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag,
353533f3bb4SAlex Smith lineSize);
3541f5facdbSJerome Duval }
3551f5facdbSJerome Duval
3561f5facdbSJerome Duval
3575ffbe7d7SAugustin Cavalier #if defined(__i386__) || defined(__x86_64__)
3581f5facdbSJerome Duval
3591f5facdbSJerome Duval static void
print_cache_desc(int32 cpu)3601f5facdbSJerome Duval print_cache_desc(int32 cpu)
3611f5facdbSJerome Duval {
3621f5facdbSJerome Duval cpuid_info info;
3631f5facdbSJerome Duval get_cpuid(&info, 0x80000005, cpu);
3641f5facdbSJerome Duval
3651f5facdbSJerome Duval putchar('\n');
3661f5facdbSJerome Duval
3671f5facdbSJerome Duval if (info.regs.eax)
3681f5facdbSJerome Duval print_TLB(info.regs.eax, info.regs.ebx ? "2M/4M-byte" : NULL);
3691f5facdbSJerome Duval if (info.regs.ebx)
3701f5facdbSJerome Duval print_TLB(info.regs.ebx, info.regs.eax ? "4K-byte" : NULL);
3711f5facdbSJerome Duval
3721f5facdbSJerome Duval print_level1_cache(info.regs.ecx, "L1 inst cache");
3731f5facdbSJerome Duval print_level1_cache(info.regs.edx, "L1 data cache");
3741f5facdbSJerome Duval
3751f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu);
3761f5facdbSJerome Duval print_level2_cache(info.regs.ecx, "L2 cache");
3771f5facdbSJerome Duval }
3781f5facdbSJerome Duval
379f1cbaf5cSAxel Dörfler
3801f5facdbSJerome Duval static void
print_intel_cache_desc(int32 cpu)3811f5facdbSJerome Duval print_intel_cache_desc(int32 cpu)
3821f5facdbSJerome Duval {
3831f5facdbSJerome Duval cpuid_info info;
3841f5facdbSJerome Duval
385f1cbaf5cSAxel Dörfler // A second parameters needs to be passed to CPUID which determines the
386f1cbaf5cSAxel Dörfler // cache level to query
3871f5facdbSJerome Duval get_cpuid(&info, 0x00000004, cpu);
3881f5facdbSJerome Duval
3891f5facdbSJerome Duval putchar('\n');
3901f5facdbSJerome Duval
3911f5facdbSJerome Duval uint32 type = info.regs.eax & 0xf;
3921f5facdbSJerome Duval uint32 level = (info.regs.eax & 0x70) >> 4;
3931f5facdbSJerome Duval bool isFullyAssoc = info.regs.eax & 0x100;
3941f5facdbSJerome Duval
3951f5facdbSJerome Duval uint32 lineSize = (info.regs.ebx & 0xfff) + 1;
3961f5facdbSJerome Duval uint32 linesPerTag = ((info.regs.ebx & 0x3ff000) >> 12) + 1;
3971f5facdbSJerome Duval uint32 ways = ((info.regs.ebx & 0xffc00000) >> 22) + 1;
3981f5facdbSJerome Duval
399533f3bb4SAlex Smith printf("\tL%" B_PRId32 " ",level);
4001f5facdbSJerome Duval
4011f5facdbSJerome Duval switch (type) {
4021f5facdbSJerome Duval case 1: printf("Data cache "); break;
4031f5facdbSJerome Duval case 2: printf("Inst cache "); break;
4041f5facdbSJerome Duval case 3: printf("Unified cache "); break;
4051f5facdbSJerome Duval default: break;
4061f5facdbSJerome Duval }
4071f5facdbSJerome Duval
4081f5facdbSJerome Duval if (isFullyAssoc)
4091f5facdbSJerome Duval printf("fully associative, ");
4101f5facdbSJerome Duval else
411533f3bb4SAlex Smith printf("%" B_PRIu32 "-way set associative, ", ways);
412533f3bb4SAlex Smith printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag,
413533f3bb4SAlex Smith lineSize);
4141f5facdbSJerome Duval
4151f5facdbSJerome Duval get_cpuid(&info, 0x80000006, cpu);
4163987287dSRob Gill uint32 sets = info.regs.ecx;
4171f5facdbSJerome Duval print_level2_cache(sets, "L2 cache");
4181f5facdbSJerome Duval }
4191f5facdbSJerome Duval
4201f5facdbSJerome Duval
4211f5facdbSJerome Duval static void
print_transmeta_features(uint32 features)4221f5facdbSJerome Duval print_transmeta_features(uint32 features)
4231f5facdbSJerome Duval {
4241f5facdbSJerome Duval if (features & (1 << 16))
4251f5facdbSJerome Duval printf("\t\tFCMOV\n");
4261f5facdbSJerome Duval }
4271f5facdbSJerome Duval
4285ffbe7d7SAugustin Cavalier #endif // __i386__ || __x86_64__
4291f5facdbSJerome Duval
4301f5facdbSJerome Duval
4311f5facdbSJerome Duval static void
print_features(const char ** table,uint32 features)43285f64f90SAlexander von Gluck IV print_features(const char** table, uint32 features)
4331f5facdbSJerome Duval {
4341f5facdbSJerome Duval int32 found = 0;
4351f5facdbSJerome Duval
4361f5facdbSJerome Duval for (int32 i = 0; i < 32; i++) {
43785f64f90SAlexander von Gluck IV if ((features & (1UL << i)) && table[i] != NULL) {
43885f64f90SAlexander von Gluck IV printf("%s%s", found == 0 ? "\t\t" : " ", table[i]);
4391f5facdbSJerome Duval found++;
4401f5facdbSJerome Duval if (found > 0 && (found % 16) == 0) {
4411f5facdbSJerome Duval putchar('\n');
4421f5facdbSJerome Duval found = 0;
4431f5facdbSJerome Duval }
4441f5facdbSJerome Duval }
4451f5facdbSJerome Duval }
4461f5facdbSJerome Duval
4471f5facdbSJerome Duval if (found != 0)
4481f5facdbSJerome Duval putchar('\n');
4491f5facdbSJerome Duval }
4501f5facdbSJerome Duval
4511f5facdbSJerome Duval
4525ffbe7d7SAugustin Cavalier #if defined(__i386__) || defined(__x86_64__)
4531f5facdbSJerome Duval
4541f5facdbSJerome Duval static void
print_processor_signature(enum cpu_vendor vendor,cpuid_info * info)45585f64f90SAlexander von Gluck IV print_processor_signature(enum cpu_vendor vendor, cpuid_info *info)
4561f5facdbSJerome Duval {
45785f64f90SAlexander von Gluck IV printf("\tSignature: 0x%1" B_PRIx32 "%1" B_PRIx32 "0%1" B_PRIx32
45885f64f90SAlexander von Gluck IV "%1" B_PRIx32 "%1" B_PRIx32 "; ", info->eax_1.extended_family,
45985f64f90SAlexander von Gluck IV info->eax_1.extended_model, info->eax_1.family,
46085f64f90SAlexander von Gluck IV info->eax_1.model, info->eax_1.stepping);
461357b9d3cSJérôme Duval if (vendor == B_CPU_VENDOR_AMD || vendor == B_CPU_VENDOR_HYGON) {
46285f64f90SAlexander von Gluck IV printf("Type %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32
46385f64f90SAlexander von Gluck IV ", stepping %" B_PRIu32 "\n",
4641f5facdbSJerome Duval info->eax_1.type,
465f1cbaf5cSAxel Dörfler info->eax_1.family + (info->eax_1.family == 0xf
466f1cbaf5cSAxel Dörfler ? info->eax_1.extended_family : 0),
467f1cbaf5cSAxel Dörfler info->eax_1.model + (info->eax_1.model == 0xf
468f1cbaf5cSAxel Dörfler ? info->eax_1.extended_model << 4 : 0),
46985f64f90SAlexander von Gluck IV info->eax_1.stepping);
4701bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_INTEL) {
4711f5facdbSJerome Duval // model calculation is different for INTEL
47285f64f90SAlexander von Gluck IV printf("Type %" B_PRIu32 ", family %" B_PRIu32 ", model %" B_PRIu32
47385f64f90SAlexander von Gluck IV ", stepping %" B_PRIu32 "\n",
4741f5facdbSJerome Duval info->eax_1.type,
475f1cbaf5cSAxel Dörfler info->eax_1.family + (info->eax_1.family == 0xf
476f1cbaf5cSAxel Dörfler ? info->eax_1.extended_family : 0),
477f1cbaf5cSAxel Dörfler info->eax_1.model
478f1cbaf5cSAxel Dörfler + ((info->eax_1.family == 0xf || info->eax_1.family == 0x6)
479f1cbaf5cSAxel Dörfler ? info->eax_1.extended_model << 4 : 0),
48085f64f90SAlexander von Gluck IV info->eax_1.stepping);
4811f5facdbSJerome Duval }
4821f5facdbSJerome Duval }
4831f5facdbSJerome Duval
4845ffbe7d7SAugustin Cavalier #endif // __i386__ || __x86_64__
4851f5facdbSJerome Duval
4861f5facdbSJerome Duval
4871f5facdbSJerome Duval static void
dump_platform(system_info * info)4881f5facdbSJerome Duval dump_platform(system_info *info)
4891f5facdbSJerome Duval {
4901bc7045fSPawel Dziepak cpu_topology_node_info root;
4911bc7045fSPawel Dziepak uint32 count = 1;
4921bc7045fSPawel Dziepak get_cpu_topology_info(&root, &count);
4931bc7045fSPawel Dziepak
4941bc7045fSPawel Dziepak const char* platform;
4951bc7045fSPawel Dziepak switch (root.data.root.platform) {
4961bc7045fSPawel Dziepak case B_CPU_x86:
4971bc7045fSPawel Dziepak platform = "IntelArchitecture";
4981bc7045fSPawel Dziepak break;
4991bc7045fSPawel Dziepak
5001bc7045fSPawel Dziepak case B_CPU_x86_64:
5011bc7045fSPawel Dziepak platform = "IntelArchitecture (64 bit)";
5021bc7045fSPawel Dziepak break;
5031bc7045fSPawel Dziepak
5041bc7045fSPawel Dziepak default:
5051bc7045fSPawel Dziepak platform = "unknown";
5061bc7045fSPawel Dziepak break;
5071bc7045fSPawel Dziepak }
5081bc7045fSPawel Dziepak
5091bc7045fSPawel Dziepak printf("%s\n", platform);
5101f5facdbSJerome Duval }
5111f5facdbSJerome Duval
5121f5facdbSJerome Duval
5135ffbe7d7SAugustin Cavalier #if defined(__i386__) || defined(__x86_64__)
5141f5facdbSJerome Duval
5151f5facdbSJerome Duval static void
dump_cpu(enum cpu_vendor vendor,uint32 model,int32 cpu)5161bc7045fSPawel Dziepak dump_cpu(enum cpu_vendor vendor, uint32 model, int32 cpu)
5171f5facdbSJerome Duval {
518f1cbaf5cSAxel Dörfler // References:
519f1cbaf5cSAxel Dörfler // http://grafi.ii.pw.edu.pl/gbm/x86/cpuid.html
520f1cbaf5cSAxel Dörfler // http://www.sandpile.org/ia32/cpuid.htm
52185f64f90SAlexander von Gluck IV // http://www.sandpile.org/x86/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,
5751bc7045fSPawel Dziepak vendor == B_CPU_VENDOR_INTEL ?
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
584*7c2c355fSJérôme Duval cpu_info frequencyInfo;
585*7c2c355fSJérôme Duval if (get_cpu_info(cpu, 1, &frequencyInfo) == B_OK
586*7c2c355fSJérôme Duval && frequencyInfo.current_frequency != 0) {
587*7c2c355fSJérôme Duval printf("\tFrequency: %" B_PRId32 ".%03" B_PRId32 "\n",
588*7c2c355fSJérôme Duval int32(frequencyInfo.current_frequency / 1000000),
589*7c2c355fSJérôme Duval int32((frequencyInfo.current_frequency % 1000000) / 1000));
590*7c2c355fSJérôme Duval }
591*7c2c355fSJérôme Duval
5921f5facdbSJerome Duval get_cpuid(&cpuInfo, 1, cpu);
59385f64f90SAlexander von Gluck IV print_processor_signature(vendor, &cpuInfo);
59485f64f90SAlexander von Gluck IV printf("\tFeatures: 0x%08" B_PRIx32 "\n", cpuInfo.eax_1.features);
59585f64f90SAlexander von Gluck IV print_features(kFeatures, cpuInfo.eax_1.features);
5961f5facdbSJerome Duval
5971f5facdbSJerome Duval if (maxStandardFunction >= 1) {
5981f5facdbSJerome Duval /* Extended features */
59985f64f90SAlexander von Gluck IV printf("\tExtended Features (0x00000001): 0x%08" B_PRIx32 "\n",
60085f64f90SAlexander von Gluck IV cpuInfo.eax_1.extended_features);
60185f64f90SAlexander von Gluck IV print_features(kExtendedFeatures, cpuInfo.eax_1.extended_features);
6021f5facdbSJerome Duval }
6031f5facdbSJerome Duval
60485f64f90SAlexander von Gluck IV /* Extended CPUID Information */
6051f5facdbSJerome Duval if (maxExtendedFunction >= 1) {
6061f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000001, cpu);
607357b9d3cSJérôme Duval if (vendor == B_CPU_VENDOR_INTEL || vendor == B_CPU_VENDOR_AMD
608357b9d3cSJérôme Duval || vendor == B_CPU_VENDOR_HYGON) {
60985f64f90SAlexander von Gluck IV // 0x80000001 EDX has overlap of 64,ED,SY/SE between amd and intel
61085f64f90SAlexander von Gluck IV printf("\tExtended Features (0x80000001): 0x%08" B_PRIx32 "\n",
61185f64f90SAlexander von Gluck IV cpuInfo.eax_1.features);
61285f64f90SAlexander von Gluck IV print_features(kAMDExtFeatures, cpuInfo.regs.edx);
61385f64f90SAlexander von Gluck IV }
6141f5facdbSJerome Duval
615357b9d3cSJérôme Duval if (vendor == B_CPU_VENDOR_AMD || vendor == B_CPU_VENDOR_HYGON) {
6161f5facdbSJerome Duval if (maxExtendedFunction >= 7) {
6171f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x80000007, cpu);
61885f64f90SAlexander von Gluck IV printf("\tExtended Features (0x80000007): 0x%08" B_PRIx32 "\n",
61985f64f90SAlexander von Gluck IV cpuInfo.regs.edx);
62085f64f90SAlexander von Gluck IV print_features(kAMDExtFeaturesPower, cpuInfo.regs.edx);
62185f64f90SAlexander von Gluck IV }
62285f64f90SAlexander von Gluck IV if (maxExtendedFunction >= 8) {
62385f64f90SAlexander von Gluck IV get_cpuid(&cpuInfo, 0x80000008, cpu);
62485f64f90SAlexander von Gluck IV printf("\tExtended Features (0x80000008): 0x%08" B_PRIx32 "\n",
62585f64f90SAlexander von Gluck IV cpuInfo.regs.ebx);
62685f64f90SAlexander von Gluck IV print_features(kAMDExtFeaturesTwo, cpuInfo.regs.ebx);
6271f5facdbSJerome Duval }
6281bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_TRANSMETA)
6291f5facdbSJerome Duval print_transmeta_features(cpuInfo.regs.edx);
6301f5facdbSJerome Duval }
6311f5facdbSJerome Duval
6321f5facdbSJerome Duval /* Cache/TLB descriptors */
6331f5facdbSJerome Duval if (maxExtendedFunction >= 5) {
6341f5facdbSJerome Duval if (!strncmp(baseInfo.eax_0.vendor_id, "CyrixInstead", 12)) {
6351f5facdbSJerome Duval get_cpuid(&cpuInfo, 0x00000002, cpu);
6361bc7045fSPawel Dziepak print_intel_cache_descriptors(vendor, model, &cpuInfo);
6371bc7045fSPawel Dziepak } else if (vendor == B_CPU_VENDOR_INTEL) {
6381f5facdbSJerome Duval // Intel does not support extended function 5 (but it does 6 hmm)
6391f5facdbSJerome Duval print_intel_cache_desc(cpu);
6401f5facdbSJerome Duval } else {
6411f5facdbSJerome Duval print_cache_desc(cpu);
6421f5facdbSJerome Duval }
6431f5facdbSJerome Duval }
6441f5facdbSJerome Duval
6451f5facdbSJerome Duval if (maxStandardFunction >= 2) {
6461f5facdbSJerome Duval do {
6471f5facdbSJerome Duval get_cpuid(&cpuInfo, 2, cpu);
6481f5facdbSJerome Duval
6491f5facdbSJerome Duval if (cpuInfo.eax_2.call_num > 0)
6501bc7045fSPawel Dziepak print_intel_cache_descriptors(vendor, model, &cpuInfo);
6511f5facdbSJerome Duval } while (cpuInfo.eax_2.call_num > 1);
6521f5facdbSJerome Duval }
6531f5facdbSJerome Duval
6541f5facdbSJerome Duval /* Serial number */
6551f5facdbSJerome Duval if (maxStandardFunction >= 3) {
6561f5facdbSJerome Duval cpuid_info flagsInfo;
6571f5facdbSJerome Duval get_cpuid(&flagsInfo, 1, cpu);
6581f5facdbSJerome Duval
6591f5facdbSJerome Duval if (flagsInfo.eax_1.features & (1UL << 18)) {
6601f5facdbSJerome Duval get_cpuid(&cpuInfo, 3, cpu);
661533f3bb4SAlex Smith printf("Serial number: %04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32
662533f3bb4SAlex Smith "-%04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 "\n",
663f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features >> 16,
664f1cbaf5cSAxel Dörfler flagsInfo.eax_1.features & 0xffff,
6651f5facdbSJerome Duval cpuInfo.regs.edx >> 16, cpuInfo.regs.edx & 0xffff,
6661f5facdbSJerome Duval cpuInfo.regs.ecx >> 16, cpuInfo.regs.edx & 0xffff);
6671f5facdbSJerome Duval }
6681f5facdbSJerome Duval }
6691f5facdbSJerome Duval
6701f5facdbSJerome Duval putchar('\n');
6711f5facdbSJerome Duval }
6721f5facdbSJerome Duval
6735ffbe7d7SAugustin Cavalier #endif // __i386__ || __x86_64__
6741f5facdbSJerome Duval
6751f5facdbSJerome Duval
6761f5facdbSJerome Duval static void
dump_cpus(system_info * info)6771f5facdbSJerome Duval dump_cpus(system_info *info)
6781f5facdbSJerome Duval {
6791bc7045fSPawel Dziepak uint32 topologyNodeCount = 0;
6801bc7045fSPawel Dziepak cpu_topology_node_info* topology = NULL;
6811bc7045fSPawel Dziepak get_cpu_topology_info(NULL, &topologyNodeCount);
6821bc7045fSPawel Dziepak if (topologyNodeCount != 0)
6831bc7045fSPawel Dziepak topology = new cpu_topology_node_info[topologyNodeCount];
6841bc7045fSPawel Dziepak get_cpu_topology_info(topology, &topologyNodeCount);
6851bc7045fSPawel Dziepak
6861bc7045fSPawel Dziepak enum cpu_platform platform = B_CPU_UNKNOWN;
6871bc7045fSPawel Dziepak enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN;
6881bc7045fSPawel Dziepak uint32 cpuModel = 0;
6891bc7045fSPawel Dziepak uint64 frequency = 0;
6901bc7045fSPawel Dziepak for (uint32 i = 0; i < topologyNodeCount; i++) {
6911bc7045fSPawel Dziepak switch (topology[i].type) {
6921bc7045fSPawel Dziepak case B_TOPOLOGY_ROOT:
6931bc7045fSPawel Dziepak platform = topology[i].data.root.platform;
6941bc7045fSPawel Dziepak break;
6951bc7045fSPawel Dziepak
6961bc7045fSPawel Dziepak case B_TOPOLOGY_PACKAGE:
6971bc7045fSPawel Dziepak cpuVendor = topology[i].data.package.vendor;
6981bc7045fSPawel Dziepak break;
6991bc7045fSPawel Dziepak
7001bc7045fSPawel Dziepak case B_TOPOLOGY_CORE:
7011bc7045fSPawel Dziepak cpuModel = topology[i].data.core.model;
7021bc7045fSPawel Dziepak frequency = topology[i].data.core.default_frequency;
7031bc7045fSPawel Dziepak break;
7041bc7045fSPawel Dziepak
7051bc7045fSPawel Dziepak default:
7061bc7045fSPawel Dziepak break;
7071bc7045fSPawel Dziepak }
7081bc7045fSPawel Dziepak }
7091bc7045fSPawel Dziepak delete[] topology;
7101bc7045fSPawel Dziepak
7111bc7045fSPawel Dziepak const char *vendor = get_cpu_vendor_string(cpuVendor);
7121bc7045fSPawel Dziepak const char *model = get_cpu_model_string(platform, cpuVendor, cpuModel);
7131f5facdbSJerome Duval char modelString[32];
7141f5facdbSJerome Duval
7151f5facdbSJerome Duval if (model == NULL && vendor == NULL)
7161f5facdbSJerome Duval model = "(Unknown)";
7171f5facdbSJerome Duval else if (model == NULL) {
7181f5facdbSJerome Duval model = modelString;
7191bc7045fSPawel Dziepak snprintf(modelString, 32, "(Unknown %" B_PRIx32 ")", cpuModel);
7201f5facdbSJerome Duval }
7211f5facdbSJerome Duval
722533f3bb4SAlex Smith printf("%" B_PRId32 " %s%s%s, revision %04" B_PRIx32 " running at %"
7231bc7045fSPawel Dziepak B_PRIu64 "MHz\n\n",
7241f5facdbSJerome Duval info->cpu_count,
7251f5facdbSJerome Duval vendor ? vendor : "", vendor ? " " : "", model,
7261bc7045fSPawel Dziepak cpuModel,
7271bc7045fSPawel Dziepak frequency / 1000000);
7281f5facdbSJerome Duval
7295ffbe7d7SAugustin Cavalier #if defined(__i386__) || defined(__x86_64__)
7301bc7045fSPawel Dziepak for (uint32 cpu = 0; cpu < info->cpu_count; cpu++)
7311bc7045fSPawel Dziepak dump_cpu(cpuVendor, cpuModel, cpu);
7325ffbe7d7SAugustin Cavalier #endif // __i386__ || __x86_64__
7331f5facdbSJerome Duval }
7341f5facdbSJerome Duval
7351f5facdbSJerome Duval
7361f5facdbSJerome Duval static void
dump_mem(system_info * info)7371f5facdbSJerome Duval dump_mem(system_info *info)
7381f5facdbSJerome Duval {
739d1a2f637SAlex Smith printf("%10" B_PRIu64 " bytes free (used/max %10" B_PRIu64 " / %10"
740d1a2f637SAlex Smith B_PRIu64 ")\n",
741d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)(info->max_pages - info->used_pages),
742d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->used_pages,
743d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->max_pages);
744d1a2f637SAlex Smith printf(" (cached %10" B_PRIu64 ")\n",
745d1a2f637SAlex Smith B_PAGE_SIZE * (uint64)info->cached_pages);
7461f5facdbSJerome Duval }
7471f5facdbSJerome Duval
7481f5facdbSJerome Duval
7491f5facdbSJerome Duval static void
dump_sem(system_info * info)7501f5facdbSJerome Duval dump_sem(system_info *info)
7511f5facdbSJerome Duval {
752533f3bb4SAlex Smith printf("%10" B_PRId32 " semaphores free (used/max %10" B_PRId32 " / %10"
753533f3bb4SAlex Smith B_PRId32 ")\n",
7541f5facdbSJerome Duval info->max_sems - info->used_sems,
7551f5facdbSJerome Duval info->used_sems, info->max_sems);
7561f5facdbSJerome Duval }
7571f5facdbSJerome Duval
7581f5facdbSJerome Duval
7591f5facdbSJerome Duval static void
dump_ports(system_info * info)7601f5facdbSJerome Duval dump_ports(system_info *info)
7611f5facdbSJerome Duval {
762533f3bb4SAlex Smith printf("%10" B_PRId32 " ports free (used/max %10" B_PRId32 " / %10"
763533f3bb4SAlex Smith B_PRId32 ")\n",
7641f5facdbSJerome Duval info->max_ports - info->used_ports,
7651f5facdbSJerome Duval info->used_ports, info->max_ports);
7661f5facdbSJerome Duval }
7671f5facdbSJerome Duval
7681f5facdbSJerome Duval
7691f5facdbSJerome Duval static void
dump_thread(system_info * info)7701f5facdbSJerome Duval dump_thread(system_info *info)
7711f5facdbSJerome Duval {
772533f3bb4SAlex Smith printf("%10" B_PRId32 " threads free (used/max %10" B_PRId32 " / %10"
773533f3bb4SAlex Smith B_PRId32 ")\n",
7741f5facdbSJerome Duval info->max_threads - info->used_threads,
7751f5facdbSJerome Duval info->used_threads, info->max_threads);
7761f5facdbSJerome Duval }
7771f5facdbSJerome Duval
7781f5facdbSJerome Duval
7791f5facdbSJerome Duval static void
dump_team(system_info * info)7801f5facdbSJerome Duval dump_team(system_info *info)
7811f5facdbSJerome Duval {
782533f3bb4SAlex Smith printf("%10" B_PRId32 " teams free (used/max %10" B_PRId32 " / %10"
783533f3bb4SAlex Smith B_PRId32 ")\n",
7841f5facdbSJerome Duval info->max_teams - info->used_teams,
7851f5facdbSJerome Duval info->used_teams, info->max_teams);
7861f5facdbSJerome Duval }
7871f5facdbSJerome Duval
7881f5facdbSJerome Duval
7891f5facdbSJerome Duval static void
dump_kinfo(system_info * info)7901f5facdbSJerome Duval dump_kinfo(system_info *info)
7911f5facdbSJerome Duval {
792533f3bb4SAlex Smith printf("Kernel name: %s built on: %s %s version 0x%" B_PRIx64 "\n",
7931f5facdbSJerome Duval info->kernel_name,
7941f5facdbSJerome Duval info->kernel_build_date, info->kernel_build_time,
7951f5facdbSJerome Duval info->kernel_version );
7961f5facdbSJerome Duval }
7971f5facdbSJerome Duval
7981f5facdbSJerome Duval
7991f5facdbSJerome Duval static void
dump_system_info(system_info * info)8001f5facdbSJerome Duval dump_system_info(system_info *info)
8011f5facdbSJerome Duval {
8021f5facdbSJerome Duval dump_kinfo(info);
8031f5facdbSJerome Duval dump_cpus(info);
8041f5facdbSJerome Duval dump_mem(info);
8051f5facdbSJerome Duval dump_sem(info);
8061f5facdbSJerome Duval dump_ports(info);
8071f5facdbSJerome Duval dump_thread(info);
8081f5facdbSJerome Duval dump_team(info);
8091f5facdbSJerome Duval }
8101f5facdbSJerome Duval
8111f5facdbSJerome Duval
8121f5facdbSJerome Duval int
main(int argc,char * argv[])8131f5facdbSJerome Duval main(int argc, char *argv[])
8141f5facdbSJerome Duval {
8151f5facdbSJerome Duval if (!is_computer_on()) {
8161f5facdbSJerome Duval printf("The computer is not on! No info available\n");
8171f5facdbSJerome Duval exit(EXIT_FAILURE);
8181f5facdbSJerome Duval }
8191f5facdbSJerome Duval
8201f5facdbSJerome Duval system_info info;
8211f5facdbSJerome Duval if (get_system_info(&info) != B_OK) {
8221f5facdbSJerome Duval printf("Error getting system information!\n");
8231f5facdbSJerome Duval return 1;
8241f5facdbSJerome Duval }
8251f5facdbSJerome Duval
8261f5facdbSJerome Duval if (argc <= 1) {
8271f5facdbSJerome Duval dump_system_info(&info);
8281f5facdbSJerome Duval } else {
8291f5facdbSJerome Duval for (int i = 1; i < argc; i++) {
8301f5facdbSJerome Duval const char *opt = argv[i];
8311f5facdbSJerome Duval if (strncmp(opt, "-id", strlen(opt)) == 0) {
8321f5facdbSJerome Duval /* note: the original also assumes this option on "sysinfo -" */
8331bc7045fSPawel Dziepak printf("%#.8x %#.8x\n", 0,0);
8341f5facdbSJerome Duval } else if (strncmp(opt, "-cpu", strlen(opt)) == 0) {
8351f5facdbSJerome Duval dump_cpus(&info);
8361f5facdbSJerome Duval } else if (strncmp(opt, "-mem", strlen(opt)) == 0) {
8371f5facdbSJerome Duval dump_mem(&info);
8381f5facdbSJerome Duval } else if (strncmp(opt, "-semaphores", strlen(opt)) == 0) {
8391f5facdbSJerome Duval dump_sem(&info);
8401f5facdbSJerome Duval } else if (strncmp(opt, "-ports", strlen(opt)) == 0) {
8411f5facdbSJerome Duval dump_ports(&info);
8421f5facdbSJerome Duval } else if (strncmp(opt, "-threads", strlen(opt)) == 0) {
8431f5facdbSJerome Duval dump_thread(&info);
8441f5facdbSJerome Duval } else if (strncmp(opt, "-teams", strlen(opt)) == 0) {
8451f5facdbSJerome Duval dump_team(&info);
8461f5facdbSJerome Duval } else if (strncmp(opt, "-kinfo", strlen(opt)) == 0) {
8471f5facdbSJerome Duval dump_kinfo(&info);
8481f5facdbSJerome Duval } else if (strncmp(opt, "-platform", strlen(opt)) == 0) {
8491f5facdbSJerome Duval dump_platform(&info);
8501f5facdbSJerome Duval } else if (strncmp(opt, "-disable_cpu_sn", strlen(opt)) == 0) {
8511f5facdbSJerome Duval /* TODO: printf("CPU #%d serial number: old state: %s, new state: %s\n", ... ); */
8521f5facdbSJerome Duval fprintf(stderr, "Sorry, not yet implemented\n");
8531f5facdbSJerome Duval } else {
8541f5facdbSJerome Duval const char *name = strrchr(argv[0], '/');
8551f5facdbSJerome Duval if (name == NULL)
8561f5facdbSJerome Duval name = argv[0];
8571f5facdbSJerome Duval else
8581f5facdbSJerome Duval name++;
8591f5facdbSJerome Duval
8601f5facdbSJerome Duval fprintf(stderr, "Usage:\n");
8611f5facdbSJerome Duval fprintf(stderr, " %s [-id|-cpu|-mem|-semaphore|-ports|-threads|-teams|-platform|-disable_cpu_sn|-kinfo]\n", name);
8621f5facdbSJerome Duval return 0;
8631f5facdbSJerome Duval }
8641f5facdbSJerome Duval }
8651f5facdbSJerome Duval }
8661f5facdbSJerome Duval return 0;
8671f5facdbSJerome Duval }
868