Compare commits

..

29 Commits

Author SHA1 Message Date
Dr-Noob
9b8e85422d [v1.05] Clean up previous commit 2024-07-04 21:51:30 +01:00
Dr-Noob
17dd9a41d2 [v1.05] Simplify implementation; we do not need separate x86/ARM nop functions 2024-07-04 21:49:43 +01:00
Dr-Noob
bb3d23e193 [v1.05] Do not show debug frequency message 2024-02-20 08:42:36 +00:00
Dr-Noob
b4bc3fdf3d [v1.05][X86] Show SSE if AVX/FMA is not supported 2024-02-18 18:34:24 +00:00
Dr-Noob
31fc312337 [v1.05][X86] Do not stop if cach is NULL and check for non-NULL cache in get_topology_info functions 2024-02-18 18:24:30 +00:00
Dr-Noob
262049dee2 [v1.05][X86] Fix bug where the number of cpus were not set if NULL was returned inside the loop. Ensure topo is not NULL in get_peak_performance. Fallback to UNKNOWN_DATA when we have no information about topology 2024-02-18 18:22:35 +00:00
Dr-Noob
748b369321 [v1.05] Fix compilation issue in x86 2024-02-18 17:53:06 +00:00
Dr-Noob
35483cc493 [v1.05] Improve error reporting due to perf_event_paranoid issues 2024-02-16 23:54:08 +01:00
Dr-Noob
670af7b61c [v1.05] Fix several issues in ARM 2024-02-16 23:45:20 +01:00
Dr-Noob
d71a461d83 [v1.05] Add support for frequency measurement in ARM (had to move bind_to_cpu to common dir) 2024-02-16 23:37:37 +01:00
Dr-Noob
72eee0e08e [v1.05] Experimental max frequency measurement (x86 only) 2024-02-14 08:48:27 +00:00
Dr-Noob
cc16bc56ef [v1.05][X86] Improve support for old x86 CPUs (#220) by improving Pentium uarch detection and adding support to infer the CPU name from uarch when the corresponding CPUID level is not available 2024-02-13 21:29:08 +00:00
Dr-Noob
1504c5d0ef [v1.05][X86] Report x86 / x86_64 in ARCH_X86 builds 2024-02-13 21:26:24 +00:00
Dr-Noob
08919916dc [v1.05] Always print manufacturing process in nanometers (this indirectly fixes a bug of processes in micrometers being incorrectly reported by 10x 2024-02-13 21:24:16 +00:00
Dr-Noob
4a8a7567f0 [v1.05] Add support for NO_COLOR (#227) 2024-02-13 08:41:54 +00:00
Dr-Noob
c01f60fa6c [v1.05] Implement new approach to infer SoC from the uarch. Add support for Kunpeng SoCs 2024-02-08 09:04:51 +00:00
Dr-Noob
b610dc8c7d [v1.05] Bump version 2024-02-05 18:33:15 +00:00
Dr-Noob
0967e3597b [v1.04] Fix error in previous commit 2024-02-05 09:48:46 +01:00
Dr-Noob
14df701707 [v1.04] Check release when printing error also in Apple chip failures 2024-02-05 08:46:17 +00:00
Dr-Noob
cbcce9c2ed [v1.04] Improve error reporting in the case of unkown microarchitectures. As pointed out in #224 this was already solved, but this commit tries to be an improvement over the previous implementation 2024-02-05 08:37:59 +00:00
Dr-Noob
b072e5c331 [v1.04] Update acknowledgements 2024-02-01 22:40:58 +00:00
Dr-Noob
4b42d2c89d [v1.04][ARM] Extend Allwinner SoC list (#207) 2024-02-01 23:26:23 +01:00
Dr-Noob
d221f578b7 [v1.04][ARM] Use sysctl to fetch topology in Apple SoCs 2024-01-25 09:33:22 +01:00
Dr-Noob
7b4b94bb93 [v1.04] Fix typo in Rockchip SoC detection 2024-01-22 07:18:15 +00:00
Dr-Noob
5e00d554aa [v1.04][ARM] Fix number of cores per cluster in M2 and M3 SoCs (#183) 2024-01-17 08:48:58 +00:00
Dr-Noob
5ffac60622 [v1.04][ARM] Support for reverse ordering in Rockchip SoCs 2024-01-17 09:37:15 +01:00
Dr-Noob
6566ac3ccf [v1.04] Add Apple VZ hypervisor (#218) 2024-01-15 08:43:28 +00:00
Dr-Noob
0a048717bf [v1.04][X86] Fix bug in AMD CPUs (#212) 2023-12-24 23:03:20 +00:00
Dr-Noob
ce6e6f9cd8 [v1.04][ARM] Preeliminary M3 support 2023-12-24 22:42:01 +00:00
30 changed files with 750 additions and 387 deletions

View File

@@ -7,8 +7,8 @@ PREFIX ?= /usr
SRC_COMMON=src/common/ SRC_COMMON=src/common/
COMMON_SRC = $(SRC_COMMON)main.c $(SRC_COMMON)cpu.c $(SRC_COMMON)udev.c $(SRC_COMMON)printer.c $(SRC_COMMON)args.c $(SRC_COMMON)global.c COMMON_SRC = $(SRC_COMMON)main.c $(SRC_COMMON)cpu.c $(SRC_COMMON)udev.c $(SRC_COMMON)printer.c $(SRC_COMMON)args.c $(SRC_COMMON)global.c $(SRC_COMMON)freq.c
COMMON_HDR = $(SRC_COMMON)ascii.h $(SRC_COMMON)cpu.h $(SRC_COMMON)udev.h $(SRC_COMMON)printer.h $(SRC_COMMON)args.h $(SRC_COMMON)global.h COMMON_HDR = $(SRC_COMMON)ascii.h $(SRC_COMMON)cpu.h $(SRC_COMMON)udev.h $(SRC_COMMON)printer.h $(SRC_COMMON)args.h $(SRC_COMMON)global.h $(SRC_COMMON)freq.h
ifneq ($(OS),Windows_NT) ifneq ($(OS),Windows_NT)
GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)" GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)"

View File

@@ -174,6 +174,7 @@ Thanks to the fellow contributors and interested people in the project. Special
- [bbonev](https://github.com/bbonev) and [stephan-cr](https://github.com/stephan-cr): Reviewed the source code. - [bbonev](https://github.com/bbonev) and [stephan-cr](https://github.com/stephan-cr): Reviewed the source code.
- [mdoksa76](https://github.com/mdoksa76) and [exkc](https://github.com/exkc): Excellent ideas and feedback for supporting Allwinner SoCs. - [mdoksa76](https://github.com/mdoksa76) and [exkc](https://github.com/exkc): Excellent ideas and feedback for supporting Allwinner SoCs.
- [Sakura286](https://github.com/Sakura286), [exkc](https://github.com/exkc) and [Patola](https://github.com/Patola): Helped with RISC-V port with ssh access, ideas, testing, etc. - [Sakura286](https://github.com/Sakura286), [exkc](https://github.com/exkc) and [Patola](https://github.com/Patola): Helped with RISC-V port with ssh access, ideas, testing, etc.
- [ThomasKaiser](https://github.com/ThomasKaiser): Very valuable feedback on improving ARM SoC detection (Apple, Allwinner, Rockchip).
## 8. cpufetch for GPUs (gpufetch) ## 8. cpufetch for GPUs (gpufetch)
See [gpufetch](https://github.com/Dr-Noob/gpufetch) project! See [gpufetch](https://github.com/Dr-Noob/gpufetch) project!

View File

@@ -14,6 +14,7 @@
#include "../common/global.h" #include "../common/global.h"
#include "../common/soc.h" #include "../common/soc.h"
#include "../common/freq.h"
#include "udev.h" #include "udev.h"
#include "midr.h" #include "midr.h"
#include "uarch.h" #include "uarch.h"
@@ -41,6 +42,12 @@ struct frequency* get_frequency_info(uint32_t core) {
freq->base = UNKNOWN_DATA; freq->base = UNKNOWN_DATA;
freq->max = get_max_freq_from_file(core); freq->max = get_max_freq_from_file(core);
#ifdef __linux__
if (freq->max == UNKNOWN_DATA) {
printWarn("Unable to find max frequency from udev, measuring CPU frequency");
freq->max = measure_max_frequency(core);
}
#endif
return freq; return freq;
} }
@@ -237,7 +244,7 @@ struct cpuInfo* get_cpu_info_linux(struct cpuInfo* cpu) {
cpu->num_cpus = sockets; cpu->num_cpus = sockets;
cpu->hv = emalloc(sizeof(struct hypervisor)); cpu->hv = emalloc(sizeof(struct hypervisor));
cpu->hv->present = false; cpu->hv->present = false;
cpu->soc = get_soc(); cpu->soc = get_soc(cpu);
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);
return cpu; return cpu;
@@ -289,7 +296,7 @@ void fill_cpu_info_avalanche_blizzard(struct cpuInfo* cpu, uint32_t pcores, uint
bli->feat = get_features_info(); bli->feat = get_features_info();
bli->topo = malloc(sizeof(struct topology)); bli->topo = malloc(sizeof(struct topology));
bli->topo->cach = bli->cach; bli->topo->cach = bli->cach;
bli->topo->total_cores = pcores; bli->topo->total_cores = ecores;
bli->freq = malloc(sizeof(struct frequency)); bli->freq = malloc(sizeof(struct frequency));
bli->freq->base = UNKNOWN_DATA; bli->freq->base = UNKNOWN_DATA;
bli->freq->max = 2800; bli->freq->max = 2800;
@@ -305,7 +312,7 @@ void fill_cpu_info_avalanche_blizzard(struct cpuInfo* cpu, uint32_t pcores, uint
ava->feat = get_features_info(); ava->feat = get_features_info();
ava->topo = malloc(sizeof(struct topology)); ava->topo = malloc(sizeof(struct topology));
ava->topo->cach = ava->cach; ava->topo->cach = ava->cach;
ava->topo->total_cores = ecores; ava->topo->total_cores = pcores;
ava->freq = malloc(sizeof(struct frequency)); ava->freq = malloc(sizeof(struct frequency));
ava->freq->base = UNKNOWN_DATA; ava->freq->base = UNKNOWN_DATA;
ava->freq->max = 3500; ava->freq->max = 3500;
@@ -324,7 +331,7 @@ void fill_cpu_info_everest_sawtooth(struct cpuInfo* cpu, uint32_t pcores, uint32
saw->feat = get_features_info(); saw->feat = get_features_info();
saw->topo = malloc(sizeof(struct topology)); saw->topo = malloc(sizeof(struct topology));
saw->topo->cach = saw->cach; saw->topo->cach = saw->cach;
saw->topo->total_cores = pcores; saw->topo->total_cores = ecores;
saw->freq = malloc(sizeof(struct frequency)); saw->freq = malloc(sizeof(struct frequency));
saw->freq->base = UNKNOWN_DATA; saw->freq->base = UNKNOWN_DATA;
saw->freq->max = 2750; saw->freq->max = 2750;
@@ -340,7 +347,7 @@ void fill_cpu_info_everest_sawtooth(struct cpuInfo* cpu, uint32_t pcores, uint32
eve->feat = get_features_info(); eve->feat = get_features_info();
eve->topo = malloc(sizeof(struct topology)); eve->topo = malloc(sizeof(struct topology));
eve->topo->cach = eve->cach; eve->topo->cach = eve->cach;
eve->topo->total_cores = ecores; eve->topo->total_cores = pcores;
eve->freq = malloc(sizeof(struct frequency)); eve->freq = malloc(sizeof(struct frequency));
eve->freq->base = UNKNOWN_DATA; eve->freq->base = UNKNOWN_DATA;
eve->freq->max = 4050; eve->freq->max = 4050;
@@ -350,97 +357,47 @@ void fill_cpu_info_everest_sawtooth(struct cpuInfo* cpu, uint32_t pcores, uint32
} }
struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) { struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) {
uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily"); // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities
uint32_t nperflevels = get_sys_info_by_name("hw.nperflevels");
if((cpu->num_cpus = nperflevels) != 2) {
printBug("Expected to find SoC with 2 perf levels, found: %d", cpu->num_cpus);
return NULL;
}
uint32_t pcores = get_sys_info_by_name("hw.perflevel0.physicalcpu");
uint32_t ecores = get_sys_info_by_name("hw.perflevel1.physicalcpu");
if(ecores <= 0) {
printBug("Expected to find a numer of ecores > 0, found: %d", ecores);
return NULL;
}
if(pcores <= 0) {
printBug("Expected to find a numer of pcores > 0, found: %d", pcores);
return NULL;
}
uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily");
// Manually fill the cpuInfo assuming that // Manually fill the cpuInfo assuming that
// the CPU is an Apple M1/M2 // the CPU is an Apple SoC
if(cpu_family == CPUFAMILY_ARM_FIRESTORM_ICESTORM) { if(cpu_family == CPUFAMILY_ARM_FIRESTORM_ICESTORM) {
cpu->num_cpus = 2; fill_cpu_info_firestorm_icestorm(cpu, pcores, ecores);
// Now detect the M1 version cpu->soc = get_soc(cpu);
uint32_t cpu_subfamily = get_sys_info_by_name("hw.cpusubfamily");
if(cpu_subfamily == CPUSUBFAMILY_ARM_HG) {
// Apple M1
fill_cpu_info_firestorm_icestorm(cpu, 4, 4);
}
else if(cpu_subfamily == CPUSUBFAMILY_ARM_HS || cpu_subfamily == CPUSUBFAMILY_ARM_HC_HD) {
// Apple M1 Pro/Max/Ultra. Detect number of cores
uint32_t physicalcpu = get_sys_info_by_name("hw.physicalcpu");
if(physicalcpu == 20) {
// M1 Ultra
fill_cpu_info_firestorm_icestorm(cpu, 16, 4);
}
else if(physicalcpu == 8 || physicalcpu == 10) {
// M1 Pro/Max
fill_cpu_info_firestorm_icestorm(cpu, physicalcpu-2, 2);
}
else {
printBug("Found invalid physical cpu number: %d", physicalcpu);
return NULL;
}
}
else {
printBug("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily);
return NULL;
}
cpu->soc = get_soc();
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);
} }
else if(cpu_family == CPUFAMILY_ARM_AVALANCHE_BLIZZARD) { else if(cpu_family == CPUFAMILY_ARM_AVALANCHE_BLIZZARD) {
cpu->num_cpus = 2; fill_cpu_info_avalanche_blizzard(cpu, pcores, ecores);
// Now detect the M2 version cpu->soc = get_soc(cpu);
uint32_t cpu_subfamily = get_sys_info_by_name("hw.cpusubfamily");
if(cpu_subfamily == CPUSUBFAMILY_ARM_HG) {
// Apple M2
fill_cpu_info_avalanche_blizzard(cpu, 4, 4);
}
else if(cpu_subfamily == CPUSUBFAMILY_ARM_HS) {
// Apple M2 Pro/Max/Ultra. Detect number of cores
uint32_t physicalcpu = get_sys_info_by_name("hw.physicalcpu");
if(physicalcpu == 24) {
// M2 Ultra
fill_cpu_info_avalanche_blizzard(cpu, 16, 8);
}
else if(physicalcpu == 10 || physicalcpu == 12) {
// M2 Pro/Max
fill_cpu_info_avalanche_blizzard(cpu, physicalcpu-4, 4);
}
else {
printBug("Found invalid physical cpu number: %d", physicalcpu);
return NULL;
}
}
else {
printBug("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily);
return NULL;
}
cpu->soc = get_soc();
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);
} }
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH || else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO || cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) { cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) {
cpu->num_cpus = 2; fill_cpu_info_everest_sawtooth(cpu, pcores, ecores);
// Now detect the M3 version cpu->soc = get_soc(cpu);
if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH) {
fill_cpu_info_everest_sawtooth(cpu, 4, 4);
}
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO) {
uint32_t physicalcpu = get_sys_info_by_name("hw.physicalcpu");
fill_cpu_info_everest_sawtooth(cpu, physicalcpu-6, 6);
}
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) {
uint32_t physicalcpu = get_sys_info_by_name("hw.physicalcpu");
fill_cpu_info_everest_sawtooth(cpu, physicalcpu-4, 4);
}
else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family);
return NULL;
}
cpu->soc = get_soc();
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);
} }
else { else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family); printBugCheckRelease("Found invalid cpu_family: 0x%.8X", cpu_family);
return NULL; return NULL;
} }
@@ -529,7 +486,10 @@ void print_debug(struct cpuInfo* cpu) {
#if defined(__APPLE__) || defined(__MACH__) #if defined(__APPLE__) || defined(__MACH__)
printf("hw.cpufamily: 0x%.8X\n", get_sys_info_by_name("hw.cpufamily")); printf("hw.cpufamily: 0x%.8X\n", get_sys_info_by_name("hw.cpufamily"));
printf("hw.cpusubfamily: 0x%.8X\n", get_sys_info_by_name("hw.cpusubfamily")); printf("hw.cpusubfamily: 0x%.8X\n", get_sys_info_by_name("hw.cpusubfamily"));
printf("hw.nperflevels: %d\n", get_sys_info_by_name("hw.nperflevels"));
printf("hw.physicalcpu: %d\n", get_sys_info_by_name("hw.physicalcpu")); printf("hw.physicalcpu: %d\n", get_sys_info_by_name("hw.physicalcpu"));
printf("hw.perflevel0.physicalcpu: %d\n", get_sys_info_by_name("hw.perflevel0.physicalcpu"));
printf("hw.perflevel1.physicalcpu: %d\n", get_sys_info_by_name("hw.perflevel1.physicalcpu"));
#endif #endif
} }

View File

@@ -6,6 +6,7 @@
#include "soc.h" #include "soc.h"
#include "socs.h" #include "socs.h"
#include "udev.h" #include "udev.h"
#include "uarch.h"
#include "../common/global.h" #include "../common/global.h"
#if defined(__APPLE__) || defined(__MACH__) #if defined(__APPLE__) || defined(__MACH__)
@@ -50,6 +51,8 @@ uint32_t get_sid_from_nvmem(char* buf) {
// SIDs list: // SIDs list:
// - https://linux-sunxi.org/SID_Register_Guide#Currently_known_SID.27s // - https://linux-sunxi.org/SID_Register_Guide#Currently_known_SID.27s
// - https://github.com/Dr-Noob/cpufetch/issues/173 // - https://github.com/Dr-Noob/cpufetch/issues/173
// - https://github.com/ThomasKaiser/sbc-bench/blob/master/sbc-bench.sh
// - https://linux-sunxi.org/*CHIP_NAME*
bool get_sunxisoc_from_sid(struct system_on_chip* soc, char* raw_name, uint32_t sid) { bool get_sunxisoc_from_sid(struct system_on_chip* soc, char* raw_name, uint32_t sid) {
typedef struct { typedef struct {
uint32_t sid; uint32_t sid;
@@ -58,23 +61,41 @@ bool get_sunxisoc_from_sid(struct system_on_chip* soc, char* raw_name, uint32_t
sidToSoC socFromSid[] = { sidToSoC socFromSid[] = {
// --- sun8i Family --- // --- sun8i Family ---
// A33
{0x0461872a, {SOC_ALLWINNER_A33, SOC_VENDOR_ALLWINNER, 40, "A33", raw_name} },
// A83T
{0x32c00401, {SOC_ALLWINNER_A83T, SOC_VENDOR_ALLWINNER, 28, "A83T", raw_name} },
{0x32c00403, {SOC_ALLWINNER_A83T, SOC_VENDOR_ALLWINNER, 28, "A83T", raw_name} },
// S3
{0x12c00001, {SOC_ALLWINNER_S3, SOC_VENDOR_ALLWINNER, 40, "S3", raw_name} },
// H2+ // H2+
{0x02c00042, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} }, {0x02c00042, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} },
{0x02c00142, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} }, {0x02c00142, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} },
{0x02c00242, {SOC_ALLWINNER_H2PLUS, SOC_VENDOR_ALLWINNER, 40, "H2+", raw_name} },
// H3 // H3
{0x02c00181, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} }, {0x02c00181, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} },
{0x02c00081, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} }, {0x02c00081, {SOC_ALLWINNER_H3, SOC_VENDOR_ALLWINNER, 40, "H3", raw_name} },
// Others // R40
{0x12c00017, {SOC_ALLWINNER_R40, SOC_VENDOR_ALLWINNER, 40, "R40", raw_name} }, {0x12c00017, {SOC_ALLWINNER_R40, SOC_VENDOR_ALLWINNER, 40, "R40", raw_name} },
// V3S
{0x12c00000, {SOC_ALLWINNER_V3S, SOC_VENDOR_ALLWINNER, 40, "V3s", raw_name} }, // 40nm is only my guess, no source {0x12c00000, {SOC_ALLWINNER_V3S, SOC_VENDOR_ALLWINNER, 40, "V3s", raw_name} }, // 40nm is only my guess, no source
// --- sun50i Family --- // --- sun50i Family ---
// H5
{0x82800001, {SOC_ALLWINNER_H5, SOC_VENDOR_ALLWINNER, 40, "H5", raw_name} }, {0x82800001, {SOC_ALLWINNER_H5, SOC_VENDOR_ALLWINNER, 40, "H5", raw_name} },
// H6
{0x82c00001, {SOC_ALLWINNER_H6, SOC_VENDOR_ALLWINNER, 28, "H6", raw_name} },
{0x82c00007, {SOC_ALLWINNER_H6, SOC_VENDOR_ALLWINNER, 28, "H6", raw_name} }, {0x82c00007, {SOC_ALLWINNER_H6, SOC_VENDOR_ALLWINNER, 28, "H6", raw_name} },
{0x92c000bb, {SOC_ALLWINNER_H64, SOC_VENDOR_ALLWINNER, 40, "H64", raw_name} }, // Same as A64 // H64
{0x92c000bb, {SOC_ALLWINNER_H64, SOC_VENDOR_ALLWINNER, 40, "H64", raw_name} }, // Same manufacturing process as A64
// H616
{0x32c05000, {SOC_ALLWINNER_H616, SOC_VENDOR_ALLWINNER, 28, "H616", raw_name} }, {0x32c05000, {SOC_ALLWINNER_H616, SOC_VENDOR_ALLWINNER, 28, "H616", raw_name} },
// H618
{0x33802000, {SOC_ALLWINNER_H618, SOC_VENDOR_ALLWINNER, 28, "H618", raw_name} },
// A64
{0x92c000ba, {SOC_ALLWINNER_A64, SOC_VENDOR_ALLWINNER, 40, "A64", raw_name} }, {0x92c000ba, {SOC_ALLWINNER_A64, SOC_VENDOR_ALLWINNER, 40, "A64", raw_name} },
{0x92c001ba, {SOC_ALLWINNER_A64, SOC_VENDOR_ALLWINNER, 40, "A64", raw_name} },
// Unknown // Unknown
{0x00000000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", raw_name} } {0x00000000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", raw_name} }
}; };
int index = 0; int index = 0;
@@ -734,6 +755,7 @@ bool get_rk_soc_from_efuse(struct system_on_chip* soc, char* efuse) {
rkToSoC socFromRK[] = { rkToSoC socFromRK[] = {
// TODO: Add RK2XXX // TODO: Add RK2XXX
// RK3XXX // RK3XXX
// Reverse order
{0x2388, {SOC_ROCKCHIP_3288, SOC_VENDOR_ROCKCHIP, 28, "RK3288", NULL} }, {0x2388, {SOC_ROCKCHIP_3288, SOC_VENDOR_ROCKCHIP, 28, "RK3288", NULL} },
{0x2392, {SOC_ROCKCHIP_3229, SOC_VENDOR_ROCKCHIP, 28, "RK3229", NULL} }, // https://gadgetversus.com/processor/rockchip-rk3229-vs-rockchip-rk3128/ {0x2392, {SOC_ROCKCHIP_3229, SOC_VENDOR_ROCKCHIP, 28, "RK3229", NULL} }, // https://gadgetversus.com/processor/rockchip-rk3229-vs-rockchip-rk3128/
{0x3380, {SOC_ROCKCHIP_3308, SOC_VENDOR_ROCKCHIP, 28, "RK3308", NULL} }, // https://en.t-firefly.com/product/rocrk3308cc?theme=pc {0x3380, {SOC_ROCKCHIP_3308, SOC_VENDOR_ROCKCHIP, 28, "RK3308", NULL} }, // https://en.t-firefly.com/product/rocrk3308cc?theme=pc
@@ -742,10 +764,12 @@ bool get_rk_soc_from_efuse(struct system_on_chip* soc, char* efuse) {
{0x3382, {SOC_ROCKCHIP_3328, SOC_VENDOR_ROCKCHIP, 28, "RK3328", NULL} }, {0x3382, {SOC_ROCKCHIP_3328, SOC_VENDOR_ROCKCHIP, 28, "RK3328", NULL} },
{0x3386, {SOC_ROCKCHIP_3368, SOC_VENDOR_ROCKCHIP, 28, "RK3368", NULL} }, {0x3386, {SOC_ROCKCHIP_3368, SOC_VENDOR_ROCKCHIP, 28, "RK3368", NULL} },
{0x3399, {SOC_ROCKCHIP_3399, SOC_VENDOR_ROCKCHIP, 28, "RK3399", NULL} }, {0x3399, {SOC_ROCKCHIP_3399, SOC_VENDOR_ROCKCHIP, 28, "RK3399", NULL} },
{0x5366, {SOC_ROCKCHIP_3566, SOC_VENDOR_ROCKCHIP, 22, "RK3566", NULL} }, // Normal Order (https://github.com/Dr-Noob/cpufetch/issues/209)
{0x5386, {SOC_ROCKCHIP_3568, SOC_VENDOR_ROCKCHIP, 22, "RK3568", NULL} }, {0x3528, {SOC_ROCKCHIP_3528, SOC_VENDOR_ROCKCHIP, 28, "RK3528", NULL} },
{0x5388, {SOC_ROCKCHIP_3588, SOC_VENDOR_ROCKCHIP, 8, "RK3588", NULL} }, {0x3562, {SOC_ROCKCHIP_3562, SOC_VENDOR_ROCKCHIP, 22, "RK3562", NULL} },
{0x3588, {SOC_ROCKCHIP_3588S, SOC_VENDOR_ROCKCHIP, 8, "RK3588S", NULL} }, // https://github.com/Dr-Noob/cpufetch/issues/188 {0x3566, {SOC_ROCKCHIP_3566, SOC_VENDOR_ROCKCHIP, 22, "RK3566", NULL} },
{0x3568, {SOC_ROCKCHIP_3568, SOC_VENDOR_ROCKCHIP, 22, "RK3568", NULL} },
{0x3588, {SOC_ROCKCHIP_3588, SOC_VENDOR_ROCKCHIP, 8, "RK3588", NULL} }, // No known way to distingish between S version: https://github.com/Dr-Noob/cpufetch/issues/188,209
// Unknown // Unknown
{0x0000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", NULL} } {0x0000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", NULL} }
}; };
@@ -778,6 +802,38 @@ struct system_on_chip* guess_soc_from_nvmem(struct system_on_chip* soc) {
return soc; return soc;
} }
struct system_on_chip* guess_soc_from_uarch(struct system_on_chip* soc, struct cpuInfo* cpu) {
// Currently we only support CPUs with only one uarch (in other words, one socket)
struct uarch* arch = cpu->arch;
if (arch == NULL) {
printWarn("guess_soc_from_uarch: uarch is NULL");
return soc;
}
typedef struct {
MICROARCH u;
struct system_on_chip soc;
} uarchToSoC;
uarchToSoC socFromUarch[] = {
{UARCH_TAISHAN_V110, {SOC_KUNPENG_920, SOC_VENDOR_KUNPENG, 7, "920", NULL} },
{UARCH_TAISHAN_V200, {SOC_KUNPENG_930, SOC_VENDOR_KUNPENG, 7, "930", NULL} }, // manufacturing process is not well-known
{UARCH_UNKNOWN, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", NULL} }
};
int index = 0;
while(socFromUarch[index].u != UARCH_UNKNOWN) {
if(socFromUarch[index].u == get_uarch(arch)) {
fill_soc(soc, socFromUarch[index].soc.soc_name, socFromUarch[index].soc.soc_model, socFromUarch[index].soc.process);
return soc;
}
index++;
}
printWarn("guess_soc_from_uarch: No uarch matched the list");
return soc;
}
int hex2int(char c) { int hex2int(char c) {
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
return c - '0'; return c - '0';
@@ -855,7 +911,7 @@ struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) {
} }
} }
else { else {
printBug("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily); printBugCheckRelease("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily);
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
} }
} }
@@ -882,7 +938,7 @@ struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) {
} }
} }
else { else {
printBug("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily); printBugCheckRelease("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily);
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
} }
} }
@@ -900,19 +956,19 @@ struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) {
fill_soc(soc, "M3 Max", SOC_APPLE_M3_MAX, 3); fill_soc(soc, "M3 Max", SOC_APPLE_M3_MAX, 3);
} }
else { else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family); printBugCheckRelease("Found invalid cpu_family: 0x%.8X", cpu_family);
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
} }
} }
else { else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family); printBugCheckRelease("Found invalid cpu_family: 0x%.8X", cpu_family);
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
} }
return soc; return soc;
} }
#endif #endif
struct system_on_chip* get_soc(void) { struct system_on_chip* get_soc(struct cpuInfo* cpu) {
struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip)); struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip));
soc->raw_name = NULL; soc->raw_name = NULL;
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
@@ -952,6 +1008,10 @@ struct system_on_chip* get_soc(void) {
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) { if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
soc = guess_soc_from_nvmem(soc); soc = guess_soc_from_nvmem(soc);
} }
// If everything else failed, try infering it from the microarchitecture
if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) {
soc = guess_soc_from_uarch(soc, cpu);
}
} }
#elif defined __APPLE__ || __MACH__ #elif defined __APPLE__ || __MACH__
soc = guess_soc_apple(soc); soc = guess_soc_apple(soc);

View File

@@ -5,6 +5,6 @@
#include "../common/soc.h" #include "../common/soc.h"
#include <stdint.h> #include <stdint.h>
struct system_on_chip* get_soc(void); struct system_on_chip* get_soc(struct cpuInfo* cpu);
#endif #endif

View File

@@ -29,6 +29,9 @@ enum {
SOC_HISILICON_3670, SOC_HISILICON_3670,
SOC_HISILICON_3680, SOC_HISILICON_3680,
SOC_HISILICON_3690, SOC_HISILICON_3690,
// Kunpeng //
SOC_KUNPENG_920,
SOC_KUNPENG_930,
// Exynos // // Exynos //
SOC_EXYNOS_3475, SOC_EXYNOS_3475,
SOC_EXYNOS_4210, SOC_EXYNOS_4210,
@@ -329,12 +332,14 @@ enum {
SOC_ALLWINNER_V3S, SOC_ALLWINNER_V3S,
SOC_ALLWINNER_HZP, SOC_ALLWINNER_HZP,
SOC_ALLWINNER_H2PLUS, SOC_ALLWINNER_H2PLUS,
SOC_ALLWINNER_S3,
SOC_ALLWINNER_H3, SOC_ALLWINNER_H3,
SOC_ALLWINNER_H8, SOC_ALLWINNER_H8,
SOC_ALLWINNER_H5, SOC_ALLWINNER_H5,
SOC_ALLWINNER_H6, SOC_ALLWINNER_H6,
SOC_ALLWINNER_H64, SOC_ALLWINNER_H64,
SOC_ALLWINNER_H616, SOC_ALLWINNER_H616,
SOC_ALLWINNER_H618,
SOC_ALLWINNER_R8, SOC_ALLWINNER_R8,
SOC_ALLWINNER_R16, SOC_ALLWINNER_R16,
SOC_ALLWINNER_R40, SOC_ALLWINNER_R40,
@@ -349,10 +354,11 @@ enum {
SOC_ROCKCHIP_3328, SOC_ROCKCHIP_3328,
SOC_ROCKCHIP_3368, SOC_ROCKCHIP_3368,
SOC_ROCKCHIP_3399, SOC_ROCKCHIP_3399,
SOC_ROCKCHIP_3528,
SOC_ROCKCHIP_3562,
SOC_ROCKCHIP_3566, SOC_ROCKCHIP_3566,
SOC_ROCKCHIP_3568, SOC_ROCKCHIP_3568,
SOC_ROCKCHIP_3588, SOC_ROCKCHIP_3588,
SOC_ROCKCHIP_3588S,
// GOOGLE // GOOGLE
SOC_GOOGLE_TENSOR, SOC_GOOGLE_TENSOR,
SOC_GOOGLE_TENSOR_G2, SOC_GOOGLE_TENSOR_G2,
@@ -364,12 +370,13 @@ enum {
inline static VENDOR get_soc_vendor_from_soc(SOC soc) { inline static VENDOR get_soc_vendor_from_soc(SOC soc) {
if(soc >= SOC_BCM_2835 && soc <= SOC_BCM_2712) return SOC_VENDOR_BROADCOM; if(soc >= SOC_BCM_2835 && soc <= SOC_BCM_2712) return SOC_VENDOR_BROADCOM;
else if(soc >= SOC_HISILICON_3620 && soc <= SOC_HISILICON_3690) return SOC_VENDOR_KIRIN; else if(soc >= SOC_HISILICON_3620 && soc <= SOC_HISILICON_3690) return SOC_VENDOR_KIRIN;
else if(soc >= SOC_KUNPENG_920 && soc <= SOC_KUNPENG_930) return SOC_VENDOR_KUNPENG;
else if(soc >= SOC_EXYNOS_3475 && soc <= SOC_EXYNOS_880) return SOC_VENDOR_EXYNOS; else if(soc >= SOC_EXYNOS_3475 && soc <= SOC_EXYNOS_880) return SOC_VENDOR_EXYNOS;
else if(soc >= SOC_MTK_MT6893 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK; else if(soc >= SOC_MTK_MT6893 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK;
else if(soc >= SOC_SNAPD_QSD8650 && soc <= SOC_SNAPD_SM8450) return SOC_VENDOR_SNAPDRAGON; else if(soc >= SOC_SNAPD_QSD8650 && soc <= SOC_SNAPD_SM8450) return SOC_VENDOR_SNAPDRAGON;
else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M3_MAX) return SOC_VENDOR_APPLE; else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M3_MAX) return SOC_VENDOR_APPLE;
else if(soc >= SOC_ALLWINNER_A10 && soc <= SOC_ALLWINNER_R328) return SOC_VENDOR_ALLWINNER; else if(soc >= SOC_ALLWINNER_A10 && soc <= SOC_ALLWINNER_R328) return SOC_VENDOR_ALLWINNER;
else if(soc >= SOC_ROCKCHIP_3288 && soc <= SOC_ROCKCHIP_3588S) return SOC_VENDOR_ROCKCHIP; else if(soc >= SOC_ROCKCHIP_3288 && soc <= SOC_ROCKCHIP_3588) return SOC_VENDOR_ROCKCHIP;
else if(soc >= SOC_GOOGLE_TENSOR && soc <= SOC_GOOGLE_TENSOR_G3) return SOC_VENDOR_GOOGLE; else if(soc >= SOC_GOOGLE_TENSOR && soc <= SOC_GOOGLE_TENSOR_G3) return SOC_VENDOR_GOOGLE;
return SOC_VENDOR_UNKNOWN; return SOC_VENDOR_UNKNOWN;
} }

View File

@@ -10,7 +10,6 @@
// Data not available // Data not available
#define NA -1 #define NA -1
typedef uint32_t MICROARCH;
typedef uint32_t ISA; typedef uint32_t ISA;
struct uarch { struct uarch {
@@ -37,89 +36,6 @@ enum {
ISA_ARMv9_A ISA_ARMv9_A
}; };
enum {
UARCH_UNKNOWN,
// ARM
UARCH_ARM7,
UARCH_ARM9,
UARCH_ARM1136,
UARCH_ARM1156,
UARCH_ARM1176,
UARCH_ARM11MPCORE,
UARCH_CORTEX_A5,
UARCH_CORTEX_A7,
UARCH_CORTEX_A8,
UARCH_CORTEX_A9,
UARCH_CORTEX_A12,
UARCH_CORTEX_A15,
UARCH_CORTEX_A17,
UARCH_CORTEX_A32,
UARCH_CORTEX_A35,
UARCH_CORTEX_A53,
UARCH_CORTEX_A55r0, // ARM Cortex-A55 revision 0 (restricted dual-issue capabilities compared to revision 1+).
UARCH_CORTEX_A55,
UARCH_CORTEX_A57,
UARCH_CORTEX_A65,
UARCH_CORTEX_A72,
UARCH_CORTEX_A73,
UARCH_CORTEX_A75,
UARCH_CORTEX_A76,
UARCH_CORTEX_A77,
UARCH_CORTEX_A78,
UARCH_CORTEX_A510,
UARCH_CORTEX_A710,
UARCH_CORTEX_A715,
UARCH_CORTEX_X1,
UARCH_CORTEX_X2,
UARCH_CORTEX_X3,
UARCH_NEOVERSE_N1,
UARCH_NEOVERSE_E1,
UARCH_NEOVERSE_V1,
UARCH_SCORPION,
UARCH_KRAIT,
UARCH_KYRO,
UARCH_FALKOR,
UARCH_SAPHIRA,
UARCH_DENVER,
UARCH_DENVER2,
UARCH_CARMEL,
// SAMSUNG
UARCH_EXYNOS_M1, // Samsung Exynos M1 (Exynos 8890 big cores)
UARCH_EXYNOS_M2, // Samsung Exynos M2 (Exynos 8895 big cores)
UARCH_EXYNOS_M3, // Samsung Exynos M3 (Exynos 9810 big cores)
UARCH_EXYNOS_M4, // Samsung Exynos M4 (Exynos 9820 big cores)
UARCH_EXYNOS_M5, // Samsung Exynos M5 (Exynos 9830 big cores)
// APPLE
UARCH_SWIFT, // Apple A6 and A6X processors.
UARCH_CYCLONE, // Apple A7 processor.
UARCH_TYPHOON, // Apple A8 and A8X processor
UARCH_TWISTER, // Apple A9 and A9X processor.
UARCH_HURRICANE, // Apple A10 and A10X processor.
UARCH_MONSOON, // Apple A11 processor (big cores).
UARCH_MISTRAL, // Apple A11 processor (little cores).
UARCH_VORTEX, // Apple A12 processor (big cores).
UARCH_TEMPEST, // Apple A12 processor (big cores).
UARCH_LIGHTNING, // Apple A13 processor (big cores).
UARCH_THUNDER, // Apple A13 processor (little cores).
UARCH_ICESTORM, // Apple M1 processor (little cores).
UARCH_FIRESTORM, // Apple M1 processor (big cores).
UARCH_BLIZZARD, // Apple M2 processor (little cores).
UARCH_AVALANCHE, // Apple M2 processor (big cores).
UARCH_SAWTOOTH, // Apple M3 processor (little cores).
UARCH_EVEREST, // Apple M3 processor (big cores).
// CAVIUM
UARCH_THUNDERX, // Cavium ThunderX
UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan).
// MARVELL
UARCH_PJ4,
UARCH_BRAHMA_B15,
UARCH_BRAHMA_B53,
UARCH_XGENE, // Applied Micro X-Gene.
UARCH_TAISHAN_V110, // HiSilicon TaiShan v110 (Huawei Kunpeng 920 series processors).
// PHYTIUM
UARCH_XIAOMI, // Not to be confused with Xiaomi Inc
};
static const ISA isas_uarch[] = { static const ISA isas_uarch[] = {
[UARCH_ARM1136] = ISA_ARMv6, [UARCH_ARM1136] = ISA_ARMv6,
[UARCH_ARM1156] = ISA_ARMv6_T2, [UARCH_ARM1156] = ISA_ARMv6_T2,
@@ -159,6 +75,7 @@ static const ISA isas_uarch[] = {
[UARCH_THUNDERX] = ISA_ARMv8_A, [UARCH_THUNDERX] = ISA_ARMv8_A,
[UARCH_THUNDERX2] = ISA_ARMv8_1_A, [UARCH_THUNDERX2] = ISA_ARMv8_1_A,
[UARCH_TAISHAN_V110] = ISA_ARMv8_2_A, [UARCH_TAISHAN_V110] = ISA_ARMv8_2_A,
[UARCH_TAISHAN_V200] = ISA_ARMv8_2_A, // Not confirmed
[UARCH_DENVER] = ISA_ARMv8_A, [UARCH_DENVER] = ISA_ARMv8_A,
[UARCH_DENVER2] = ISA_ARMv8_A, [UARCH_DENVER2] = ISA_ARMv8_A,
[UARCH_CARMEL] = ISA_ARMv8_A, [UARCH_CARMEL] = ISA_ARMv8_A,
@@ -200,8 +117,7 @@ static char* isas_string[] = {
#define UARCH_START if (false) {} #define UARCH_START if (false) {}
#define CHECK_UARCH(arch, cpu, im_, p_, v_, r_, str, uarch, vendor) \ #define CHECK_UARCH(arch, cpu, im_, p_, v_, r_, str, uarch, vendor) \
else if (im_ == im && p_ == p && (v_ == NA || v_ == v) && (r_ == NA || r_ == r)) fill_uarch(arch, cpu, str, uarch, vendor); else if (im_ == im && p_ == p && (v_ == NA || v_ == v) && (r_ == NA || r_ == r)) fill_uarch(arch, cpu, str, uarch, vendor);
#define UARCH_END else { printErr("Unknown microarchitecture detected: IM=0x%X P=0x%X V=0x%X R=0x%X", im, p, v, r); \ #define UARCH_END else { printBugCheckRelease("Unknown microarchitecture detected: IM=0x%X P=0x%X V=0x%X R=0x%X", im, p, v, r); \
fprintf(stderr, "Please see https://github.com/Dr-Noob/cpufetch#61-unknown-microarchitecture-error to know how to report this error\n"); \
fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); } fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); }
void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, VENDOR vendor) { void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, VENDOR vendor) {
@@ -285,8 +201,9 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
CHECK_UARCH(arch, cpu, 'C', 0x0A3, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM) CHECK_UARCH(arch, cpu, 'C', 0x0A3, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
CHECK_UARCH(arch, cpu, 'C', 0x0AF, NA, NA, "ThunderX2 99XX", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM) CHECK_UARCH(arch, cpu, 'C', 0x0AF, NA, NA, "ThunderX2 99XX", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM)
CHECK_UARCH(arch, cpu, 'H', 0xD01, NA, NA, "TaiShan v110", UARCH_TAISHAN_V110, CPU_VENDOR_HUAWUEI) // Kunpeng 920 series CHECK_UARCH(arch, cpu, 'H', 0xD01, NA, NA, "TaiShan v110", UARCH_TAISHAN_V110, CPU_VENDOR_HUAWEI) // Kunpeng 920 series
CHECK_UARCH(arch, cpu, 'H', 0xD40, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // Kirin 980 Big/Medium cores -> Cortex-A76 CHECK_UARCH(arch, cpu, 'H', 0xD02, NA, NA, "TaiShan v200", UARCH_TAISHAN_V200, CPU_VENDOR_HUAWEI) // Kunpeng 930 series (found in openeuler: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/XQCV7NX2UKRIUWUFKRF4PO3QENCOUFR3)
CHECK_UARCH(arch, cpu, 'H', 0xD40, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // Kirin 980 Big/Medium cores -> Cortex-A76
CHECK_UARCH(arch, cpu, 'N', 0x000, NA, NA, "Denver", UARCH_DENVER, CPU_VENDOR_NVIDIA) CHECK_UARCH(arch, cpu, 'N', 0x000, NA, NA, "Denver", UARCH_DENVER, CPU_VENDOR_NVIDIA)
CHECK_UARCH(arch, cpu, 'N', 0x003, NA, NA, "Denver2", UARCH_DENVER2, CPU_VENDOR_NVIDIA) CHECK_UARCH(arch, cpu, 'N', 0x003, NA, NA, "Denver2", UARCH_DENVER2, CPU_VENDOR_NVIDIA)
@@ -438,6 +355,10 @@ char* get_str_uarch(struct cpuInfo* cpu) {
return cpu->arch->uarch_str; return cpu->arch->uarch_str;
} }
MICROARCH get_uarch(struct uarch* arch) {
return arch->uarch;
}
void free_uarch_struct(struct uarch* arch) { void free_uarch_struct(struct uarch* arch) {
free(arch->uarch_str); free(arch->uarch_str);
free(arch); free(arch);

View File

@@ -5,11 +5,98 @@
#include "midr.h" #include "midr.h"
enum {
UARCH_UNKNOWN,
// ARM
UARCH_ARM7,
UARCH_ARM9,
UARCH_ARM1136,
UARCH_ARM1156,
UARCH_ARM1176,
UARCH_ARM11MPCORE,
UARCH_CORTEX_A5,
UARCH_CORTEX_A7,
UARCH_CORTEX_A8,
UARCH_CORTEX_A9,
UARCH_CORTEX_A12,
UARCH_CORTEX_A15,
UARCH_CORTEX_A17,
UARCH_CORTEX_A32,
UARCH_CORTEX_A35,
UARCH_CORTEX_A53,
UARCH_CORTEX_A55r0, // ARM Cortex-A55 revision 0 (restricted dual-issue capabilities compared to revision 1+).
UARCH_CORTEX_A55,
UARCH_CORTEX_A57,
UARCH_CORTEX_A65,
UARCH_CORTEX_A72,
UARCH_CORTEX_A73,
UARCH_CORTEX_A75,
UARCH_CORTEX_A76,
UARCH_CORTEX_A77,
UARCH_CORTEX_A78,
UARCH_CORTEX_A510,
UARCH_CORTEX_A710,
UARCH_CORTEX_A715,
UARCH_CORTEX_X1,
UARCH_CORTEX_X2,
UARCH_CORTEX_X3,
UARCH_NEOVERSE_N1,
UARCH_NEOVERSE_E1,
UARCH_NEOVERSE_V1,
UARCH_SCORPION,
UARCH_KRAIT,
UARCH_KYRO,
UARCH_FALKOR,
UARCH_SAPHIRA,
UARCH_DENVER,
UARCH_DENVER2,
UARCH_CARMEL,
// SAMSUNG
UARCH_EXYNOS_M1, // Samsung Exynos M1 (Exynos 8890 big cores)
UARCH_EXYNOS_M2, // Samsung Exynos M2 (Exynos 8895 big cores)
UARCH_EXYNOS_M3, // Samsung Exynos M3 (Exynos 9810 big cores)
UARCH_EXYNOS_M4, // Samsung Exynos M4 (Exynos 9820 big cores)
UARCH_EXYNOS_M5, // Samsung Exynos M5 (Exynos 9830 big cores)
// APPLE
UARCH_SWIFT, // Apple A6 and A6X processors.
UARCH_CYCLONE, // Apple A7 processor.
UARCH_TYPHOON, // Apple A8 and A8X processor
UARCH_TWISTER, // Apple A9 and A9X processor.
UARCH_HURRICANE, // Apple A10 and A10X processor.
UARCH_MONSOON, // Apple A11 processor (big cores).
UARCH_MISTRAL, // Apple A11 processor (little cores).
UARCH_VORTEX, // Apple A12 processor (big cores).
UARCH_TEMPEST, // Apple A12 processor (big cores).
UARCH_LIGHTNING, // Apple A13 processor (big cores).
UARCH_THUNDER, // Apple A13 processor (little cores).
UARCH_ICESTORM, // Apple M1 processor (little cores).
UARCH_FIRESTORM, // Apple M1 processor (big cores).
UARCH_BLIZZARD, // Apple M2 processor (little cores).
UARCH_AVALANCHE, // Apple M2 processor (big cores).
UARCH_SAWTOOTH, // Apple M3 processor (little cores).
UARCH_EVEREST, // Apple M3 processor (big cores).
// CAVIUM
UARCH_THUNDERX, // Cavium ThunderX
UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan).
// MARVELL
UARCH_PJ4,
UARCH_BRAHMA_B15,
UARCH_BRAHMA_B53,
UARCH_XGENE, // Applied Micro X-Gene.
UARCH_TAISHAN_V110, // HiSilicon TaiShan v110
UARCH_TAISHAN_V200, // HiSilicon TaiShan v200
// PHYTIUM
UARCH_XIAOMI, // Not to be confused with Xiaomi Inc
};
typedef uint32_t MICROARCH;
struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu); struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu);
int get_number_of_vpus(struct cpuInfo* cpu); int get_number_of_vpus(struct cpuInfo* cpu);
int get_vpus_width(struct cpuInfo* cpu); int get_vpus_width(struct cpuInfo* cpu);
bool has_fma_support(struct cpuInfo* cpu); bool has_fma_support(struct cpuInfo* cpu);
char* get_str_uarch(struct cpuInfo* cpu); char* get_str_uarch(struct cpuInfo* cpu);
void free_uarch_struct(struct uarch* arch); void free_uarch_struct(struct uarch* arch);
MICROARCH get_uarch(struct uarch* arch);
#endif #endif

View File

@@ -145,6 +145,25 @@ $C2 Exynos \
$C2 \ $C2 \
$C2 " $C2 "
#define ASCII_KUNPENG \
"$C2 . \
$C2 .. \
$C2 .## \
$C1 .$CR $C2.###. \
$C1 ..$CR $C2#####. \
$C1 .#.$CR $C2.#######. \
$C1 .####.$CR $C2.#######. \
$C1 ..######*$CR $C2.#######. . \
$C1 .#########*$CR $C2.#######* . \
$C1 ######*$CR $C2.#######. .#. \
$C1*#######*$CR $C2.#######. *##. \
$C1 ##*$CR $C2.#######. ####### \
$C2 ###.$CR $C1#####$C2 *### \
$C1 *########## \
$C1 *######## \
$C1 #####. \
$C1 *###. "
#define ASCII_KIRIN \ #define ASCII_KIRIN \
"$C1 ####### \ "$C1 ####### \
$C1 ##### #################### \ $C1 ##### #################### \
@@ -485,6 +504,7 @@ asciiL logo_snapd = { ASCII_SNAPD, 39, 16, false, {C_FG_RED, C_FG_WH
asciiL logo_mtk = { ASCII_MTK, 59, 5, false, {C_FG_BLUE, C_FG_YELLOW}, {C_FG_BLUE, C_FG_YELLOW} }; asciiL logo_mtk = { ASCII_MTK, 59, 5, false, {C_FG_BLUE, C_FG_YELLOW}, {C_FG_BLUE, C_FG_YELLOW} };
asciiL logo_exynos = { ASCII_EXYNOS, 22, 13, true, {C_BG_BLUE, C_FG_WHITE}, {C_FG_BLUE, C_FG_WHITE} }; asciiL logo_exynos = { ASCII_EXYNOS, 22, 13, true, {C_BG_BLUE, C_FG_WHITE}, {C_FG_BLUE, C_FG_WHITE} };
asciiL logo_kirin = { ASCII_KIRIN, 53, 12, false, {C_FG_RED}, {C_FG_WHITE, C_FG_RED} }; asciiL logo_kirin = { ASCII_KIRIN, 53, 12, false, {C_FG_RED}, {C_FG_WHITE, C_FG_RED} };
asciiL logo_kunpeng = { ASCII_KUNPENG, 48, 17, false, {C_FG_RED, C_FG_WHITE}, {C_FG_WHITE, C_FG_RED} };
asciiL logo_broadcom = { ASCII_BROADCOM, 44, 19, false, {C_FG_WHITE, C_FG_RED}, {C_FG_WHITE, C_FG_RED} }; asciiL logo_broadcom = { ASCII_BROADCOM, 44, 19, false, {C_FG_WHITE, C_FG_RED}, {C_FG_WHITE, C_FG_RED} };
asciiL logo_arm = { ASCII_ARM, 42, 5, false, {C_FG_CYAN}, {C_FG_WHITE, C_FG_CYAN} }; asciiL logo_arm = { ASCII_ARM, 42, 5, false, {C_FG_CYAN}, {C_FG_WHITE, C_FG_CYAN} };
asciiL logo_ibm = { ASCII_IBM, 42, 9, false, {C_FG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} }; asciiL logo_ibm = { ASCII_IBM, 42, 9, false, {C_FG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };

View File

@@ -194,7 +194,7 @@ void init_topology_struct(struct topology* topo, struct cache* cach) {
topo->sockets = 0; topo->sockets = 0;
#ifdef ARCH_X86 #ifdef ARCH_X86
topo->smt_available = 0; topo->smt_available = 0;
topo->apic = emalloc(sizeof(struct apic)); topo->apic = ecalloc(1, sizeof(struct apic));
#endif #endif
#endif #endif
} }

View File

@@ -16,7 +16,7 @@ enum {
CPU_VENDOR_NVIDIA, CPU_VENDOR_NVIDIA,
CPU_VENDOR_APM, CPU_VENDOR_APM,
CPU_VENDOR_QUALCOMM, CPU_VENDOR_QUALCOMM,
CPU_VENDOR_HUAWUEI, CPU_VENDOR_HUAWEI,
CPU_VENDOR_SAMSUNG, CPU_VENDOR_SAMSUNG,
CPU_VENDOR_MARVELL, CPU_VENDOR_MARVELL,
CPU_VENDOR_PHYTIUM, CPU_VENDOR_PHYTIUM,
@@ -38,6 +38,7 @@ enum {
HV_VENDOR_PARALLELS, HV_VENDOR_PARALLELS,
HV_VENDOR_PHYP, HV_VENDOR_PHYP,
HV_VENDOR_BHYVE, HV_VENDOR_BHYVE,
HV_VENDOR_APPLEVZ,
HV_VENDOR_INVALID HV_VENDOR_INVALID
}; };

154
src/common/freq.c Normal file
View File

@@ -0,0 +1,154 @@
#ifdef __linux__
#define _GNU_SOURCE
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include "global.h"
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags) {
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
#define INSERT_ASM_ONCE __asm volatile("nop");
#define INSERT_ASM_10_TIMES \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
INSERT_ASM_ONCE \
#define INSERT_ASM_100_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES \
INSERT_ASM_10_TIMES
#define INSERT_ASM_1000_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
INSERT_ASM_100_TIMES \
void nop_function(uint64_t iters) {
for (uint64_t i = 0; i < iters; i++) {
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
INSERT_ASM_1000_TIMES
}
}
// Differences between x86 measure_frequency this measure_max_frequency:
// - measure_frequency employs all cores simultaneously wherease
// measure_max_frequency only employs 1.
// - measure_frequency runs the computation and checks /proc/cpuinfo whereas
// measure_max_frequency does not rely on /proc/cpuinfo and simply
// counts cpu cycles to measure frequency.
// - measure_frequency uses actual computation while measuring the frequency
// whereas measure_max_frequency uses nop instructions. This makes the former
// x86 dependant whereas the latter is architecture independant.
int64_t measure_max_frequency(uint32_t core) {
if (!bind_to_cpu(core)) {
printErr("Failed binding the process to CPU %d", core);
return -1;
}
clockid_t clock = CLOCK_PROCESS_CPUTIME_ID;
struct perf_event_attr pe;
uint64_t instructions;
int fd;
int pid = 0;
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = PERF_TYPE_HARDWARE;
pe.size = sizeof(struct perf_event_attr);
pe.config = PERF_COUNT_HW_CPU_CYCLES;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, pid, core, -1, 0);
if (fd == -1) {
perror("perf_event_open");
if (errno == EPERM || errno == EACCES) {
printf("You may not have permission to collect stats.\n");
printf("Consider tweaking /proc/sys/kernel/perf_event_paranoid or running as root.\n");
}
return -1;
}
const char* frequency_banner = "cpufetch is measuring the max frequency...";
printf("%s", frequency_banner);
fflush(stdout);
uint64_t iters = 10000000;
struct timespec start, end;
if (clock_gettime(clock, &start) == -1) {
perror("clock_gettime");
return -1;
}
if(ioctl(fd, PERF_EVENT_IOC_RESET, 0) == -1) {
perror("ioctl");
return -1;
}
if(ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1) {
perror("ioctl");
return -1;
}
nop_function(iters);
read(fd, &instructions, sizeof(uint64_t));
if(ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) == -1) {
perror("ioctl");
return -1;
}
if (clock_gettime(clock, &end) == -1) {
perror("clock_gettime");
return -1;
}
uint64_t nsecs = (end.tv_sec*1e9 + end.tv_nsec) - (start.tv_sec*1e9 + start.tv_nsec);
uint64_t usecs = nsecs/1000;
double frequency = instructions/((double)usecs);
printf("\r%*c\r", (int) strlen(frequency_banner), ' ');
// Discard last digit in the frequency, which should help providing
// more reliable and predictable values.
return (((int) frequency + 5)/10) * 10;
}
#endif // #ifdef __linux__

6
src/common/freq.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef __COMMON_FREQ__
#define __COMMON_FREQ__
int64_t measure_max_frequency(uint32_t core);
#endif

View File

@@ -1,3 +1,14 @@
#ifdef _WIN32
#define NOMINMAX
#include <windows.h>
#elif defined __linux__
#define _GNU_SOURCE
#include <sched.h>
#elif defined __FreeBSD__
#include <sys/param.h>
#include <sys/cpuset.h>
#endif
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -21,7 +32,7 @@
#endif #endif
#ifdef ARCH_X86 #ifdef ARCH_X86
static const char* ARCH_STR = "x86_64 build"; static const char* ARCH_STR = "x86 / x86_64 build";
#include "../x86/cpuid.h" #include "../x86/cpuid.h"
#elif ARCH_PPC #elif ARCH_PPC
static const char* ARCH_STR = "PowerPC build"; static const char* ARCH_STR = "PowerPC build";
@@ -51,7 +62,7 @@
#endif #endif
#ifndef GIT_FULL_VERSION #ifndef GIT_FULL_VERSION
static const char* VERSION = "1.04"; static const char* VERSION = "1.05";
#endif #endif
enum { enum {
@@ -61,6 +72,14 @@ enum {
int LOG_LEVEL; int LOG_LEVEL;
void printBugMessage(FILE *restrict stream) {
#if defined(ARCH_X86) || defined(ARCH_PPC)
fprintf(stream, "Please, create a new issue with this error message, the output of 'cpufetch' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n");
#elif ARCH_ARM
fprintf(stream, "Please, create a new issue with this error message, your smartphone/computer model, the output of 'cpufetch --verbose' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n");
#endif
}
void printWarn(const char *fmt, ...) { void printWarn(const char *fmt, ...) {
if(LOG_LEVEL == LOG_LEVEL_VERBOSE) { if(LOG_LEVEL == LOG_LEVEL_VERBOSE) {
int buffer_size = 4096; int buffer_size = 4096;
@@ -95,10 +114,40 @@ void printBug(const char *fmt, ...) {
fprintf(stderr,RED "[ERROR]: "RESET "%s\n",buffer); fprintf(stderr,RED "[ERROR]: "RESET "%s\n",buffer);
fprintf(stderr,"[VERSION]: "); fprintf(stderr,"[VERSION]: ");
print_version(stderr); print_version(stderr);
#if defined(ARCH_X86) || defined(ARCH_PPC) printBugMessage(stderr);
fprintf(stderr, "Please, create a new issue with this error message, the output of 'cpufetch' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n"); }
#elif ARCH_ARM
fprintf(stderr, "Please, create a new issue with this error message, your smartphone/computer model, the output of 'cpufetch --verbose' and 'cpufetch --debug' on https://github.com/Dr-Noob/cpufetch/issues\n"); bool isReleaseVersion(char *git_full_version) {
return strstr(git_full_version, "-") == NULL;
}
/// The unknown uarch errors are by far the most common error a user will encounter.
/// Rather than using the generic printBug function, which asks the user to report
/// the problem on the issues webpage, this function will check if the program is
/// the release version. In such case, support for this feature is most likely already
/// in the last version, so just tell the user to compile that one and not report this
/// in github.
void printBugCheckRelease(const char *fmt, ...) {
int buffer_size = 4096;
char buffer[buffer_size];
va_list args;
va_start(args, fmt);
vsnprintf(buffer,buffer_size, fmt, args);
va_end(args);
fprintf(stderr, RED "[ERROR]: "RESET "%s\n", buffer);
fprintf(stderr, "[VERSION]: ");
print_version(stderr);
#ifdef GIT_FULL_VERSION
if (isReleaseVersion(GIT_FULL_VERSION)) {
fprintf(stderr, RED "[ERROR]: "RESET "You are using an outdated version of cpufetch. Please compile cpufetch from source (see https://github.com/Dr-Noob/cpufetch?tab=readme-ov-file#22-building-from-source)");
}
else {
printBugMessage(stderr);
}
#else
printBugMessage(stderr);
#endif #endif
} }
@@ -161,6 +210,34 @@ void* erealloc(void *ptr, size_t size) {
return newptr; return newptr;
} }
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id) {
#ifdef _WIN32
HANDLE process = GetCurrentProcess();
DWORD_PTR processAffinityMask = 1 << cpu_id;
return SetProcessAffinityMask(process, processAffinityMask);
#elif defined __linux__
cpu_set_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if (sched_setaffinity (0, sizeof(currentCPU), &currentCPU) == -1) {
printWarn("sched_setaffinity: %s", strerror(errno));
return false;
}
return true;
#elif defined __FreeBSD__
cpuset_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), &currentCPU) == -1) {
printWarn("cpuset_setaffinity: %s", strerror(errno));
return false;
}
return true;
#endif
}
#endif
void print_version(FILE *restrict stream) { void print_version(FILE *restrict stream) {
#ifdef GIT_FULL_VERSION #ifdef GIT_FULL_VERSION
fprintf(stream, "cpufetch %s (%s %s)\n", GIT_FULL_VERSION, OS_STR, ARCH_STR); fprintf(stream, "cpufetch %s (%s %s)\n", GIT_FULL_VERSION, OS_STR, ARCH_STR);

View File

@@ -12,12 +12,16 @@ void set_log_level(bool verbose);
void printWarn(const char *fmt, ...); void printWarn(const char *fmt, ...);
void printErr(const char *fmt, ...); void printErr(const char *fmt, ...);
void printBug(const char *fmt, ...); void printBug(const char *fmt, ...);
void printBugCheckRelease(const char *fmt, ...);
int min(int a, int b); int min(int a, int b);
int max(int a, int b); int max(int a, int b);
char *strremove(char *str, const char *sub); char *strremove(char *str, const char *sub);
void* emalloc(size_t size); void* emalloc(size_t size);
void* ecalloc(size_t nmemb, size_t size); void* ecalloc(size_t nmemb, size_t size);
void* erealloc(void *ptr, size_t size); void* erealloc(void *ptr, size_t size);
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id);
#endif
void print_version(FILE *restrict stream); void print_version(FILE *restrict stream);
#endif #endif

View File

@@ -61,6 +61,7 @@ enum {
ATTRIBUTE_NCORES, ATTRIBUTE_NCORES,
ATTRIBUTE_NCORES_DUAL, ATTRIBUTE_NCORES_DUAL,
#ifdef ARCH_X86 #ifdef ARCH_X86
ATTRIBUTE_SSE,
ATTRIBUTE_AVX, ATTRIBUTE_AVX,
ATTRIBUTE_FMA, ATTRIBUTE_FMA,
#elif ARCH_PPC #elif ARCH_PPC
@@ -96,6 +97,7 @@ static const char* ATTRIBUTE_FIELDS [] = {
"Cores:", "Cores:",
"Cores (Total):", "Cores (Total):",
#ifdef ARCH_X86 #ifdef ARCH_X86
"SSE:",
"AVX:", "AVX:",
"FMA:", "FMA:",
#elif ARCH_PPC #elif ARCH_PPC
@@ -131,6 +133,7 @@ static const char* ATTRIBUTE_FIELDS_SHORT [] = {
"Cores:", "Cores:",
"Cores (Total):", "Cores (Total):",
#ifdef ARCH_X86 #ifdef ARCH_X86
"SSE:",
"AVX:", "AVX:",
"FMA:", "FMA:",
#elif ARCH_PPC #elif ARCH_PPC
@@ -336,6 +339,13 @@ struct ascii_logo* choose_ascii_art_aux(struct ascii_logo* logo_long, struct asc
} }
} }
// https://no-color.org/
bool is_color_enabled(void) {
const char *var_name = "NO_COLOR";
char *no_color = getenv(var_name);
return no_color == NULL || no_color[0] == '\0';
}
void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* term, int lf) { void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* term, int lf) {
// 1. Choose logo // 1. Choose logo
#ifdef ARCH_X86 #ifdef ARCH_X86
@@ -364,6 +374,8 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
art->art = &logo_exynos; art->art = &logo_exynos;
else if(art->vendor == SOC_VENDOR_KIRIN) else if(art->vendor == SOC_VENDOR_KIRIN)
art->art = &logo_kirin; art->art = &logo_kirin;
else if(art->vendor == SOC_VENDOR_KUNPENG)
art->art = &logo_kunpeng;
else if(art->vendor == SOC_VENDOR_BROADCOM) else if(art->vendor == SOC_VENDOR_BROADCOM)
art->art = &logo_broadcom; art->art = &logo_broadcom;
else if(art->vendor == SOC_VENDOR_APPLE) else if(art->vendor == SOC_VENDOR_APPLE)
@@ -392,6 +404,9 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
// 2. Choose colors // 2. Choose colors
struct ascii_logo* logo = art->art; struct ascii_logo* logo = art->art;
bool color = is_color_enabled();
if (!color)
art->style = STYLE_LEGACY;
switch(art->style) { switch(art->style) {
case STYLE_LEGACY: case STYLE_LEGACY:
@@ -577,6 +592,7 @@ bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
for(int i = 0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) { for(int i = 0; i < cpu->num_cpus; ptr = ptr->next_cpu, i++) {
char* max_frequency = get_str_freq(ptr->freq); char* max_frequency = get_str_freq(ptr->freq);
char* avx = get_str_avx(ptr); char* avx = get_str_avx(ptr);
char* sse = get_str_sse(ptr);
char* fma = get_str_fma(ptr); char* fma = get_str_fma(ptr);
char* cpu_num = emalloc(sizeof(char) * 9); char* cpu_num = emalloc(sizeof(char) * 9);
@@ -611,8 +627,17 @@ bool print_cpufetch_x86(struct cpuInfo* cpu, STYLE s, struct color** cs, struct
setAttribute(art, ATTRIBUTE_NCORES, n_cores); setAttribute(art, ATTRIBUTE_NCORES, n_cores);
} }
} }
setAttribute(art, ATTRIBUTE_AVX, avx);
setAttribute(art, ATTRIBUTE_FMA, fma); // Show the most modern vector instructions.
// If AVX is supported show it, otherwise show SSE
if (strcmp(avx, "No") == 0) {
setAttribute(art, ATTRIBUTE_SSE, sse);
}
else {
setAttribute(art, ATTRIBUTE_AVX, avx);
setAttribute(art, ATTRIBUTE_FMA, fma);
}
if(l1i != NULL) setAttribute(art, ATTRIBUTE_L1i, l1i); if(l1i != NULL) setAttribute(art, ATTRIBUTE_L1i, l1i);
if(l1d != NULL) setAttribute(art, ATTRIBUTE_L1d, l1d); if(l1d != NULL) setAttribute(art, ATTRIBUTE_L1d, l1d);
if(l2 != NULL) setAttribute(art, ATTRIBUTE_L2, l2); if(l2 != NULL) setAttribute(art, ATTRIBUTE_L2, l2);

View File

@@ -15,6 +15,7 @@ static char* soc_trademark_string[] = {
[SOC_VENDOR_MEDIATEK] = "MediaTek ", [SOC_VENDOR_MEDIATEK] = "MediaTek ",
[SOC_VENDOR_EXYNOS] = "Exynos ", [SOC_VENDOR_EXYNOS] = "Exynos ",
[SOC_VENDOR_KIRIN] = "Kirin ", [SOC_VENDOR_KIRIN] = "Kirin ",
[SOC_VENDOR_KUNPENG] = "Kunpeng ",
[SOC_VENDOR_BROADCOM] = "Broadcom BCM", [SOC_VENDOR_BROADCOM] = "Broadcom BCM",
[SOC_VENDOR_APPLE] = "Apple ", [SOC_VENDOR_APPLE] = "Apple ",
[SOC_VENDOR_ROCKCHIP] = "Rockchip ", [SOC_VENDOR_ROCKCHIP] = "Rockchip ",

View File

@@ -19,6 +19,7 @@ enum {
SOC_VENDOR_MEDIATEK, SOC_VENDOR_MEDIATEK,
SOC_VENDOR_EXYNOS, SOC_VENDOR_EXYNOS,
SOC_VENDOR_KIRIN, SOC_VENDOR_KIRIN,
SOC_VENDOR_KUNPENG,
SOC_VENDOR_BROADCOM, SOC_VENDOR_BROADCOM,
SOC_VENDOR_APPLE, SOC_VENDOR_APPLE,
SOC_VENDOR_ROCKCHIP, SOC_VENDOR_ROCKCHIP,
@@ -39,7 +40,7 @@ struct system_on_chip {
char* raw_name; char* raw_name;
}; };
struct system_on_chip* get_soc(void); struct system_on_chip* get_soc(struct cpuInfo* cpu);
char* get_soc_name(struct system_on_chip* soc); char* get_soc_name(struct system_on_chip* soc);
VENDOR get_soc_vendor(struct system_on_chip* soc); VENDOR get_soc_vendor(struct system_on_chip* soc);
bool match_soc(struct system_on_chip* soc, char* raw_name, char* expected_name, char* soc_name, SOC soc_model, int32_t process); bool match_soc(struct system_on_chip* soc, char* raw_name, char* expected_name, char* soc_name, SOC soc_model, int32_t process);

View File

@@ -20,6 +20,7 @@ static char *hv_vendors_name[] = {
[HV_VENDOR_PARALLELS] = "Parallels", [HV_VENDOR_PARALLELS] = "Parallels",
[HV_VENDOR_PHYP] = "pHyp", [HV_VENDOR_PHYP] = "pHyp",
[HV_VENDOR_BHYVE] = "bhyve", [HV_VENDOR_BHYVE] = "bhyve",
[HV_VENDOR_APPLEVZ] = "Apple VZ",
[HV_VENDOR_INVALID] = STRING_UNKNOWN [HV_VENDOR_INVALID] = STRING_UNKNOWN
}; };

View File

@@ -280,9 +280,6 @@ char* get_str_process(struct cpuInfo* cpu) {
if(process == UNK) { if(process == UNK) {
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN); snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
} }
else if(process > 100) {
sprintf(str, "%.2fum", (double)process/100);
}
else if(process > 0){ else if(process > 0){
sprintf(str, "%dnm", process); sprintf(str, "%dnm", process);
} }

View File

@@ -163,7 +163,7 @@ struct cpuInfo* get_cpu_info(void) {
cpu->ext = get_extensions_from_str(ext_str); cpu->ext = get_extensions_from_str(ext_str);
if(cpu->ext->str != NULL && cpu->ext->mask == 0) return NULL; if(cpu->ext->str != NULL && cpu->ext->mask == 0) return NULL;
cpu->arch = get_uarch_from_cpuinfo_str(cpuinfo_str, cpu); cpu->arch = get_uarch_from_cpuinfo_str(cpuinfo_str, cpu);
cpu->soc = get_soc(); cpu->soc = get_soc(cpu);
cpu->freq = get_frequency_info(0); cpu->freq = get_frequency_info(0);
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);

View File

@@ -65,7 +65,7 @@ struct system_on_chip* guess_soc_from_devtree(struct system_on_chip* soc) {
return soc; return soc;
} }
struct system_on_chip* get_soc(void) { struct system_on_chip* get_soc(struct cpuInfo* cpu) {
struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip)); struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip));
soc->raw_name = NULL; soc->raw_name = NULL;
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;

View File

@@ -5,6 +5,6 @@
#include "../common/cpu.h" #include "../common/cpu.h"
#include <stdint.h> #include <stdint.h>
struct system_on_chip* get_soc(void); struct system_on_chip* get_soc(struct cpuInfo* cpu);
#endif #endif

View File

@@ -72,34 +72,6 @@ uint32_t get_apic_id(bool x2apic_id) {
} }
} }
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id) {
#ifdef _WIN32
HANDLE process = GetCurrentProcess();
DWORD_PTR processAffinityMask = 1 << cpu_id;
return SetProcessAffinityMask(process, processAffinityMask);
#elif defined __linux__
cpu_set_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if (sched_setaffinity (0, sizeof(currentCPU), &currentCPU) == -1) {
printWarn("sched_setaffinity: %s", strerror(errno));
return false;
}
return true;
#elif defined __FreeBSD__
cpuset_t currentCPU;
CPU_ZERO(&currentCPU);
CPU_SET(cpu_id, &currentCPU);
if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset_t), &currentCPU) == -1) {
printWarn("cpuset_setaffinity: %s", strerror(errno));
return false;
}
return true;
#endif
}
#endif
#ifdef __linux__ #ifdef __linux__
int get_total_cores_module(int total_cores, int module) { int get_total_cores_module(int total_cores, int module) {
int total_modules = 2; int total_modules = 2;
@@ -397,6 +369,11 @@ bool fill_apic_ids(uint32_t* apic_ids, int first_core, int n, bool x2apic_id) {
} }
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) { bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo) {
if (topo->cach == NULL) {
printWarn("get_topology_from_apic: cach is NULL");
return false;
}
uint32_t apic_id; uint32_t apic_id;
uint32_t* apic_ids = emalloc(sizeof(uint32_t) * topo->total_cores_module); uint32_t* apic_ids = emalloc(sizeof(uint32_t) * topo->total_cores_module);
uint32_t* apic_pkg = emalloc(sizeof(uint32_t) * topo->total_cores_module); uint32_t* apic_pkg = emalloc(sizeof(uint32_t) * topo->total_cores_module);

View File

@@ -17,10 +17,6 @@ struct apic {
bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo); bool get_topology_from_apic(struct cpuInfo* cpu, struct topology* topo);
uint32_t is_smt_enabled_amd(struct topology* topo); uint32_t is_smt_enabled_amd(struct topology* topo);
#ifndef __APPLE__
bool bind_to_cpu(int cpu_id);
#endif
#ifdef __linux__ #ifdef __linux__
int get_total_cores_module(int total_cores, int module); int get_total_cores_module(int total_cores, int module);
#endif #endif

View File

@@ -6,6 +6,10 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#ifdef __linux__
#include "../common/freq.h"
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -30,8 +34,9 @@ static const char *hv_vendors_string[] = {
[HV_VENDOR_VMWARE] = "VMwareVMware", [HV_VENDOR_VMWARE] = "VMwareVMware",
[HV_VENDOR_XEN] = "XenVMMXenVMM", [HV_VENDOR_XEN] = "XenVMMXenVMM",
[HV_VENDOR_PARALLELS] = "lrpepyh vr", [HV_VENDOR_PARALLELS] = "lrpepyh vr",
[HV_VENDOR_PHYP] = NULL,
[HV_VENDOR_BHYVE] = "bhyve bhyve ", [HV_VENDOR_BHYVE] = "bhyve bhyve ",
[HV_VENDOR_PHYP] = NULL [HV_VENDOR_APPLEVZ] = "Apple VZ"
}; };
static char *hv_vendors_name[] = { static char *hv_vendors_name[] = {
@@ -43,6 +48,7 @@ static char *hv_vendors_name[] = {
[HV_VENDOR_PARALLELS] = "Parallels", [HV_VENDOR_PARALLELS] = "Parallels",
[HV_VENDOR_PHYP] = "pHyp", [HV_VENDOR_PHYP] = "pHyp",
[HV_VENDOR_BHYVE] = "bhyve", [HV_VENDOR_BHYVE] = "bhyve",
[HV_VENDOR_APPLEVZ] = "Apple VZ",
[HV_VENDOR_INVALID] = STRING_UNKNOWN [HV_VENDOR_INVALID] = STRING_UNKNOWN
}; };
@@ -214,7 +220,7 @@ int64_t get_peak_performance(struct cpuInfo* cpu, bool accurate_pp) {
#endif #endif
//First, check we have consistent data //First, check we have consistent data
if(freq == UNKNOWN_DATA || topo->logical_cores == UNKNOWN_DATA) { if(freq == UNKNOWN_DATA || topo == NULL || topo->logical_cores == UNKNOWN_DATA) {
return -1; return -1;
} }
@@ -284,7 +290,7 @@ struct hypervisor* get_hp_info(bool hv_present) {
if(!found) { if(!found) {
hv->hv_vendor = HV_VENDOR_INVALID; hv->hv_vendor = HV_VENDOR_INVALID;
printBug("Unknown hypervisor vendor: %s", name); printBug("Unknown hypervisor vendor: '%s'", name);
} }
} }
@@ -447,7 +453,7 @@ struct cpuInfo* get_cpu_info(void) {
cpu->cach = NULL; cpu->cach = NULL;
cpu->feat = NULL; cpu->feat = NULL;
uint32_t modules = 1; cpu->num_cpus = 1;
uint32_t eax = 0; uint32_t eax = 0;
uint32_t ebx = 0; uint32_t ebx = 0;
uint32_t ecx = 0; uint32_t ecx = 0;
@@ -484,9 +490,8 @@ struct cpuInfo* get_cpu_info(void) {
cpu->cpu_name = get_str_cpu_name_internal(); cpu->cpu_name = get_str_cpu_name_internal();
} }
else { else {
cpu->cpu_name = emalloc(sizeof(char) * (strlen(STRING_UNKNOWN) + 1)); cpu->cpu_name = NULL;
strcpy(cpu->cpu_name, STRING_UNKNOWN); printWarn("Can't read CPU name from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", 0x80000004, cpu->maxExtendedLevels);
printWarn("Can't read cpu name from cpuid (needed extended level is 0x%.8X, max is 0x%.8X)", 0x80000004, cpu->maxExtendedLevels);
} }
cpu->topology_extensions = false; cpu->topology_extensions = false;
@@ -504,12 +509,12 @@ struct cpuInfo* get_cpu_info(void) {
cpu->hybrid_flag = (edx >> 15) & 0x1; cpu->hybrid_flag = (edx >> 15) & 0x1;
} }
if(cpu->hybrid_flag) modules = 2; if(cpu->hybrid_flag) cpu->num_cpus = 2;
struct cpuInfo* ptr = cpu; struct cpuInfo* ptr = cpu;
for(uint32_t i=0; i < modules; i++) { for(uint32_t i=0; i < cpu->num_cpus; i++) {
int32_t first_core; int32_t first_core;
set_cpu_module(i, modules, &first_core); set_cpu_module(i, cpu->num_cpus, &first_core);
if(i > 0) { if(i > 0) {
ptr->next_cpu = emalloc(sizeof(struct cpuInfo)); ptr->next_cpu = emalloc(sizeof(struct cpuInfo));
@@ -536,14 +541,15 @@ struct cpuInfo* get_cpu_info(void) {
ptr->first_core_id = first_core; ptr->first_core_id = first_core;
ptr->feat = get_features_info(ptr); ptr->feat = get_features_info(ptr);
// If any field of the struct is NULL,
// return inmideately, as further functions
// require valid fields (cach, topo, etc)
ptr->arch = get_cpu_uarch(ptr); ptr->arch = get_cpu_uarch(ptr);
ptr->freq = get_frequency_info(ptr); ptr->freq = get_frequency_info(ptr);
if (cpu->cpu_name == NULL && ptr == cpu) {
// If we couldnt read CPU name from cpuid, infer it now
cpu->cpu_name = infer_cpu_name_from_uarch(cpu->arch);
}
ptr->cach = get_cache_info(ptr); ptr->cach = get_cache_info(ptr);
if(ptr->cach == NULL) return cpu;
if(cpu->hybrid_flag) { if(cpu->hybrid_flag) {
ptr->topo = get_topology_info(ptr, ptr->cach, i); ptr->topo = get_topology_info(ptr, ptr->cach, i);
@@ -551,16 +557,23 @@ struct cpuInfo* get_cpu_info(void) {
else { else {
ptr->topo = get_topology_info(ptr, ptr->cach, -1); ptr->topo = get_topology_info(ptr, ptr->cach, -1);
} }
if(cpu->topo == NULL) return cpu;
// If topo is NULL, return early, as get_peak_performance
// requries non-NULL topology.
if(ptr->topo == NULL) return cpu;
} }
cpu->num_cpus = modules;
cpu->peak_performance = get_peak_performance(cpu, accurate_pp()); cpu->peak_performance = get_peak_performance(cpu, accurate_pp());
return cpu; return cpu;
} }
bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) { bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) {
if (topo->cach == NULL) {
printWarn("get_cache_topology_amd: cach is NULL");
return false;
}
if(cpu->maxExtendedLevels >= 0x8000001D && cpu->topology_extensions) { if(cpu->maxExtendedLevels >= 0x8000001D && cpu->topology_extensions) {
uint32_t i, eax, ebx, ecx, edx, num_sharing_cache, cache_type, cache_level; uint32_t i, eax, ebx, ecx, edx, num_sharing_cache, cache_type, cache_level;
@@ -636,10 +649,12 @@ bool get_cache_topology_amd(struct cpuInfo* cpu, struct topology* topo) {
#ifdef __linux__ #ifdef __linux__
void get_topology_from_udev(struct topology* topo) { void get_topology_from_udev(struct topology* topo) {
// TODO: To be improved in the future
topo->total_cores = get_ncores_from_cpuinfo(); topo->total_cores = get_ncores_from_cpuinfo();
topo->logical_cores = topo->total_cores; // TODO: To be improved in the future
topo->physical_cores = topo->total_cores; // Conservative setting as we only know the total
// number of cores.
topo->logical_cores = UNKNOWN_DATA;
topo->physical_cores = UNKNOWN_DATA;
topo->smt_available = 1; topo->smt_available = 1;
topo->smt_supported = 1; topo->smt_supported = 1;
topo->sockets = 1; topo->sockets = 1;
@@ -703,8 +718,8 @@ struct topology* get_topology_info(struct cpuInfo* cpu, struct cache* cach, int
} }
else { else {
printWarn("Can't read topology information from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x00000001, cpu->maxLevels); printWarn("Can't read topology information from cpuid (needed level is 0x%.8X, max is 0x%.8X)", 0x00000001, cpu->maxLevels);
topo->physical_cores = 1; topo->physical_cores = UNKNOWN_DATA;
topo->logical_cores = 1; topo->logical_cores = UNKNOWN_DATA;
topo->smt_available = 1; topo->smt_available = 1;
topo->smt_supported = 1; topo->smt_supported = 1;
} }
@@ -954,6 +969,14 @@ struct frequency* get_frequency_info(struct cpuInfo* cpu) {
} }
} }
#ifdef __linux__
if (freq->max == UNKNOWN_DATA) {
printWarn("All previous methods failed, measuring CPU frequency");
// TODO: Support hybrid architectures
freq->max = measure_max_frequency(0);
}
#endif
return freq; return freq;
} }

View File

@@ -143,4 +143,4 @@ int64_t measure_frequency(struct cpuInfo* cpu) {
printf("\r%*c", num_spaces, ' '); printf("\r%*c", num_spaces, ' ');
return freq_struct->freq; return freq_struct->freq;
} }

View File

@@ -9,5 +9,6 @@
#define LOOP_ITERS 100000000 #define LOOP_ITERS 100000000
int64_t measure_frequency(struct cpuInfo* cpu); int64_t measure_frequency(struct cpuInfo* cpu);
void nop_function_x86(uint64_t iters);
#endif #endif

View File

@@ -48,7 +48,9 @@ enum {
UARCH_UNKNOWN, UARCH_UNKNOWN,
// INTEL // // INTEL //
UARCH_P5, UARCH_P5,
UARCH_P6, UARCH_P5_MMX,
UARCH_P6_PENTIUM_II,
UARCH_P6_PENTIUM_III,
UARCH_DOTHAN, UARCH_DOTHAN,
UARCH_YONAH, UARCH_YONAH,
UARCH_MEROM, UARCH_MEROM,
@@ -125,8 +127,7 @@ struct uarch {
#define UARCH_START if (false) {} #define UARCH_START if (false) {}
#define CHECK_UARCH(arch, ef_, f_, em_, m_, s_, str, uarch, process) \ #define CHECK_UARCH(arch, ef_, f_, em_, m_, s_, str, uarch, process) \
else if (ef_ == ef && f_ == f && (em_ == NA || em_ == em) && (m_ == NA || m_ == m) && (s_ == NA || s_ == s)) fill_uarch(arch, str, uarch, process); else if (ef_ == ef && f_ == f && (em_ == NA || em_ == em) && (m_ == NA || m_ == m) && (s_ == NA || s_ == s)) fill_uarch(arch, str, uarch, process);
#define UARCH_END else { printErr("Unknown microarchitecture detected: M=0x%X EM=0x%X F=0x%X EF=0x%X S=0x%X", m, em, f, ef, s); \ #define UARCH_END else { printBugCheckRelease("Unknown microarchitecture detected: M=0x%X EM=0x%X F=0x%X EF=0x%X S=0x%X", m, em, f, ef, s); \
fprintf(stderr, "Please see https://github.com/Dr-Noob/cpufetch#61-unknown-microarchitecture-error to know how to report this error\n"); \
fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK); } fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK); }
void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) { void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
@@ -140,128 +141,128 @@ void fill_uarch(struct uarch* arch, char* str, MICROARCH u, uint32_t process) {
struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) { struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
struct uarch* arch = emalloc(sizeof(struct uarch)); struct uarch* arch = emalloc(sizeof(struct uarch));
// EF: Extended Family // // EF: Extended Family //
// F: Family // // F: Family //
// EM: Extended Model // // EM: Extended Model //
// M: Model // // M: Model //
// S: Stepping // // S: Stepping //
// ----------------------------------------------------------------------------- // // ------------------------------------------------------------------------------- //
// EF F EM M S // // EF F EM M S //
UARCH_START UARCH_START
CHECK_UARCH(arch, 0, 5, 0, 0, NA, "P5", UARCH_P5, 800) CHECK_UARCH(arch, 0, 5, 0, 0, NA, "P5", UARCH_P5, 800)
CHECK_UARCH(arch, 0, 5, 0, 1, NA, "P5", UARCH_P5, 800) CHECK_UARCH(arch, 0, 5, 0, 1, NA, "P5", UARCH_P5, 800)
CHECK_UARCH(arch, 0, 5, 0, 2, NA, "P5", UARCH_P5, UNK) CHECK_UARCH(arch, 0, 5, 0, 2, NA, "P5", UARCH_P5, UNK)
CHECK_UARCH(arch, 0, 5, 0, 3, NA, "P5", UARCH_P5, 600) CHECK_UARCH(arch, 0, 5, 0, 3, NA, "P5", UARCH_P5, 600)
CHECK_UARCH(arch, 0, 5, 0, 4, NA, "P5 MMX", UARCH_P5, UNK) CHECK_UARCH(arch, 0, 5, 0, 4, NA, "P5 (MMX)", UARCH_P5_MMX, UNK)
CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 MMX", UARCH_P5, UNK) CHECK_UARCH(arch, 0, 5, 0, 7, NA, "P5 (MMX)", UARCH_P5_MMX, UNK)
CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 MMX", UARCH_P5, 250) CHECK_UARCH(arch, 0, 5, 0, 8, NA, "P5 (MMX)", UARCH_P5_MMX, 250)
CHECK_UARCH(arch, 0, 5, 0, 9, 0, "Lakemont", UARCH_LAKEMONT, 32) CHECK_UARCH(arch, 0, 5, 0, 9, 0, "Lakemont", UARCH_LAKEMONT, 32)
CHECK_UARCH(arch, 0, 5, 0, 9, NA, "P5 MMX", UARCH_P5, UNK) CHECK_UARCH(arch, 0, 5, 0, 9, NA, "P5 (MMX)", UARCH_P5_MMX, UNK)
CHECK_UARCH(arch, 0, 5, 0, 10, 0, "Lakemont", UARCH_LAKEMONT, 32) CHECK_UARCH(arch, 0, 5, 0, 10, 0, "Lakemont", UARCH_LAKEMONT, 32)
CHECK_UARCH(arch, 0, 6, 0, 0, NA, "P6 Pentium II", UARCH_P6, UNK) CHECK_UARCH(arch, 0, 6, 0, 0, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 Pentium II", UARCH_P6, UNK) // process depends on core CHECK_UARCH(arch, 0, 6, 0, 1, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK) // process depends on core
CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 Pentium II", UARCH_P6, UNK) CHECK_UARCH(arch, 0, 6, 0, 2, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 3, NA, "P6 Pentium II", UARCH_P6, 350) CHECK_UARCH(arch, 0, 6, 0, 3, NA, "P6 (Klamath)", UARCH_P6_PENTIUM_II, 350) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 4, NA, "P6 Pentium II", UARCH_P6, UNK) CHECK_UARCH(arch, 0, 6, 0, 4, NA, "P6 (Pentium II)", UARCH_P6_PENTIUM_II, UNK)
CHECK_UARCH(arch, 0, 6, 0, 5, NA, "P6 Pentium II", UARCH_P6, 250) CHECK_UARCH(arch, 0, 6, 0, 5, NA, "P6 (Deschutes)", UARCH_P6_PENTIUM_II, 250) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 6, NA, "P6 Pentium II", UARCH_P6, UNK) CHECK_UARCH(arch, 0, 6, 0, 6, NA, "P6 (Dixon)", UARCH_P6_PENTIUM_II, UNK) // http://instlatx64.atw.hu.
CHECK_UARCH(arch, 0, 6, 0, 7, NA, "P6 Pentium III", UARCH_P6, 250) CHECK_UARCH(arch, 0, 6, 0, 7, NA, "P6 (Katmai)", UARCH_P6_PENTIUM_III, 250) // Core names from: https://en.wikichip.org/wiki/intel/cpuid. NOTE: Xeon core names are different! https://www.techpowerup.com/cpu-specs/?generation=Intel+Pentium+III+Xeon
CHECK_UARCH(arch, 0, 6, 0, 8, NA, "P6 Pentium III", UARCH_P6, 180) CHECK_UARCH(arch, 0, 6, 0, 8, NA, "P6 (Coppermine)", UARCH_P6_PENTIUM_III, 180) // Also: https://en.wikipedia.org/wiki/Pentium_III
CHECK_UARCH(arch, 0, 6, 0, 9, NA, "P6 Pentium M", UARCH_P6, 130) CHECK_UARCH(arch, 0, 6, 0, 9, NA, "P6 (Pentium M)", UARCH_P6_PENTIUM_III, 130)
CHECK_UARCH(arch, 0, 6, 0, 10, NA, "P6 Pentium III", UARCH_P6, 180) CHECK_UARCH(arch, 0, 6, 0, 10, NA, "P6 (Coppermine T)", UARCH_P6_PENTIUM_III, 180)
CHECK_UARCH(arch, 0, 6, 0, 11, NA, "P6 Pentium III", UARCH_P6, 130) CHECK_UARCH(arch, 0, 6, 0, 11, NA, "P6 (Tualatin)", UARCH_P6_PENTIUM_III, 130)
CHECK_UARCH(arch, 0, 6, 0, 13, NA, "Dothan", UARCH_DOTHAN, UNK) // process depends on core CHECK_UARCH(arch, 0, 6, 0, 13, NA, "Dothan", UARCH_DOTHAN, UNK) // process depends on core
CHECK_UARCH(arch, 0, 6, 0, 14, NA, "Yonah", UARCH_YONAH, 65) CHECK_UARCH(arch, 0, 6, 0, 14, NA, "Yonah", UARCH_YONAH, 65)
CHECK_UARCH(arch, 0, 6, 0, 15, NA, "Merom", UARCH_MEROM, 65) CHECK_UARCH(arch, 0, 6, 0, 15, NA, "Merom", UARCH_MEROM, 65)
CHECK_UARCH(arch, 0, 6, 1, 5, NA, "Dothan", UARCH_DOTHAN, 90) CHECK_UARCH(arch, 0, 6, 1, 5, NA, "Dothan", UARCH_DOTHAN, 90)
CHECK_UARCH(arch, 0, 6, 1, 6, NA, "Merom", UARCH_MEROM, 65) CHECK_UARCH(arch, 0, 6, 1, 6, NA, "Merom", UARCH_MEROM, 65)
CHECK_UARCH(arch, 0, 6, 1, 7, NA, "Penryn", UARCH_PENYR, 45) CHECK_UARCH(arch, 0, 6, 1, 7, NA, "Penryn", UARCH_PENYR, 45)
CHECK_UARCH(arch, 0, 6, 1, 10, NA, "Nehalem", UARCH_NEHALEM, 45) CHECK_UARCH(arch, 0, 6, 1, 10, NA, "Nehalem", UARCH_NEHALEM, 45)
CHECK_UARCH(arch, 0, 6, 1, 12, NA, "Bonnell", UARCH_BONNELL, 45) CHECK_UARCH(arch, 0, 6, 1, 12, NA, "Bonnell", UARCH_BONNELL, 45)
CHECK_UARCH(arch, 0, 6, 1, 13, NA, "Penryn", UARCH_PENYR, 45) CHECK_UARCH(arch, 0, 6, 1, 13, NA, "Penryn", UARCH_PENYR, 45)
CHECK_UARCH(arch, 0, 6, 1, 14, NA, "Nehalem", UARCH_NEHALEM, 45) CHECK_UARCH(arch, 0, 6, 1, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
CHECK_UARCH(arch, 0, 6, 1, 15, NA, "Nehalem", UARCH_NEHALEM, 45) CHECK_UARCH(arch, 0, 6, 1, 15, NA, "Nehalem", UARCH_NEHALEM, 45)
CHECK_UARCH(arch, 0, 6, 2, 5, NA, "Westmere", UARCH_WESTMERE, 32) CHECK_UARCH(arch, 0, 6, 2, 5, NA, "Westmere", UARCH_WESTMERE, 32)
CHECK_UARCH(arch, 0, 6, 2 , 6, NA, "Bonnell", UARCH_BONNELL, 45) CHECK_UARCH(arch, 0, 6, 2 , 6, NA, "Bonnell", UARCH_BONNELL, 45)
CHECK_UARCH(arch, 0, 6, 2, 7, NA, "Saltwell", UARCH_SALTWELL, 32) CHECK_UARCH(arch, 0, 6, 2, 7, NA, "Saltwell", UARCH_SALTWELL, 32)
CHECK_UARCH(arch, 0, 6, 2, 10, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32) CHECK_UARCH(arch, 0, 6, 2, 10, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
CHECK_UARCH(arch, 0, 6, 2, 12, NA, "Westmere", UARCH_WESTMERE, 32) CHECK_UARCH(arch, 0, 6, 2, 12, NA, "Westmere", UARCH_WESTMERE, 32)
CHECK_UARCH(arch, 0, 6, 2, 13, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32) CHECK_UARCH(arch, 0, 6, 2, 13, NA, "Sandy Bridge", UARCH_SANDY_BRIDGE, 32)
CHECK_UARCH(arch, 0, 6, 2, 14, NA, "Nehalem", UARCH_NEHALEM, 45) CHECK_UARCH(arch, 0, 6, 2, 14, NA, "Nehalem", UARCH_NEHALEM, 45)
CHECK_UARCH(arch, 0, 6, 2, 15, NA, "Westmere", UARCH_WESTMERE, 32) CHECK_UARCH(arch, 0, 6, 2, 15, NA, "Westmere", UARCH_WESTMERE, 32)
CHECK_UARCH(arch, 0, 6, 3, 5, NA, "Saltwell", UARCH_SALTWELL, 14) CHECK_UARCH(arch, 0, 6, 3, 5, NA, "Saltwell", UARCH_SALTWELL, 14)
CHECK_UARCH(arch, 0, 6, 3, 6, NA, "Saltwell", UARCH_SALTWELL, 32) CHECK_UARCH(arch, 0, 6, 3, 6, NA, "Saltwell", UARCH_SALTWELL, 32)
CHECK_UARCH(arch, 0, 6, 3, 7, NA, "Silvermont", UARCH_SILVERMONT, 22) CHECK_UARCH(arch, 0, 6, 3, 7, NA, "Silvermont", UARCH_SILVERMONT, 22)
CHECK_UARCH(arch, 0, 6, 3, 10, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22) CHECK_UARCH(arch, 0, 6, 3, 10, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
CHECK_UARCH(arch, 0, 6, 3, 12, NA, "Haswell", UARCH_HASWELL, 22) CHECK_UARCH(arch, 0, 6, 3, 12, NA, "Haswell", UARCH_HASWELL, 22)
CHECK_UARCH(arch, 0, 6, 3, 13, NA, "Broadwell", UARCH_BROADWELL, 14) CHECK_UARCH(arch, 0, 6, 3, 13, NA, "Broadwell", UARCH_BROADWELL, 14)
CHECK_UARCH(arch, 0, 6, 3, 14, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22) CHECK_UARCH(arch, 0, 6, 3, 14, NA, "Ivy Bridge", UARCH_IVY_BRIDGE, 22)
CHECK_UARCH(arch, 0, 6, 3, 15, NA, "Haswell", UARCH_HASWELL, 22) CHECK_UARCH(arch, 0, 6, 3, 15, NA, "Haswell", UARCH_HASWELL, 22)
CHECK_UARCH(arch, 0, 6, 4, 5, NA, "Haswell", UARCH_HASWELL, 22) CHECK_UARCH(arch, 0, 6, 4, 5, NA, "Haswell", UARCH_HASWELL, 22)
CHECK_UARCH(arch, 0, 6, 4, 6, NA, "Haswell", UARCH_HASWELL, 22) CHECK_UARCH(arch, 0, 6, 4, 6, NA, "Haswell", UARCH_HASWELL, 22)
CHECK_UARCH(arch, 0, 6, 4, 7, NA, "Broadwell", UARCH_BROADWELL, 14) CHECK_UARCH(arch, 0, 6, 4, 7, NA, "Broadwell", UARCH_BROADWELL, 14)
CHECK_UARCH(arch, 0, 6, 4, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no docs, but /proc/cpuinfo seen in wild CHECK_UARCH(arch, 0, 6, 4, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no docs, but /proc/cpuinfo seen in wild
CHECK_UARCH(arch, 0, 6, 4, 12, NA, "Airmont", UARCH_AIRMONT, 14) CHECK_UARCH(arch, 0, 6, 4, 12, NA, "Airmont", UARCH_AIRMONT, 14)
CHECK_UARCH(arch, 0, 6, 4, 13, NA, "Silvermont", UARCH_SILVERMONT, 22) CHECK_UARCH(arch, 0, 6, 4, 13, NA, "Silvermont", UARCH_SILVERMONT, 22)
CHECK_UARCH(arch, 0, 6, 4, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14) CHECK_UARCH(arch, 0, 6, 4, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 4, 14, NA, "Skylake", UARCH_SKYLAKE, 14) CHECK_UARCH(arch, 0, 6, 4, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
CHECK_UARCH(arch, 0, 6, 4, 15, NA, "Broadwell", UARCH_BROADWELL, 14) CHECK_UARCH(arch, 0, 6, 4, 15, NA, "Broadwell", UARCH_BROADWELL, 14)
CHECK_UARCH(arch, 0, 6, 5, 5, 6, "Cascade Lake", UARCH_CASCADE_LAKE, 14) // no docs, but example from Greg Stewart CHECK_UARCH(arch, 0, 6, 5, 5, 6, "Cascade Lake", UARCH_CASCADE_LAKE, 14) // no docs, but example from Greg Stewart
CHECK_UARCH(arch, 0, 6, 5, 5, 7, "Cascade Lake", UARCH_CASCADE_LAKE, 14) CHECK_UARCH(arch, 0, 6, 5, 5, 7, "Cascade Lake", UARCH_CASCADE_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 5, 5, 10, "Cooper Lake", UARCH_COOPER_LAKE, 14) CHECK_UARCH(arch, 0, 6, 5, 5, 10, "Cooper Lake", UARCH_COOPER_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 5, 5, NA, "Skylake", UARCH_SKYLAKE, 14) CHECK_UARCH(arch, 0, 6, 5, 5, NA, "Skylake", UARCH_SKYLAKE, 14)
CHECK_UARCH(arch, 0, 6, 5, 6, NA, "Broadwell", UARCH_BROADWELL, 14) CHECK_UARCH(arch, 0, 6, 5, 6, NA, "Broadwell", UARCH_BROADWELL, 14)
CHECK_UARCH(arch, 0, 6, 5, 7, NA, "Knights Landing", UARCH_KNIGHTS_LANDING, 14) CHECK_UARCH(arch, 0, 6, 5, 7, NA, "Knights Landing", UARCH_KNIGHTS_LANDING, 14)
CHECK_UARCH(arch, 0, 6, 5, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 5, 10, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 5, 12, NA, "Goldmont", UARCH_GOLDMONT, 14) CHECK_UARCH(arch, 0, 6, 5, 12, NA, "Goldmont", UARCH_GOLDMONT, 14)
CHECK_UARCH(arch, 0, 6, 5, 13, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 5, 13, NA, "Silvermont", UARCH_SILVERMONT, 22) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 5, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14) CHECK_UARCH(arch, 0, 6, 5, 14, 8, "Kaby Lake", UARCH_KABY_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 5, 14, NA, "Skylake", UARCH_SKYLAKE, 14) CHECK_UARCH(arch, 0, 6, 5, 14, NA, "Skylake", UARCH_SKYLAKE, 14)
CHECK_UARCH(arch, 0, 6, 5, 15, NA, "Goldmont", UARCH_GOLDMONT, 14) CHECK_UARCH(arch, 0, 6, 5, 15, NA, "Goldmont", UARCH_GOLDMONT, 14)
CHECK_UARCH(arch, 0, 6, 6, 6, NA, "Palm Cove", UARCH_PALM_COVE, 10) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 6, 6, NA, "Palm Cove", UARCH_PALM_COVE, 10) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 6, 10, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 6, 10, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 6, 12, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 6, 12, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 7, 5, NA, "Airmont", UARCH_AIRMONT, 14) // no spec update; whispers & rumors CHECK_UARCH(arch, 0, 6, 7, 5, NA, "Airmont", UARCH_AIRMONT, 14) // no spec update; whispers & rumors
CHECK_UARCH(arch, 0, 6, 7, 10, NA, "Goldmont Plus", UARCH_GOLDMONT_PLUS, 14) CHECK_UARCH(arch, 0, 6, 7, 10, NA, "Goldmont Plus", UARCH_GOLDMONT_PLUS, 14)
CHECK_UARCH(arch, 0, 6, 7, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 7, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 7, 14, NA, "Ice Lake", UARCH_ICE_LAKE, 10) CHECK_UARCH(arch, 0, 6, 7, 14, NA, "Ice Lake", UARCH_ICE_LAKE, 10)
CHECK_UARCH(arch, 0, 6, 8, 5, NA, "Knights Mill", UARCH_KNIGHTS_MILL, 14) // no spec update; only MSR_CPUID_table* so far CHECK_UARCH(arch, 0, 6, 8, 5, NA, "Knights Mill", UARCH_KNIGHTS_MILL, 14) // no spec update; only MSR_CPUID_table* so far
CHECK_UARCH(arch, 0, 6, 8, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX* CHECK_UARCH(arch, 0, 6, 8, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
CHECK_UARCH(arch, 0, 6, 8, 10, NA, "Tremont", UARCH_TREMONT, 10) // no spec update; only geekbench.com example CHECK_UARCH(arch, 0, 6, 8, 10, NA, "Tremont", UARCH_TREMONT, 10) // no spec update; only geekbench.com example
CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64 CHECK_UARCH(arch, 0, 6, 8, 12, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64 CHECK_UARCH(arch, 0, 6, 8, 13, NA, "Tiger Lake", UARCH_TIGER_LAKE, 10) // instlatx64
// CHECK_UARCH(arch, 0, 6, 8, 14, 9, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake) // CHECK_UARCH(arch, 0, 6, 8, 14, 9, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
// CHECK_UARCH(arch, 0, 6, 8, 14, 10, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U) // CHECK_UARCH(arch, 0, 6, 8, 14, 10, ...) It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U)
CHECK_UARCH(arch, 0, 6, 8, 14, 11, "Whiskey Lake", UARCH_WHISKEY_LAKE, 14) // wikichip CHECK_UARCH(arch, 0, 6, 8, 14, 11, "Whiskey Lake", UARCH_WHISKEY_LAKE, 14) // wikichip
CHECK_UARCH(arch, 0, 6, 8, 14, 12, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip CHECK_UARCH(arch, 0, 6, 8, 14, 12, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
CHECK_UARCH(arch, 0, 6, 9, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX* CHECK_UARCH(arch, 0, 6, 9, 6, NA, "Tremont", UARCH_TREMONT, 10) // LX*
CHECK_UARCH(arch, 0, 6, 9, 7, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-S) CHECK_UARCH(arch, 0, 6, 9, 7, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-S)
CHECK_UARCH(arch, 0, 6, 9, 10, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-P) CHECK_UARCH(arch, 0, 6, 9, 10, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64 (Alder Lake-P)
CHECK_UARCH(arch, 0, 6, 9, 12, NA, "Tremont", UARCH_TREMONT, 10) // LX* CHECK_UARCH(arch, 0, 6, 9, 12, NA, "Tremont", UARCH_TREMONT, 10) // LX*
CHECK_UARCH(arch, 0, 6, 9, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // LX* CHECK_UARCH(arch, 0, 6, 9, 13, NA, "Sunny Cove", UARCH_SUNNY_COVE, 10) // LX*
CHECK_UARCH(arch, 0, 6, 9, 14, 9, "Kaby Lake", UARCH_KABY_LAKE, 14) CHECK_UARCH(arch, 0, 6, 9, 14, 9, "Kaby Lake", UARCH_KABY_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 9, 14, 10, "Coffee Lake", UARCH_COFFEE_LAKE, 14) CHECK_UARCH(arch, 0, 6, 9, 14, 10, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 9, 14, 11, "Coffee Lake", UARCH_COFFEE_LAKE, 14) CHECK_UARCH(arch, 0, 6, 9, 14, 11, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 9, 14, 12, "Coffee Lake", UARCH_COFFEE_LAKE, 14) CHECK_UARCH(arch, 0, 6, 9, 14, 12, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 9, 14, 13, "Coffee Lake", UARCH_COFFEE_LAKE, 14) CHECK_UARCH(arch, 0, 6, 9, 14, 13, "Coffee Lake", UARCH_COFFEE_LAKE, 14)
CHECK_UARCH(arch, 0, 6, 10, 5, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip CHECK_UARCH(arch, 0, 6, 10, 5, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // wikichip
CHECK_UARCH(arch, 0, 6, 10, 6, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // instlatx64.atw.hu (i7-10710U) CHECK_UARCH(arch, 0, 6, 10, 6, NA, "Comet Lake", UARCH_COMET_LAKE, 14) // instlatx64.atw.hu (i7-10710U)
CHECK_UARCH(arch, 0, 6, 10, 7, NA, "Rocket Lake", UARCH_ROCKET_LAKE, 14) // instlatx64.atw.hu (i7-11700K) CHECK_UARCH(arch, 0, 6, 10, 7, NA, "Rocket Lake", UARCH_ROCKET_LAKE, 14) // instlatx64.atw.hu (i7-11700K)
CHECK_UARCH(arch, 0, 6, 11, 7, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13600K) CHECK_UARCH(arch, 0, 6, 11, 7, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13600K)
CHECK_UARCH(arch, 0, 6, 11, 10, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i7-1370P) CHECK_UARCH(arch, 0, 6, 11, 10, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i7-1370P)
CHECK_UARCH(arch, 0, 6, 11, 14, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64.atw.hu (Alder Lake-N) CHECK_UARCH(arch, 0, 6, 11, 14, NA, "Alder Lake", UARCH_ALDER_LAKE, 10) // instlatx64.atw.hu (Alder Lake-N)
CHECK_UARCH(arch, 0, 6, 11, 15, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13500) CHECK_UARCH(arch, 0, 6, 11, 15, NA, "Raptor Lake", UARCH_RAPTOR_LAKE, 10) // instlatx64.atw.hu (i5-13500)
CHECK_UARCH(arch, 0, 11, 0, 0, NA, "Knights Ferry", UARCH_KNIGHTS_FERRY, 45) // found only on en.wikichip.org CHECK_UARCH(arch, 0, 11, 0, 0, NA, "Knights Ferry", UARCH_KNIGHTS_FERRY, 45) // found only on en.wikichip.org
CHECK_UARCH(arch, 0, 11, 0, 1, NA, "Knights Corner", UARCH_KNIGHTS_CORNER, 22) CHECK_UARCH(arch, 0, 11, 0, 1, NA, "Knights Corner", UARCH_KNIGHTS_CORNER, 22)
CHECK_UARCH(arch, 0, 15, 0, 0, NA, "Willamette", UARCH_WILLAMETTE, 180) CHECK_UARCH(arch, 0, 15, 0, 0, NA, "Willamette", UARCH_WILLAMETTE, 180)
CHECK_UARCH(arch, 0, 15, 0, 1, NA, "Willamette", UARCH_WILLAMETTE, 180) CHECK_UARCH(arch, 0, 15, 0, 1, NA, "Willamette", UARCH_WILLAMETTE, 180)
CHECK_UARCH(arch, 0, 15, 0, 2, NA, "Northwood", UARCH_NORTHWOOD, 130) CHECK_UARCH(arch, 0, 15, 0, 2, NA, "Northwood", UARCH_NORTHWOOD, 130)
CHECK_UARCH(arch, 0, 15, 0, 3, NA, "Prescott", UARCH_PRESCOTT, 90) CHECK_UARCH(arch, 0, 15, 0, 3, NA, "Prescott", UARCH_PRESCOTT, 90)
CHECK_UARCH(arch, 0, 15, 0, 4, NA, "Prescott", UARCH_PRESCOTT, 90) CHECK_UARCH(arch, 0, 15, 0, 4, NA, "Prescott", UARCH_PRESCOTT, 90)
CHECK_UARCH(arch, 0, 15, 0, 6, NA, "Cedar Mill", UARCH_CEDAR_MILL, 65) CHECK_UARCH(arch, 0, 15, 0, 6, NA, "Cedar Mill", UARCH_CEDAR_MILL, 65)
CHECK_UARCH(arch, 1, 15, 0, 0, NA, "Itanium2", UARCH_ITANIUM2, 180) CHECK_UARCH(arch, 1, 15, 0, 0, NA, "Itanium2", UARCH_ITANIUM2, 180)
CHECK_UARCH(arch, 1, 15, 0, 1, NA, "Itanium2", UARCH_ITANIUM2, 130) CHECK_UARCH(arch, 1, 15, 0, 1, NA, "Itanium2", UARCH_ITANIUM2, 130)
CHECK_UARCH(arch, 1, 15, 0, 2, NA, "Itanium2", UARCH_ITANIUM2, 130) CHECK_UARCH(arch, 1, 15, 0, 2, NA, "Itanium2", UARCH_ITANIUM2, 130)
UARCH_END UARCH_END
return arch; return arch;
} }
@@ -392,11 +393,16 @@ struct uarch* get_uarch_from_cpuid_amd(uint32_t ef, uint32_t f, uint32_t em, uin
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) { struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s) {
if(cpu->cpu_vendor == CPU_VENDOR_INTEL) { if(cpu->cpu_vendor == CPU_VENDOR_INTEL) {
struct uarch* arch = emalloc(sizeof(struct uarch));
if(dump == 0x000806E9) { if(dump == 0x000806E9) {
if (cpu->cpu_name == NULL) {
printErr("Unable to find uarch without CPU name");
fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK);
return arch;
}
// It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake) // It is not possible to determine uarch only from CPUID dump (can be Kaby Lake or Amber Lake)
// See issue https://github.com/Dr-Noob/cpufetch/issues/122 // See issue https://github.com/Dr-Noob/cpufetch/issues/122
struct uarch* arch = emalloc(sizeof(struct uarch));
if(strstr(cpu->cpu_name, "Y") != NULL) { if(strstr(cpu->cpu_name, "Y") != NULL) {
fill_uarch(arch, "Amber Lake", UARCH_AMBER_LAKE, 14); fill_uarch(arch, "Amber Lake", UARCH_AMBER_LAKE, 14);
} }
@@ -407,10 +413,14 @@ struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t
return arch; return arch;
} }
else if (dump == 0x000806EA) { else if (dump == 0x000806EA) {
if (cpu->cpu_name == NULL) {
printErr("Unable to find uarch without CPU name");
fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK);
return arch;
}
// It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U) // It is not possible to determine uarch only from CPUID dump (can be Kaby Lake R or Coffee Lake U)
// See issue https://github.com/Dr-Noob/cpufetch/issues/149 // See issue https://github.com/Dr-Noob/cpufetch/issues/149
struct uarch* arch = emalloc(sizeof(struct uarch));
if(strstr(cpu->cpu_name, "i5-8250U") != NULL || if(strstr(cpu->cpu_name, "i5-8250U") != NULL ||
strstr(cpu->cpu_name, "i5-8350U") != NULL || strstr(cpu->cpu_name, "i5-8350U") != NULL ||
strstr(cpu->cpu_name, "i7-8550U") != NULL || strstr(cpu->cpu_name, "i7-8550U") != NULL ||
@@ -429,6 +439,41 @@ struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t
return get_uarch_from_cpuid_amd(ef, f, em, m, s); return get_uarch_from_cpuid_amd(ef, f, em, m, s);
} }
// If we cannot get the CPU name from CPUID, try to infer it from uarch
char* infer_cpu_name_from_uarch(struct uarch* arch) {
char* cpu_name = NULL;
if (arch == NULL) {
printErr("infer_cpu_name_from_uarch: Unable to find CPU name");
cpu_name = ecalloc(strlen(STRING_UNKNOWN) + 1, sizeof(char));
strcpy(cpu_name, STRING_UNKNOWN);
return cpu_name;
}
char *str = NULL;
if (arch->uarch == UARCH_P5)
str = "Intel Pentium";
else if (arch->uarch == UARCH_P5_MMX)
str = "Intel Pentium MMX";
else if (arch->uarch == UARCH_P6_PENTIUM_II)
str = "Intel Pentium II";
else if (arch->uarch == UARCH_P6_PENTIUM_III)
str = "Intel Pentium III";
else
printErr("Unable to find name from uarch: %d", arch->uarch);
if (str == NULL) {
cpu_name = ecalloc(strlen(STRING_UNKNOWN) + 1, sizeof(char));
strcpy(cpu_name, STRING_UNKNOWN);
}
else {
cpu_name = ecalloc(strlen(str) + 1, sizeof(char));
strcpy(cpu_name, str);
}
return cpu_name;
}
bool vpus_are_AVX512(struct cpuInfo* cpu) { bool vpus_are_AVX512(struct cpuInfo* cpu) {
return cpu->arch->uarch != UARCH_ICE_LAKE && return cpu->arch->uarch != UARCH_ICE_LAKE &&
cpu->arch->uarch != UARCH_TIGER_LAKE && cpu->arch->uarch != UARCH_TIGER_LAKE &&
@@ -499,9 +544,6 @@ char* get_str_process(struct cpuInfo* cpu) {
if(process == UNK) { if(process == UNK) {
snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN); snprintf(str, strlen(STRING_UNKNOWN)+1, STRING_UNKNOWN);
} }
else if(process > 100) {
sprintf(str, "%.2fum", (double)process/100);
}
else if(process > 0){ else if(process > 0){
sprintf(str, "%dnm", process); sprintf(str, "%dnm", process);
} }

View File

@@ -8,6 +8,7 @@
struct uarch; struct uarch;
struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s); struct uarch* get_uarch_from_cpuid(struct cpuInfo* cpu, uint32_t dump, uint32_t ef, uint32_t f, uint32_t em, uint32_t m, int s);
char* infer_cpu_name_from_uarch(struct uarch* arch);
bool vpus_are_AVX512(struct cpuInfo* cpu); bool vpus_are_AVX512(struct cpuInfo* cpu);
bool is_knights_landing(struct cpuInfo* cpu); bool is_knights_landing(struct cpuInfo* cpu);
int get_number_of_vpus(struct cpuInfo* cpu); int get_number_of_vpus(struct cpuInfo* cpu);