master ohmu/fastfetch-openbsd / src / detection / cpucache / cpucache_shared.c
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}