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