diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 792a9aaac..ded5e0d89 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -20,6 +20,77 @@ static double detectCpuTemp(const FFstrbuf* cpuName) return result; } +#ifdef __aarch64__ +#include "util/apple/cf_helpers.h" + +#include + +static const char* detectFrequency(FFCPUResult* cpu) +{ + // https://github.com/giampaolo/psutil/pull/2222/files + + CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice"); + if (matchDict == NULL) + return "IOServiceMatching(\"AppleARMIODevice\") failed"; + + io_iterator_t iterator; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + return "IOServiceGetMatchingServices() failed"; + + io_registry_entry_t registryEntry; + while((registryEntry = IOIteratorNext(iterator)) != 0) + { + CFMutableDictionaryRef properties; + if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) + { + IOObjectRelease(registryEntry); + continue; + } + + io_name_t name; + if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS) + continue; + if (strcmp(name, "pmgr") != 0) + continue; + + uint32_t pMin, eMin, aMax, pCoreLength; + ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore + ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore + cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000); + + if (pCoreLength >= 8) + { + ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL); + cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000); + } + else + cpu->frequencyMax = 0.0; + + CFRelease(properties); + IOObjectRelease(registryEntry); + } + + IOObjectRelease(iterator); + return NULL; +} +#else +static const char* detectFrequency(FFCPUResult* cpu) +{ + cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); + if(cpu->frequencyMax > 0.0) + cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; + else + { + unsigned current = 0; + size_t size = sizeof(current); + if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) + cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; + } + return NULL; +} +#endif + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) @@ -41,17 +112,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if(cpu->coresOnline == 1) cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1); - cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; - cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); - if(cpu->frequencyMax > 0.0) - cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; - else - { - unsigned current = 0; - size_t size = sizeof(current); - if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) - cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; - } + detectFrequency(cpu); cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET; diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 797b51b59..2ce563d5e 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -83,6 +83,27 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) return "TypeID is neither 'CFNumber' nor 'CFData'"; } +const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) +{ + CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); + if(cf == NULL) + return "CFDictionaryGetValue() failed"; + + if(CFGetTypeID(cf) != CFDataGetTypeID()) + return "TypeID is not 'CFData'"; + + CFIndex trueLength = CFDataGetLength((CFDataRef)cf); + + if(trueLength < offset + size) + return "Data length is less than offset + size"; + + if(length) + *length = (uint32_t) trueLength; + + CFDataGetBytes((CFDataRef)cf, CFRangeMake(offset, size), result); + return NULL; +} + const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result) { CFDictionaryRef cf = (CFDictionaryRef)CFDictionaryGetValue(dict, key); diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index 52755bb8b..a8d9804a3 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -11,6 +11,7 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result); const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result); const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result); const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result); +const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length); const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result); static inline CFNumberRef ffCfCreateInt(int value)