ohmu
·
2026-10-15
1#include "cpucache.h"
2#include "common/endian.h"
3#include "common/smbios.h"
4#include "common/strutil.h"
5
6typedef struct [[gnu::packed]] FFSmbiosCacheInfo {
7 FFSmbiosHeader Header;
8
9 uint8_t SocketDesignation; // string
10 uint16_t CacheConfiguration; // varies
11 uint16_t MaximumCacheSize; // varies
12 uint16_t InstalledSize; // varies
13 uint16_t SupportedSramType; // bit field
14 uint16_t CurrentSramType; // bit field
15
16 // 2.1+
17 uint8_t CacheSpeed; // varies
18 uint8_t ErrorCorrectionType; // enum
19 uint8_t SystemCacheType; // enum
20 uint8_t Associativity; // enum
21
22 // 3.1+
23 uint32_t MaximumCacheSize2; // bit field
24 uint32_t InstalledCacheSize2; // bit field
25} FFSmbiosCacheInfo;
26
27static_assert(offsetof(FFSmbiosCacheInfo, InstalledCacheSize2) == 0x17,
28 "FFSmbiosCacheInfo: Wrong struct alignment");
29
30const char* ffDetectCPUCache(FFCPUCacheResult* result) {
31 const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
32 if (!smbiosTable) {
33 return "Failed to get SMBIOS data";
34 }
35
36 const FFSmbiosCacheInfo* data = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_CACHE_INFO];
37 if (!data) {
38 return "Cache information is not found in SMBIOS data";
39 }
40
41 const FFSmbiosCacheInfo* endOfTable = (const FFSmbiosCacheInfo*) (*smbiosTable)[FF_SMBIOS_TYPE_END_OF_TABLE];
42 for (; data != endOfTable; data = (const FFSmbiosCacheInfo*) ffSmbiosNextEntry(&data->Header)) {
43 if (data->Header.Type != FF_SMBIOS_TYPE_CACHE_INFO) {
44 continue;
45 }
46
47 uint16_t cacheConfiguration = FF_READ_LE(data->CacheConfiguration);
48 uint16_t installedSize = FF_READ_LE(data->InstalledSize);
49 bool enabled = !!(cacheConfiguration & (1 << 7));
50 if (!enabled) {
51 continue;
52 }
53
54 uint32_t size = installedSize;
55 if (size == 0) {
56 continue;
57 }
58
59 if (installedSize != 0xFFFF) {
60 size *= (size >> 15 ? 64 : 1) * 1024u;
61 } else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) {
62 size = FF_READ_LE(data->InstalledCacheSize2);
63 size *= (size >> 31 ? 64 : 1) * 1024u;
64 }
65
66 uint32_t level = (cacheConfiguration & 0b111u) + 1;
67
68 FFCPUCacheType type;
69 switch (data->SystemCacheType) {
70 case 3:
71 type = FF_CPU_CACHE_TYPE_INSTRUCTION;
72 break;
73 case 4:
74 type = FF_CPU_CACHE_TYPE_DATA;
75 break;
76 default:
77 type = FF_CPU_CACHE_TYPE_UNIFIED;
78 break;
79 }
80
81 ffCPUCacheAddItem(result, level, size, 0, type);
82 }
83
84 return nullptr;
85}