xref: /haiku/src/bin/sysinfo.cpp (revision 11c9f9a1d649c006f9066ae9436372ab75728c4b)
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