2022-11-21 22:26:50 +08:00
|
|
|
#include "cpu.h"
|
2023-02-23 21:31:33 +08:00
|
|
|
#include "detection/temps/temps_windows.h"
|
2022-11-26 12:55:48 +08:00
|
|
|
#include "util/windows/registry.h"
|
2022-11-23 15:10:40 +08:00
|
|
|
#include "util/mallocHelper.h"
|
2024-01-06 14:00:53 +08:00
|
|
|
#include "util/smbiosHelper.h"
|
2022-11-21 22:26:50 +08:00
|
|
|
|
2024-01-06 14:00:53 +08:00
|
|
|
// 7.5
|
|
|
|
|
typedef struct FFSmbiosProcessorInfo
|
|
|
|
|
{
|
|
|
|
|
FFSmbiosHeader Header;
|
|
|
|
|
|
|
|
|
|
uint8_t SocketDesignation; // string
|
|
|
|
|
uint8_t ProcessorType; // enum
|
|
|
|
|
uint8_t ProcessorFamily; // enum
|
|
|
|
|
uint8_t ProcessorManufacturer; // string
|
|
|
|
|
uint64_t ProcessorID; // varies
|
|
|
|
|
uint8_t ProcessorVersion; // string
|
|
|
|
|
uint8_t Voltage; // varies
|
|
|
|
|
uint16_t ExternalClock; // varies
|
|
|
|
|
uint16_t MaxSpeed; // varies
|
|
|
|
|
uint16_t CurrentSpeed; // varies
|
|
|
|
|
uint8_t Status; // varies
|
|
|
|
|
uint8_t ProcessorUpgrade; // enum
|
|
|
|
|
|
|
|
|
|
// 2.1+
|
|
|
|
|
uint16_t L1CacheHandle; // varies
|
|
|
|
|
uint16_t L2CacheHandle; // varies
|
|
|
|
|
uint16_t L3CacheHandle; // varies
|
|
|
|
|
|
|
|
|
|
// 2.3+
|
|
|
|
|
uint8_t SerialNumber; // string
|
|
|
|
|
uint8_t AssertTag; // string
|
|
|
|
|
uint8_t PartNumber; // string
|
|
|
|
|
|
|
|
|
|
// 2.5+
|
|
|
|
|
uint8_t CoreCount; // varies
|
|
|
|
|
uint8_t CoreEnabled; // varies
|
|
|
|
|
uint8_t ThreadCount; // varies
|
|
|
|
|
uint16_t ProcessorCharacteristics; // bit field
|
|
|
|
|
|
|
|
|
|
// 2.6+
|
|
|
|
|
uint16_t ProcessorFamily2; // enum
|
|
|
|
|
|
|
|
|
|
// 3.0+
|
|
|
|
|
uint16_t CoreCount2; // varies
|
|
|
|
|
uint16_t CoreEnabled2; // varies
|
|
|
|
|
uint16_t ThreadCount2; // varies
|
|
|
|
|
|
|
|
|
|
// 3.6+
|
|
|
|
|
uint16_t ThreadEnabled; // varies
|
|
|
|
|
} FFSmbiosProcessorInfo;
|
|
|
|
|
|
2024-04-27 23:05:36 +08:00
|
|
|
#if defined(__x86_64__) || defined(__i386__)
|
|
|
|
|
|
|
|
|
|
#include <cpuid.h>
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2024-01-06 18:00:59 +08:00
|
|
|
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
2024-01-06 14:00:53 +08:00
|
|
|
{
|
2024-01-06 14:46:54 +08:00
|
|
|
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
|
2024-01-06 14:00:53 +08:00
|
|
|
|
2024-01-06 14:46:54 +08:00
|
|
|
if (!data)
|
|
|
|
|
return "Processor information is not found in SMBIOS data";
|
|
|
|
|
|
|
|
|
|
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
|
2024-01-06 14:00:53 +08:00
|
|
|
{
|
2024-01-06 14:46:54 +08:00
|
|
|
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
|
|
|
|
|
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
|
2024-01-06 18:00:59 +08:00
|
|
|
return "No active CPU is found in SMBIOS data";
|
2024-01-06 14:46:54 +08:00
|
|
|
}
|
2024-01-06 14:00:53 +08:00
|
|
|
|
2024-04-21 17:57:32 +08:00
|
|
|
double speed = data->MaxSpeed / 1000.0;
|
|
|
|
|
// Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base
|
|
|
|
|
if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2)
|
|
|
|
|
return "Possible invalid CPU max speed in SMBIOS data. See #800";
|
2024-01-06 16:20:07 +08:00
|
|
|
|
2024-04-21 17:57:32 +08:00
|
|
|
cpu->frequencyMax = speed;
|
2024-01-06 14:00:53 +08:00
|
|
|
|
2024-01-06 14:46:54 +08:00
|
|
|
return NULL;
|
2024-01-06 14:00:53 +08:00
|
|
|
}
|
|
|
|
|
|
2024-03-12 23:48:03 +08:00
|
|
|
static const char* detectNCores(FFCPUResult* cpu)
|
2022-11-21 22:26:50 +08:00
|
|
|
{
|
2024-03-12 23:48:03 +08:00
|
|
|
DWORD length = 0;
|
|
|
|
|
GetLogicalProcessorInformationEx(RelationAll, NULL, &length);
|
|
|
|
|
if (length == 0)
|
|
|
|
|
return "GetLogicalProcessorInformationEx(RelationAll, NULL, &length) failed";
|
|
|
|
|
|
|
|
|
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* FF_AUTO_FREE
|
|
|
|
|
pProcessorInfo = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(length);
|
|
|
|
|
|
|
|
|
|
if (!pProcessorInfo || !GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length))
|
|
|
|
|
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
|
|
|
|
|
|
|
|
|
|
for(
|
|
|
|
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* ptr = pProcessorInfo;
|
|
|
|
|
(uint8_t*)ptr < ((uint8_t*)pProcessorInfo) + length;
|
|
|
|
|
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)(((uint8_t*)ptr) + ptr->Size)
|
|
|
|
|
)
|
2022-11-21 22:26:50 +08:00
|
|
|
{
|
2024-03-12 23:48:03 +08:00
|
|
|
if(ptr->Relationship == RelationProcessorCore)
|
|
|
|
|
++cpu->coresPhysical;
|
|
|
|
|
else if(ptr->Relationship == RelationGroup)
|
2022-11-21 22:26:50 +08:00
|
|
|
{
|
2024-03-12 23:48:03 +08:00
|
|
|
for (uint32_t index = 0; index < ptr->Group.ActiveGroupCount; ++index)
|
2022-11-21 22:26:50 +08:00
|
|
|
{
|
2024-03-12 23:48:03 +08:00
|
|
|
cpu->coresOnline += ptr->Group.GroupInfo[index].ActiveProcessorCount;
|
|
|
|
|
cpu->coresLogical += ptr->Group.GroupInfo[index].MaximumProcessorCount;
|
2022-11-21 22:26:50 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-12 23:48:03 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char* detectByRegistry(FFCPUResult* cpu)
|
|
|
|
|
{
|
2023-09-07 17:03:24 +08:00
|
|
|
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
2022-11-23 15:42:19 +08:00
|
|
|
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
2023-06-12 09:56:03 +08:00
|
|
|
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
2022-11-21 22:26:50 +08:00
|
|
|
|
2024-04-27 23:27:16 +08:00
|
|
|
if (detectSpeedByCpuid(cpu) != NULL || cpu->frequencyBase != cpu->frequencyBase)
|
2022-11-21 22:26:50 +08:00
|
|
|
{
|
|
|
|
|
uint32_t mhz;
|
2022-11-23 15:42:19 +08:00
|
|
|
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
2024-03-14 18:45:08 +08:00
|
|
|
cpu->frequencyBase = mhz / 1000.0;
|
2022-11-21 22:26:50 +08:00
|
|
|
}
|
|
|
|
|
|
2022-11-23 15:42:19 +08:00
|
|
|
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
|
|
|
|
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
2023-02-23 21:31:33 +08:00
|
|
|
|
2024-03-12 23:48:03 +08:00
|
|
|
if (cpu->coresLogical == 0)
|
|
|
|
|
{
|
|
|
|
|
DWORD cores;
|
|
|
|
|
if (RegQueryInfoKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", NULL, NULL, &cores, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
|
|
|
|
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 14:00:53 +08:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
|
|
|
|
{
|
2024-03-12 23:48:03 +08:00
|
|
|
detectNCores(cpu);
|
|
|
|
|
|
|
|
|
|
const char* error = detectByRegistry(cpu);
|
2024-01-06 18:00:59 +08:00
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
|
2024-04-27 23:27:16 +08:00
|
|
|
if (cpu->frequencyMax != cpu->frequencyMax)
|
2024-04-27 23:05:36 +08:00
|
|
|
detectMaxSpeedBySmbios(cpu);
|
2024-03-12 23:48:03 +08:00
|
|
|
|
2023-06-12 09:56:03 +08:00
|
|
|
if(options->temp)
|
2023-02-23 21:31:33 +08:00
|
|
|
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
2023-06-12 09:56:03 +08:00
|
|
|
|
2024-01-06 18:00:59 +08:00
|
|
|
return NULL;
|
2022-11-21 22:26:50 +08:00
|
|
|
}
|