Compare commits

..

13 Commits
i212 ... i220

12 changed files with 314 additions and 209 deletions

View File

@@ -289,7 +289,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 +305,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;
@@ -314,70 +314,78 @@ void fill_cpu_info_avalanche_blizzard(struct cpuInfo* cpu, uint32_t pcores, uint
ava->next_cpu = NULL; ava->next_cpu = NULL;
} }
struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) { void fill_cpu_info_everest_sawtooth(struct cpuInfo* cpu, uint32_t pcores, uint32_t ecores) {
uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily"); // 1. Fill SAWTOOTH
struct cpuInfo* saw = cpu;
saw->midr = MIDR_APPLE_M3_SAWTOOTH;
saw->arch = get_uarch_from_midr(saw->midr, saw);
saw->cach = get_cache_info(saw);
saw->feat = get_features_info();
saw->topo = malloc(sizeof(struct topology));
saw->topo->cach = saw->cach;
saw->topo->total_cores = ecores;
saw->freq = malloc(sizeof(struct frequency));
saw->freq->base = UNKNOWN_DATA;
saw->freq->max = 2750;
saw->hv = malloc(sizeof(struct hypervisor));
saw->hv->present = false;
saw->next_cpu = malloc(sizeof(struct cpuInfo));
// 2. Fill EVEREST
struct cpuInfo* eve = saw->next_cpu;
eve->midr = MIDR_APPLE_M3_EVEREST;
eve->arch = get_uarch_from_midr(eve->midr, eve);
eve->cach = get_cache_info(eve);
eve->feat = get_features_info();
eve->topo = malloc(sizeof(struct topology));
eve->topo->cach = eve->cach;
eve->topo->total_cores = pcores;
eve->freq = malloc(sizeof(struct frequency));
eve->freq->base = UNKNOWN_DATA;
eve->freq->max = 4050;
eve->hv = malloc(sizeof(struct hypervisor));
eve->hv->present = false;
eve->next_cpu = NULL;
}
struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) {
// 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
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->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();
uint32_t cpu_subfamily = get_sys_info_by_name("hw.cpusubfamily"); cpu->peak_performance = get_peak_performance(cpu);
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;
} }
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) {
fill_cpu_info_everest_sawtooth(cpu, pcores, ecores);
cpu->soc = get_soc(); cpu->soc = get_soc();
cpu->peak_performance = get_peak_performance(cpu); cpu->peak_performance = get_peak_performance(cpu);
} }
@@ -467,6 +475,15 @@ void print_debug(struct cpuInfo* cpu) {
printf("%ld MHz\n", freq); printf("%ld MHz\n", freq);
} }
} }
#if defined(__APPLE__) || defined(__MACH__)
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.nperflevels: %d\n", get_sys_info_by_name("hw.nperflevels"));
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
} }
void free_topo_struct(struct topology* topo) { void free_topo_struct(struct topology* topo) {

View File

@@ -734,6 +734,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 +743,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} }
}; };
@@ -886,6 +889,24 @@ struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) {
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;
} }
} }
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO ||
cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) {
// Check M3 version
if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH) {
fill_soc(soc, "M3", SOC_APPLE_M3, 3);
}
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO) {
fill_soc(soc, "M3 Pro", SOC_APPLE_M3_PRO, 3);
}
else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) {
fill_soc(soc, "M3 Max", SOC_APPLE_M3_MAX, 3);
}
else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family);
soc->soc_vendor = SOC_VENDOR_UNKNOWN;
}
}
else { else {
printBug("Found invalid cpu_family: 0x%.8X", cpu_family); printBug("Found invalid cpu_family: 0x%.8X", cpu_family);
soc->soc_vendor = SOC_VENDOR_UNKNOWN; soc->soc_vendor = SOC_VENDOR_UNKNOWN;

View File

@@ -309,6 +309,9 @@ enum {
SOC_APPLE_M2_PRO, SOC_APPLE_M2_PRO,
SOC_APPLE_M2_MAX, SOC_APPLE_M2_MAX,
SOC_APPLE_M2_ULTRA, SOC_APPLE_M2_ULTRA,
SOC_APPLE_M3,
SOC_APPLE_M3_PRO,
SOC_APPLE_M3_MAX,
// ALLWINNER // ALLWINNER
SOC_ALLWINNER_A10, SOC_ALLWINNER_A10,
SOC_ALLWINNER_A13, SOC_ALLWINNER_A13,
@@ -346,10 +349,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,9 +368,9 @@ inline static VENDOR get_soc_vendor_from_soc(SOC soc) {
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_M2_ULTRA) 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

@@ -8,6 +8,9 @@
// APPLE_CPU_PART_M2_BLIZZARD=0x30,M2_AVALANCHE=0x31 // APPLE_CPU_PART_M2_BLIZZARD=0x30,M2_AVALANCHE=0x31
#define MIDR_APPLE_M2_BLIZZARD 0x610F0300 #define MIDR_APPLE_M2_BLIZZARD 0x610F0300
#define MIDR_APPLE_M2_AVALANCHE 0x610F0310 #define MIDR_APPLE_M2_AVALANCHE 0x610F0310
// https://github.com/AsahiLinux/m1n1/blob/main/src/chickens.c
#define MIDR_APPLE_M3_SAWTOOTH 0x610F0480
#define MIDR_APPLE_M3_EVEREST 0x610F0490
// M1 / A14 // M1 / A14
#ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
@@ -17,6 +20,12 @@
#ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD #ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD
#define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D #define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D
#endif #endif
// M3 / A16 / A17
// https://ratfactor.com/zig/stdlib-browseable2/c/darwin.zig.html
// https://github.com/Dr-Noob/cpufetch/issues/210
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH 0x8765EDEA
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO 0x5F4DEA93
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX 0x72015832
// For detecting different M1 types // For detecting different M1 types
// NOTE: Could also be achieved detecting different // NOTE: Could also be achieved detecting different

View File

@@ -105,6 +105,8 @@ enum {
UARCH_FIRESTORM, // Apple M1 processor (big cores). UARCH_FIRESTORM, // Apple M1 processor (big cores).
UARCH_BLIZZARD, // Apple M2 processor (little cores). UARCH_BLIZZARD, // Apple M2 processor (little cores).
UARCH_AVALANCHE, // Apple M2 processor (big cores). UARCH_AVALANCHE, // Apple M2 processor (big cores).
UARCH_SAWTOOTH, // Apple M3 processor (little cores).
UARCH_EVEREST, // Apple M3 processor (big cores).
// CAVIUM // CAVIUM
UARCH_THUNDERX, // Cavium ThunderX UARCH_THUNDERX, // Cavium ThunderX
UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan). UARCH_THUNDERX2, // Cavium ThunderX2 (originally Broadcom Vulkan).
@@ -220,6 +222,7 @@ void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u,
* Other sources: * Other sources:
* - https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/cputype.h * - https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/cputype.h
* - https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/cputype.h * - https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/cputype.h
* - https://github.com/AsahiLinux/m1n1/blob/main/src/chickens.c
*/ */
struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) { struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
struct uarch* arch = emalloc(sizeof(struct uarch)); struct uarch* arch = emalloc(sizeof(struct uarch));
@@ -327,6 +330,8 @@ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
CHECK_UARCH(arch, cpu, 'a', 0x023, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE) CHECK_UARCH(arch, cpu, 'a', 0x023, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE)
CHECK_UARCH(arch, cpu, 'a', 0x030, NA, NA, "Blizzard", UARCH_BLIZZARD, CPU_VENDOR_APPLE) CHECK_UARCH(arch, cpu, 'a', 0x030, NA, NA, "Blizzard", UARCH_BLIZZARD, CPU_VENDOR_APPLE)
CHECK_UARCH(arch, cpu, 'a', 0x031, NA, NA, "Avalanche", UARCH_AVALANCHE, CPU_VENDOR_APPLE) CHECK_UARCH(arch, cpu, 'a', 0x031, NA, NA, "Avalanche", UARCH_AVALANCHE, CPU_VENDOR_APPLE)
CHECK_UARCH(arch, cpu, 'a', 0x048, NA, NA, "Sawtooth", UARCH_SAWTOOTH, CPU_VENDOR_APPLE)
CHECK_UARCH(arch, cpu, 'a', 0x049, NA, NA, "Everest", UARCH_EVEREST, CPU_VENDOR_APPLE)
CHECK_UARCH(arch, cpu, 'V', 0x581, NA, NA, "PJ4", UARCH_PJ4, CPU_VENDOR_MARVELL) CHECK_UARCH(arch, cpu, 'V', 0x581, NA, NA, "PJ4", UARCH_PJ4, CPU_VENDOR_MARVELL)
CHECK_UARCH(arch, cpu, 'V', 0x584, NA, NA, "PJ4B-MP", UARCH_PJ4, CPU_VENDOR_MARVELL) CHECK_UARCH(arch, cpu, 'V', 0x584, NA, NA, "PJ4B-MP", UARCH_PJ4, CPU_VENDOR_MARVELL)
@@ -387,6 +392,7 @@ int get_number_of_vpus(struct cpuInfo* cpu) {
MICROARCH ua = cpu->arch->uarch; MICROARCH ua = cpu->arch->uarch;
switch(ua) { switch(ua) {
case UARCH_EVEREST: // Just a guess, needs confirmation.
case UARCH_FIRESTORM: // [https://dougallj.github.io/applecpu/firestorm-simd.html] case UARCH_FIRESTORM: // [https://dougallj.github.io/applecpu/firestorm-simd.html]
case UARCH_AVALANCHE: // [https://en.wikipedia.org/wiki/Comparison_of_ARM_processors] case UARCH_AVALANCHE: // [https://en.wikipedia.org/wiki/Comparison_of_ARM_processors]
case UARCH_CORTEX_X1: // [https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/3] case UARCH_CORTEX_X1: // [https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/3]
@@ -394,6 +400,7 @@ int get_number_of_vpus(struct cpuInfo* cpu) {
case UARCH_CORTEX_X3: // [https://www.hwcooling.net/en/cortex-x3-the-new-fastest-arm-core-architecture-analysis: "The FPU and SIMD unit of the core still has four pipelines"] case UARCH_CORTEX_X3: // [https://www.hwcooling.net/en/cortex-x3-the-new-fastest-arm-core-architecture-analysis: "The FPU and SIMD unit of the core still has four pipelines"]
case UARCH_NEOVERSE_V1: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/neoverse_v1] case UARCH_NEOVERSE_V1: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/neoverse_v1]
return 4; return 4;
case UARCH_SAWTOOTH: // Needs confirmation, rn this is the best we know: https://mastodon.social/@dougall/111118317031041336
case UARCH_EXYNOS_M3: // [https://www.anandtech.com/show/12361/samsung-exynos-m3-architecture] case UARCH_EXYNOS_M3: // [https://www.anandtech.com/show/12361/samsung-exynos-m3-architecture]
case UARCH_EXYNOS_M4: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m4#Block_Diagram] case UARCH_EXYNOS_M4: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m4#Block_Diagram]
case UARCH_EXYNOS_M5: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m5] case UARCH_EXYNOS_M5: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m5]

View File

@@ -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
}; };

View File

@@ -21,7 +21,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";

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

@@ -30,8 +30,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 +44,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
}; };
@@ -284,7 +286,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);
} }
} }
@@ -484,9 +486,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;
@@ -536,12 +537,17 @@ 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);
}
// If any field of the struct is NULL,
// return early, as next functions
// require non NULL fields in cach and topo
ptr->cach = get_cache_info(ptr); ptr->cach = get_cache_info(ptr);
if(ptr->cach == NULL) return cpu; if(ptr->cach == NULL) return cpu;
@@ -1170,9 +1176,7 @@ void print_raw(struct cpuInfo* cpu) {
} }
void free_topo_struct(struct topology* topo) { void free_topo_struct(struct topology* topo) {
if(topo->apic->cache_select_mask != NULL)
free(topo->apic->cache_select_mask); free(topo->apic->cache_select_mask);
if(topo->apic->cache_id_apic != NULL)
free(topo->apic->cache_id_apic); free(topo->apic->cache_id_apic);
free(topo->apic); free(topo->apic);
free(topo); free(topo);

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,
@@ -145,31 +147,31 @@ struct uarch* get_uarch_from_cpuid_intel(uint32_t ef, uint32_t f, uint32_t em, u
// 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)
@@ -392,11 +394,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 +414,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 +440,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 +545,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);