27 #include "precompiled.h"
51 size_t maxCoresPerPackage = 1;
60 maxCoresPerPackage =
bits(regs.
eax, 26, 31)+1;
64 regs.
eax = 0x80000008;
66 maxCoresPerPackage =
bits(regs.
ecx, 0, 7)+1;
73 return maxCoresPerPackage;
79 struct IsHyperthreadingCapable
81 bool operator()()
const
96 if(IsHyperthreadingCapable()())
102 const size_t logicalPerPackage =
bits(regs.
ebx, 16, 23);
105 ENSURE(logicalPerPackage % maxCoresPerPackage == 0);
106 const size_t maxLogicalPerCore = logicalPerPackage / maxCoresPerPackage;
107 return maxLogicalPerCore;
160 const size_t maxPackages = 256;
162 const size_t logicalWidth =
ceil_log2(maxLogicalPerCore);
163 const size_t coreWidth =
ceil_log2(maxCoresPerPackage);
164 const size_t packageWidth =
ceil_log2(maxPackages);
176 struct NumUniqueValuesInField
178 size_t operator()(
const ApicField& apicField)
const
180 std::bitset<os_cpu_MaxProcessors> values;
184 const size_t value = apicField(apicId);
187 return values.count();
199 size_t operator()(
size_t maxCoresPerPackage,
size_t maxLogicalPerCore)
const
204 const size_t maxLogicalPerPackage = maxCoresPerPackage*maxLogicalPerCore;
205 const size_t minPackagesPerNode =
DivideRoundUp(logicalPerNode, maxLogicalPerPackage);
213 const size_t minPackages = MinPackages()(maxCoresPerPackage, maxLogicalPerCore);
219 const size_t minCoresPerPackage =
DivideRoundUp(logicalPerPackage, maxLogicalPerCore);
220 for(
size_t coresPerPackage = maxCoresPerPackage; coresPerPackage >= minCoresPerPackage; coresPerPackage--)
222 if(logicalPerPackage % coresPerPackage != 0)
224 const size_t logicalPerCore = logicalPerPackage / coresPerPackage;
225 if(logicalPerCore <= maxLogicalPerCore)
285 size_t contiguousId = 0;
287 contiguousId += idxPackage;
291 contiguousId += idxCore;
295 contiguousId += idxLogical;
315 void Add(
u8 cacheId,
size_t processor)
323 cache->
Add(processor);
338 cachesProcessorMask[i] =
m_caches[i].ProcessorMask();
358 void Add(
size_t processor)
375 for(
size_t i = 0; i <
m_caches.size(); i++)
393 const u8 cacheIdMask =
u8((0xFF << numBits) & 0xFF);
397 const u8 cacheId =
u8(apicId & cacheIdMask);
398 cacheRelations.
Add(cacheId, processor);
406 const u8 cacheId = (
u8)processor;
407 cacheRelations.
Add(cacheId, processor);
418 for(
size_t cache = 0; cache <
numCaches; cache++)
421 const uintptr_t processorMask = cachesProcessorMask[cache];
422 for(
size_t processor = 0; processor < numProcessors; processor++)
424 if(
IsBitSet(processorMask, processor))
426 ENSURE(processorsCache[processor] == 0);
427 processorsCache[processor] = cache;
size_t CoreFromApicId(ApicId apicId)
void Add(size_t processor)
bool AreApicIdsReliable()
static CpuTopology cpuTopology
SharedCache * Find(u8 cacheId)
static size_t MaxLogicalPerCore()
T DivideRoundUp(T dividend, T divisor)
bool Matches(u8 cacheId) const
const x86_x64::Cache * Caches(size_t idxCache)
std::vector< SharedCache > m_caches
static const size_t os_cpu_MaxProcessors
maximum number of processors supported by the OS (determined by the number of bits in an affinity mas...
static size_t MaxLogicalPerCache()
static ModuleInitState cacheInitState
size_t PackageFromApicId(ApicId apicId)
static const size_t numCaches
static Status InitCpuTopology()
static size_t PopulationCount(T x)
static size_t MaxCoresPerPackage()
LIB_API uintptr_t numa_ProcessorMaskFromNode(size_t node)
size_t os_cpu_NumProcessors()
ApicId ApicIdFromProcessor(size_t processor)
size_t processorsCache[os_cpu_MaxProcessors]
ApicId ApicIdFromContiguousId(size_t contiguousId)
uintptr_t m_processorMask
size_t LogicalFromApicId(ApicId apicId)
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
intptr_t ModuleInitState
initialization state of a module (class, source file, etc.) must be initialized to zero (e...
bool cpuid(CpuidRegs *regs)
invoke CPUID instruction.
void StoreProcessorMasks(uintptr_t *cachesProcessorMask)
store topology in an array (one entry per cache) of masks representing the processors that share a ca...
size_t sharedBy
how many logical processors share this cache?
bool IsBitSet(T value, size_t index)
static void DetermineProcessorsCache(const uintptr_t *cachesProcessorMask, size_t numCaches, size_t *processorsCache, size_t numProcessors)
static Status InitCacheTopology()
ApicId ApicIdFromIndices(size_t idxLogical, size_t idxCore, size_t idxPackage)
size_t operator()(size_t bits) const
i64 Status
Error handling system.
size_t ContiguousIdFromApicId(ApicId apicId)
T bits(T num, size_t lo_idx, size_t hi_idx)
extract the value of bits hi_idx:lo_idx within num
const Status CPU_FEATURE_MISSING
#define DEBUG_WARN_ERR(status)
display the error dialog with text corresponding to the given error code.
static void DetermineCachesProcessorMask(uintptr_t *cachesProcessorMask, size_t &numCaches)
LIB_API size_t numa_NumNodes()
size_t ceil_log2(T x)
ceil(log2(x))
void Add(u8 cacheId, size_t processor)
add processor to the processor mask owned by cache identified by <id>
uintptr_t ProcessorMaskFromCache(size_t cache)
registers used/returned by cpuid
static CacheTopology cacheTopology
uintptr_t cachesProcessorMask[os_cpu_MaxProcessors]
static ModuleInitState cpuInitState
Status ModuleInit(volatile ModuleInitState *initState, Status(*init)())
calls a user-defined init function if initState is zero.
stores ID and tracks which processors share this cache
size_t CacheFromProcessor(size_t processor)
uintptr_t ProcessorMask() const