From ce6e6f9cd87df72a38c08715cde62880185a2891 Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Sun, 24 Dec 2023 22:41:05 +0000 Subject: [PATCH] [v1.04][ARM] Preeliminary M3 support --- src/arm/midr.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ src/arm/soc.c | 18 ++++++++++++++ src/arm/socs.h | 5 +++- src/arm/sysctl.h | 9 +++++++ src/arm/uarch.c | 7 ++++++ 5 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/arm/midr.c b/src/arm/midr.c index e01fd27..ae041c6 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -314,6 +314,41 @@ void fill_cpu_info_avalanche_blizzard(struct cpuInfo* cpu, uint32_t pcores, uint ava->next_cpu = NULL; } +void fill_cpu_info_everest_sawtooth(struct cpuInfo* cpu, uint32_t pcores, uint32_t ecores) { + // 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 = pcores; + 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 = ecores; + 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) { uint32_t cpu_family = get_sys_info_by_name("hw.cpufamily"); @@ -381,6 +416,29 @@ struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) { cpu->soc = get_soc(); cpu->peak_performance = get_peak_performance(cpu); } + else if(cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH || + cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_PRO || + cpu_family == CPUFAMILY_ARM_EVEREST_SAWTOOTH_MAX) { + cpu->num_cpus = 2; + // Now detect the M3 version + 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); + } else { printBug("Found invalid cpu_family: 0x%.8X", cpu_family); return NULL; @@ -467,6 +525,12 @@ void print_debug(struct cpuInfo* cpu) { 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.physicalcpu: %d\n", get_sys_info_by_name("hw.physicalcpu")); + #endif } void free_topo_struct(struct topology* topo) { diff --git a/src/arm/soc.c b/src/arm/soc.c index 0d86bc3..99c5877 100644 --- a/src/arm/soc.c +++ b/src/arm/soc.c @@ -886,6 +886,24 @@ struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) { 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 { printBug("Found invalid cpu_family: 0x%.8X", cpu_family); soc->soc_vendor = SOC_VENDOR_UNKNOWN; diff --git a/src/arm/socs.h b/src/arm/socs.h index b75e24d..0261fa6 100644 --- a/src/arm/socs.h +++ b/src/arm/socs.h @@ -309,6 +309,9 @@ enum { SOC_APPLE_M2_PRO, SOC_APPLE_M2_MAX, SOC_APPLE_M2_ULTRA, + SOC_APPLE_M3, + SOC_APPLE_M3_PRO, + SOC_APPLE_M3_MAX, // ALLWINNER SOC_ALLWINNER_A10, SOC_ALLWINNER_A13, @@ -364,7 +367,7 @@ 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_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_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_ROCKCHIP_3288 && soc <= SOC_ROCKCHIP_3588S) return SOC_VENDOR_ROCKCHIP; else if(soc >= SOC_GOOGLE_TENSOR && soc <= SOC_GOOGLE_TENSOR_G3) return SOC_VENDOR_GOOGLE; diff --git a/src/arm/sysctl.h b/src/arm/sysctl.h index 687c377..f4432ab 100644 --- a/src/arm/sysctl.h +++ b/src/arm/sysctl.h @@ -8,6 +8,9 @@ // APPLE_CPU_PART_M2_BLIZZARD=0x30,M2_AVALANCHE=0x31 #define MIDR_APPLE_M2_BLIZZARD 0x610F0300 #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 #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM @@ -17,6 +20,12 @@ #ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD #define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D #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 // NOTE: Could also be achieved detecting different diff --git a/src/arm/uarch.c b/src/arm/uarch.c index 4f73eb6..dd5ebe2 100644 --- a/src/arm/uarch.c +++ b/src/arm/uarch.c @@ -105,6 +105,8 @@ enum { 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). @@ -220,6 +222,7 @@ void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, * Other sources: * - 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://github.com/AsahiLinux/m1n1/blob/main/src/chickens.c */ struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) { 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', 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', 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', 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; switch(ua) { + case UARCH_EVEREST: // Just a guess, needs confirmation. 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_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_NEOVERSE_V1: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/neoverse_v1] 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_M4: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m4#Block_Diagram] case UARCH_EXYNOS_M5: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m5]