From edf24d982023a7e6a05a48a2b31be54de3b916a5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Jun 2024 15:21:55 +0800 Subject: [PATCH] CPUCache: add detection by SMBIOS --- CMakeLists.txt | 4 +- src/detection/battery/battery_windows.c | 2 +- src/detection/cpucache/cpucache_shared.c | 75 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/detection/cpucache/cpucache_shared.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e6388cf2d..fa526f990 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -549,7 +549,7 @@ elseif(BSD) src/detection/brightness/brightness_bsd.c src/detection/chassis/chassis_bsd.c src/detection/cpu/cpu_bsd.c - src/detection/cpucache/cpucache_nosupport.c + src/detection/cpucache/cpucache_shared.c src/detection/cpuusage/cpuusage_bsd.c src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c @@ -749,7 +749,7 @@ elseif(SunOS) src/detection/brightness/brightness_nosupport.c src/detection/chassis/chassis_windows.c src/detection/cpu/cpu_sunos.c - src/detection/cpucache/cpucache_nosupport.c + src/detection/cpucache/cpucache_shared.c src/detection/cpuusage/cpuusage_sunos.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_nosupport.c diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 1d507c8c6..6c7298231 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -172,7 +172,7 @@ typedef struct FFSmbiosPortableBattery static_assert(offsetof(FFSmbiosPortableBattery, OEMSpecific) == 0x16, "FFSmbiosPortableBattery: Wrong struct alignment"); -const char* detectBySmbios(FFBatteryResult* battery) +static const char* detectBySmbios(FFBatteryResult* battery) { const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); if (!smbiosTable) diff --git a/src/detection/cpucache/cpucache_shared.c b/src/detection/cpucache/cpucache_shared.c new file mode 100644 index 000000000..abf0e9474 --- /dev/null +++ b/src/detection/cpucache/cpucache_shared.c @@ -0,0 +1,75 @@ +#include "cpucache.h" +#include "util/smbiosHelper.h" +#include "util/stringUtils.h" + +typedef struct FFSmbiosCacheInfo +{ + FFSmbiosHeader Header; + + uint8_t SocketDesignation; // string + uint16_t CacheConfiguration; // varies + uint16_t MaximumCacheSize; // varies + uint16_t InstalledSize; // varies + uint16_t SupportedSramType; // bit field + uint16_t CurrentSramType; // bit field + + // 2.1+ + uint8_t CacheSpeed; // varies + uint8_t ErrorCorrectionType; // enum + uint8_t SystemCacheType; // enum + uint8_t Associativity; // enum + + // 3.1+ + uint32_t MaximumCacheSize2; // bit field + uint32_t InstalledCacheSize2; // bit field +} __attribute__((__packed__)) FFSmbiosCacheInfo; + +static_assert(offsetof(FFSmbiosCacheInfo, InstalledCacheSize2) == 0x17, + "FFSmbiosCacheInfo: Wrong struct alignment"); + +const char* ffDetectCPUCache(FFCPUCacheResult* result) +{ + const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); + if (!smbiosTable) + return "Failed to get SMBIOS data"; + + const FFSmbiosCacheInfo* data = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_CACHE_INFO]; + if (!data) + return "Cache information is not found in SMBIOS data"; + + for (; data->Header.Type == FF_SMBIOS_TYPE_CACHE_INFO; + data = (const FFSmbiosCacheInfo*) ffSmbiosNextEntry(&data->Header)) + { + bool enabled = !!(data->CacheConfiguration & (1 << 7)); + if (!enabled) + continue; + + uint32_t size = data->InstalledSize; + if (size == 0) + continue; + + if (data->InstalledSize != 0xFFFF) + { + size *= (size >> 15 ? 64 : 1) * 1024u; + } + else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) + { + size = data->InstalledCacheSize2; + size *= (size >> 31 ? 64 : 1) * 1024u; + } + + uint32_t level = (data->CacheConfiguration & 0b111u) + 1; + + FFCPUCacheType type; + switch (data->SystemCacheType) + { + case 3: type = FF_CPU_CACHE_TYPE_INSTRUCTION; break; + case 4: type = FF_CPU_CACHE_TYPE_DATA; break; + default: type = FF_CPU_CACHE_TYPE_UNIFIED; break; + } + + ffCPUCacheAddItem(result, level, size, 0, type); + } + + return NULL; +}