From 81fb1468699491d301013294113fd90a0105a840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 27 Apr 2024 23:05:36 +0800 Subject: [PATCH] CPU (Windows): detect max CPU freq with `CPUID` instruction Note this only works when Hyper-V is not enabled Ultimately fixes #800 #812 #815 --- src/detection/cpu/cpu_windows.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 2a8b69bfb..534ec74b4 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -50,6 +50,31 @@ typedef struct FFSmbiosProcessorInfo uint16_t ThreadEnabled; // varies } FFSmbiosProcessorInfo; +#if defined(__x86_64__) || defined(__i386__) + +#include + +inline static const char* detectSpeedByCpuid(FFCPUResult* cpu) +{ + uint32_t base = 0, max = 0, bus = 0, unused = 0; + if (!__get_cpuid(0x16, &base, &max, &bus, &unused)) + return "Unsupported instruction"; + + // cpuid returns 0 MHz when hyper-v is enabled + if (base) cpu->frequencyBase = base / 1000.0; + if (max) cpu->frequencyMax = max / 1000.0; + return NULL; +} + +#else + +inline static const char* detectSpeedByCpuid(FFCPUResult* cpu) +{ + return "Unsupported platform"; +} + +#endif + static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) { const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO]; @@ -114,6 +139,7 @@ static const char* detectByRegistry(FFCPUResult* cpu) if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed"; + if (detectSpeedByCpuid(cpu) == NULL && cpu->frequencyBase == 0) { uint32_t mhz; if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL)) @@ -141,7 +167,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (error) return error; - detectMaxSpeedBySmbios(cpu); + if (cpu->frequencyMax == 0) + detectMaxSpeedBySmbios(cpu); if(options->temp) ffDetectSmbiosTemp(&cpu->temperature, NULL);