diff --git a/src/detection/cpucache/cpucache.h b/src/detection/cpucache/cpucache.h index 567c6e21f..3d42acfd3 100644 --- a/src/detection/cpucache/cpucache.h +++ b/src/detection/cpucache/cpucache.h @@ -24,7 +24,7 @@ typedef struct FFCPUCacheResult const char* ffDetectCPUCache(FFCPUCacheResult* result); -static inline void ffCPUCacheAddItem(FFCPUCacheResult* result, uint32_t level, uint32_t size, FFCPUCacheType type) +static inline FFCPUCache* ffCPUCacheAddItem(FFCPUCacheResult* result, uint32_t level, uint32_t size, FFCPUCacheType type) { FFlist* cacheLevel = &result->caches[level - 1]; @@ -33,12 +33,15 @@ static inline void ffCPUCacheAddItem(FFCPUCacheResult* result, uint32_t level, u if (item->type == type && item->size == size) { item->num++; - return; + return item; } } - *(FFCPUCache*) ffListAdd(cacheLevel) = (FFCPUCache) { + + FFCPUCache* item = (FFCPUCache*)ffListAdd(cacheLevel); + *item = (FFCPUCache) { .size = size, .num = 1, .type = type, }; + return item; } diff --git a/src/detection/cpucache/cpucache_apple.c b/src/detection/cpucache/cpucache_apple.c new file mode 100644 index 000000000..1505ac9b7 --- /dev/null +++ b/src/detection/cpucache/cpucache_apple.c @@ -0,0 +1,55 @@ +#include "cpucache.h" +#include "common/sysctl.h" + +const char* ffDetectCPUCache(FFCPUCacheResult* result) +{ + // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_system_capabilities#3901385 + uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0); + if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed"; + + char sysctlKey[256] = "hw.perflevelN."; + char* pNum = sysctlKey + strlen("hw.perflevel"); + char* pSubkey = sysctlKey + strlen("hw.perflevelN."); + const size_t lenLeft = sizeof(sysctlKey) - strlen("hw.perflevelN."); + + for (uint32_t i = 0; i < nPerfLevels; ++i) + { + *pNum = (char) ('0' + i); + + strncpy(pSubkey, "physicalcpu", lenLeft); + uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (ncpu <= 0) continue; + + strncpy(pSubkey, "l1icachesize", lenLeft); + uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (size) + ffCPUCacheAddItem(result, 1, size, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu; + + strncpy(pSubkey, "l1dcachesize", lenLeft); + size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (size) + ffCPUCacheAddItem(result, 1, size, FF_CPU_CACHE_TYPE_DATA)->num = ncpu; + + strncpy(pSubkey, "l2cachesize", lenLeft); + size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (size) + { + strncpy(pSubkey, "cpusperl2", lenLeft); + uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (cpuSper) + ffCPUCacheAddItem(result, 2, size, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; + } + + strncpy(pSubkey, "l3cachesize", lenLeft); + size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (size) + { + strncpy(pSubkey, "cpusperl3", lenLeft); + uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); + if (cpuSper) + ffCPUCacheAddItem(result, 3, size, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; + } + } + + return NULL; +}