From 63a0faa1d92837537c633fde523a837baab07e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 17 Jul 2024 15:51:15 +0800 Subject: [PATCH] GPU (macOS): support GPU frequency detection for Apple Silicon Also refactor CPU freq detection code --- src/detection/cpu/cpu_apple.c | 19 +++++++++------- src/detection/gpu/gpu_apple.c | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 20ef4a023..ad6852732 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -2,7 +2,6 @@ #include "common/sysctl.h" #include "detection/temps/temps_apple.h" #include "util/stringUtils.h" -#include "util/apple/cf_helpers.h" static double detectCpuTemp(const FFstrbuf* cpuName) { @@ -44,15 +43,19 @@ static const char* detectFrequency(FFCPUResult* cpu) if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) return "\"pmgr\" should conform to \"AppleARMIODevice\""; - FF_CFTYPE_AUTO_RELEASE CFDataRef pFreqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions); - if (CFGetTypeID(pFreqProperty) != CFDataGetTypeID()) + FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, kNilOptions); + if (CFGetTypeID(freqProperty) != CFDataGetTypeID()) return "\"voltage-states5-sram\" in \"pmgr\" is not found"; - // voltage-states5-sram stores supported frequencies of pcores from the lowest to the highest - CFIndex pCoreFreqLength = CFDataGetLength(pFreqProperty); - uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(pFreqProperty); - uint32_t pMax = 0; - for (CFIndex i = 0; i < pCoreFreqLength && pStart[i] > 0; i += 4) + // voltage-states5-sram stores supported pairs of pcores from the lowest to the highest + // voltage-states1-sram stores ecores' + CFIndex propLength = CFDataGetLength(freqProperty); + if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) + return "Invalid \"voltage-states5-sram\" length"; + + uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty); + uint32_t pMax = *pStart; + for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) pMax = pMax > pStart[i] ? pMax : pStart[i]; if (pMax > 0) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 6bc0ee48e..c63974d1f 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -36,6 +36,43 @@ static double detectGpuTemp(const FFstrbuf* gpuName) return result; } +#ifdef __aarch64__ +#include "util/apple/cf_helpers.h" + +#include + +static const char* detectFrequency(FFGPUResult* gpu) +{ + // https://github.com/giampaolo/psutil/pull/2222/files + + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr")); + if (!entryDevice) + return "IOServiceGetMatchingServices() failed"; + + if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice")) + return "\"pmgr\" should conform to \"AppleARMIODevice\""; + + FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states9-sram"), kCFAllocatorDefault, kNilOptions); + if (CFGetTypeID(freqProperty) != CFDataGetTypeID()) + return "\"voltage-states9-sram\" in \"pmgr\" is not found"; + + // voltage-states5-sram stores supported pairs of gpu from the lowest to the highest + CFIndex propLength = CFDataGetLength(freqProperty); + if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0) + return "Invalid \"voltage-states9-sram\" length"; + + uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty); + uint32_t pMax = *pStart; + for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */) + pMax = pMax > pStart[i] ? pMax : pStart[i]; + + if (pMax > 0) + gpu->frequency = pMax / 1000 / 1000; + + return NULL; +} +#endif + const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; @@ -94,6 +131,11 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->type = FF_GPU_TYPE_INTEGRATED; else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD) gpu->type = FF_GPU_TYPE_DISCRETE; + + #ifdef __aarch64__ + if (vendorStr == FF_GPU_VENDOR_NAME_APPLE) + detectFrequency(gpu); + #endif } gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET;