From 0ea07547279bf9cd08e0fa8e2aa484646ad0a03f Mon Sep 17 00:00:00 2001 From: Dr-Noob Date: Sun, 6 Mar 2022 10:40:05 +0100 Subject: [PATCH] [v1.01] Experimental M1 chip detection using hw.cpusubfamily --- src/arm/midr.c | 32 ++++++++++++++++++++++---------- src/arm/soc.c | 28 +++++++++++++++++++++++++++- src/arm/socs.h | 6 ++++-- src/arm/sysctl.h | 16 ++++++++++++++++ 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/arm/midr.c b/src/arm/midr.c index 83b46a9..1ceae14 100644 --- a/src/arm/midr.c +++ b/src/arm/midr.c @@ -10,12 +10,6 @@ #include #elif defined __APPLE__ || __MACH__ #include "sysctl.h" - // From Linux kernel: arch/arm64/include/asm/cputype.h - #define MIDR_APPLE_M1_ICESTORM 0x610F0220 - #define MIDR_APPLE_M1_FIRESTORM 0x610F0230 - #ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM - #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3 - #endif #endif #include "../common/global.h" @@ -244,7 +238,7 @@ struct cpuInfo* get_cpu_info_linux(struct cpuInfo* cpu) { } #elif defined __APPLE__ || __MACH__ -void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu) { +void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu, uint32_t pcores, uint32_t ecores) { // 1. Fill ICESTORM struct cpuInfo* ice = cpu; @@ -254,7 +248,7 @@ void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu) { ice->feat = get_features_info(); ice->topo = malloc(sizeof(struct topology)); ice->topo->cach = ice->cach; - ice->topo->total_cores = 4; + ice->topo->total_cores = ecores; ice->freq = malloc(sizeof(struct frequency)); ice->freq->base = UNKNOWN_DATA; ice->freq->max = 2064; @@ -270,7 +264,7 @@ void fill_cpu_info_firestorm_icestorm(struct cpuInfo* cpu) { fire->feat = get_features_info(); fire->topo = malloc(sizeof(struct topology)); fire->topo->cach = fire->cach; - fire->topo->total_cores = 4; + fire->topo->total_cores = pcores; fire->freq = malloc(sizeof(struct frequency)); fire->freq->base = UNKNOWN_DATA; fire->freq->max = 3200; @@ -286,8 +280,26 @@ struct cpuInfo* get_cpu_info_mach(struct cpuInfo* cpu) { // is a ARM_FIRESTORM_ICESTORM (Apple M1) if(cpu_family == CPUFAMILY_ARM_FIRESTORM_ICESTORM) { cpu->num_cpus = 2; + // 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. Detect number of cores + uint32_t physicalcpu = get_sys_info_by_name("hw.physicalcpu"); + if(physicalcpu < 8 || physicalcpu > 10) { + printBug("Found invalid physicalcpu: 0x%.8X", physicalcpu); + return NULL; + } + fill_cpu_info_firestorm_icestorm(cpu, physicalcpu-2, 2); + } + else { + printBug("Found invalid cpu_subfamily: 0x%.8X", cpu_subfamily); + return NULL; + } cpu->soc = get_soc(); - fill_cpu_info_firestorm_icestorm(cpu); cpu->peak_performance = get_peak_performance(cpu); } else { diff --git a/src/arm/soc.c b/src/arm/soc.c index 7484955..27a6d15 100644 --- a/src/arm/soc.c +++ b/src/arm/soc.c @@ -8,6 +8,10 @@ #include "udev.h" #include "../common/global.h" +#if defined(__APPLE__) || defined(__MACH__) + #include "sysctl.h" +#endif + #define min(a,b) (((a)<(b))?(a):(b)) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -642,6 +646,22 @@ struct system_on_chip* guess_soc_raspbery_pi(struct system_on_chip* soc) { return soc; } +#if defined(__APPLE__) || defined(__MACH__) +struct system_on_chip* guess_soc_apple(struct system_on_chip* soc) { + uint32_t cpu_subfamily = get_sys_info_by_name("hw.cpusubfamily"); + if(cpu_subfamily == CPUSUBFAMILY_ARM_HG) { + fill_soc(soc, "M1", SOC_APPLE_M1, 5); + } + else if(cpu_subfamily == CPUSUBFAMILY_ARM_HS) { + fill_soc(soc, "M1 Pro", SOC_APPLE_M1_PRO, 5); + } + else if(cpu_subfamily == CPUSUBFAMILY_ARM_HC_HD) { + fill_soc(soc, "M1 Max", SOC_APPLE_M1_MAX, 5); + } + return soc; +} +#endif + struct system_on_chip* get_soc() { struct system_on_chip* soc = emalloc(sizeof(struct system_on_chip)); soc->raw_name = NULL; @@ -675,7 +695,13 @@ struct system_on_chip* get_soc() { #endif // ifdef __ANDROID__ } #elif defined __APPLE__ || __MACH__ - fill_soc(soc, "M1", SOC_APPLE_M1, 5); + soc = guess_soc_apple(soc); + if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) { + printWarn("SoC detection failed using cpu_subfamily"); + } + else { + return soc; + } #endif // ifdef __linux__ if(soc->raw_name == NULL) { diff --git a/src/arm/socs.h b/src/arm/socs.h index 668c4f3..7632bc3 100644 --- a/src/arm/socs.h +++ b/src/arm/socs.h @@ -254,6 +254,8 @@ enum { SOC_SNAPD_SM8350, // APPLE SOC_APPLE_M1, + SOC_APPLE_M1_PRO, + SOC_APPLE_M1_MAX, // ALLWINNER SOC_ALLWINNER_A10, SOC_ALLWINNER_A13, @@ -286,9 +288,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_MTK_MT6893 && soc <= SOC_MTK_MT8783) return SOC_VENDOR_MEDIATEK; else if(soc >= SOC_SNAPD_QSD8650 && soc <= SOC_SNAPD_SM8350) return SOC_VENDOR_SNAPDRAGON; - else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M1) return SOC_VENDOR_APPLE; + else if(soc >= SOC_APPLE_M1 && soc <= SOC_APPLE_M1_MAX) return SOC_VENDOR_APPLE; else if(soc >= SOC_ALLWINNER_A10 && soc <= SOC_ALLWINNER_R328) return SOC_VENDOR_ALLWINNER; - return SOC_VENDOR_UNKNOWN; + return SOC_VENDOR_UNKNOWN; } #endif diff --git a/src/arm/sysctl.h b/src/arm/sysctl.h index 1140aec..716c143 100644 --- a/src/arm/sysctl.h +++ b/src/arm/sysctl.h @@ -1,6 +1,22 @@ #ifndef __SYSCTL__ #define __SYSCTL__ +// From Linux kernel: arch/arm64/include/asm/cputype.h +#define MIDR_APPLE_M1_ICESTORM 0x610F0220 +#define MIDR_APPLE_M1_FIRESTORM 0x610F0230 +#ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM + #define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3 +#endif +#ifndef CPUSUBFAMILY_ARM_HG + #define CPUSUBFAMILY_ARM_HG 2 +#endif +#ifndef CPUSUBFAMILY_ARM_HS + #define CPUSUBFAMILY_ARM_HS 4 +#endif +#ifndef CPUSUBFAMILY_ARM_HC_HD + #define CPUSUBFAMILY_ARM_HC_HD 5 +#endif + uint32_t get_sys_info_by_name(char* name); #endif