1
0
forked from 0ad/0ad
avoid reporting a (not-present) third-level cache for Athlon X2 that
don't have one
add better documentation of cache information
ensure we're running on the same CPU while retrieving cache/TLB
descriptors
wgfx: always check all known graphics driver names (more robust in the
face of changing gfx_card strings), correct the intel driver name

This was SVN commit r8991.
This commit is contained in:
janwas 2011-02-26 19:22:02 +00:00
parent 567a698628
commit bb562ce179
5 changed files with 60 additions and 33 deletions

View File

@ -258,7 +258,7 @@ size_t x86_x64_Family()
// cache
static const size_t maxCacheLevels = 3;
static x86_x64_Cache cacheStorage[maxCacheLevels*2];
static x86_x64_Cache cacheStorage[maxCacheLevels*2]; // separate D and I hierarchies
static x86_x64_Caches dcaches = { 0, cacheStorage };
static x86_x64_Caches icaches = { 0, cacheStorage+maxCacheLevels };
@ -433,8 +433,13 @@ static void DetectCacheAndTLB()
icaches.numLevels = dcaches.numLevels = 2;
icaches.levels[1] = dcaches.levels[1] = L2Cache(regs.ecx, X86_X64_CACHE_TYPE_UNIFIED);
icaches.numLevels = dcaches.numLevels = 3;
icaches.levels[2] = dcaches.levels[2] = L3Cache(regs.edx, X86_X64_CACHE_TYPE_UNIFIED);
// (some Athlon 64 X2 models have no L3 cache, and it's better to report only 2 levels than
// have L3 type == NULL)
if(dcaches.levels[2].type != X86_X64_CACHE_TYPE_NULL)
{
icaches.numLevels = dcaches.numLevels = 3;
}
}
}
@ -487,6 +492,7 @@ static void DetectCache_CPUID4()
}
}
static void ExtractDescriptors(u32 reg, std::vector<u8>& descriptors)
{
if(IsBitSet(reg, 31)) // register contents are reserved
@ -529,8 +535,9 @@ static const u8 F = x86_x64_fullyAssociative;
#define PROPERTIES(descriptor, flags, assoc, entries) { flags, descriptor, assoc, entries }
// references: [accessed 2009-01-05]
// AP485 http://download.intel.com/design/processor/applnots/241618033.pdf
// (we only bother with TLB descriptors because CPUID.4 is a much easier way to detect the cache)
// references: [accessed 2011-02-26]
// AP485 http://www.intel.com/Assets/PDF/appnote/241618.pdf
// sandp http://www.sandpile.org/ia32/cpuid.htm
// opsol http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/i86pc/os/cpuid.c
static const Properties propertyTable[] =
@ -541,7 +548,7 @@ static const Properties propertyTable[] =
PROPERTIES(0x04, D|S4M, 4, 8),
PROPERTIES(0x05, D|S4M, 4, 32),
PROPERTIES(0x0B, I|S4M, 4, 4),
PROPERTIES(0x4F, I|S4K, F, 32), // sandp: unknown assoc, opsol: full, AP485: unmentioned
PROPERTIES(0x4F, I|S4K, F, 32), // sandp: unknown assoc, opsol: full, AP485: unspecified
PROPERTIES(0x50, I|S4K, F, 64),
PROPERTIES(0x50, I|S4M, F, 64),
PROPERTIES(0x50, I|S2M, F, 64),
@ -634,7 +641,11 @@ static void DecodeDescriptor(u8 descriptor)
static void DetectTLB_CPUID2()
{
// TODO: ensure we are pinned to the same CPU
// ensure consistency by pinning to a CPU.
// (don't use a hard-coded mask because process affinity may be restricted)
const uintptr_t allProcessors = os_cpu_ProcessorMask();
const uintptr_t firstProcessor = allProcessors & -intptr_t(allProcessors);
const uintptr_t prevAffinityMask = os_cpu_SetThreadAffinityMask(firstProcessor);
// extract descriptors
x86_x64_CpuidRegs regs = { 0 };
@ -656,6 +667,8 @@ static void DetectTLB_CPUID2()
debug_assert(ok);
}
os_cpu_SetThreadAffinityMask(prevAffinityMask);
for(std::vector<u8>::const_iterator it = descriptors.begin(); it != descriptors.end(); ++it)
{
const u8 descriptor = *it;

View File

@ -141,18 +141,32 @@ enum x86_x64_CacheType
// note: further values are "reserved"
};
const u8 x86_x64_fullyAssociative = 0xFF;
static const u8 x86_x64_fullyAssociative = 0xFF;
struct x86_x64_Cache
{
/**
* (used to determine if this cache is unified or disabled)
* if X86_X64_CACHE_TYPE_NULL, all other values are invalid.
**/
x86_x64_CacheType type;
/**
* equal to the index within x86_x64_Caches.levels[] + 1
**/
size_t level;
/**
* = x86_x64_fullyAssociative or the actual ways of associativity
**/
size_t associativity;
size_t lineSize; /// [bytes]
/**
* how many logical processors share this cache?
**/
size_t sharedBy;
size_t totalSize; /// [bytes]
};
@ -163,6 +177,9 @@ struct x86_x64_Cache
**/
struct x86_x64_Caches
{
/**
* equal to the highest value of x86_x64_Cache.level
**/
size_t numLevels;
x86_x64_Cache* levels;
};
@ -181,7 +198,7 @@ LIB_API size_t x86_x64_L1CacheLineSize();
LIB_API size_t x86_x64_L2CacheLineSize();
/**
* Translation Lookaside Buffer.
* Translation Lookaside Buffer. (documentation: see x86_x64_Cache)
**/
struct x86_x64_TLB
{

View File

@ -98,7 +98,7 @@ void wdll_ver_Append(const fs::wpath& pathname, std::wstring& list)
// read file version. try this with and without FS redirection since
// pathname might assume both.
wchar_t versionString[500] = L"unknown"; // enclosed in () below
wchar_t versionString[500]; // enclosed in () below
if(ReadVersionString(modulePathname, versionString, ARRAY_SIZE(versionString)) != INFO::OK)
{
WinScopedDisableWow64Redirection s;

View File

@ -169,26 +169,25 @@ static LibError AppendDriverVersionsFromRegistry(std::wstring& versionList)
return INFO::OK;
}
#include "lib/timer.h"
static LibError AppendDriverVersionsFromKnownFiles(std::wstring& versionList)
static void AppendDriverVersionsFromKnownFiles(std::wstring& versionList)
{
if(!wcsncmp(gfx_card, L"NVIDIA", 6))
{
wdll_ver_Append(L"nvoglv64.dll", versionList);
wdll_ver_Append(L"nvoglv32.dll", versionList);
wdll_ver_Append(L"nvoglnt.dll", versionList);
}
else if(!wcsncmp(gfx_card, L"ATI", 3))
{
wdll_ver_Append(L"atioglxx.dll", versionList);
}
else if(!wcsncmp(gfx_card, L"Intel", 5))
{
wdll_ver_Append(L"igxpdv32.dll", versionList);
}
else
return INFO::CANNOT_HANDLE;
return INFO::OK;
// (check all known file names regardless of gfx_card, which may change and
// defeat our parsing. this takes about 5..10 ms)
// NVidia
wdll_ver_Append(L"nvoglv64.dll", versionList);
wdll_ver_Append(L"nvoglv32.dll", versionList);
wdll_ver_Append(L"nvoglnt.dll", versionList);
// ATI
wdll_ver_Append(L"atioglxx.dll", versionList);
// Intel
wdll_ver_Append(L"ig4icd32.dll", versionList);
wdll_ver_Append(L"ig4icd64.dll", versionList);
wdll_ver_Append(L"iglicd32.dll", versionList);
}
@ -198,10 +197,9 @@ LibError win_get_gfx_info()
std::wstring versionList;
if(AppendDriverVersionsFromRegistry(versionList) != INFO::OK) // (fails on Windows 7)
{
if(AppendDriverVersionsFromKnownFiles(versionList) != INFO::OK)
versionList = L"(unknown)";
}
AppendDriverVersionsFromKnownFiles(versionList);
if(versionList.empty())
versionList = L"(unknown)";
wcscpy_s(gfx_drv_ver, GFX_DRV_VER_LEN, versionList.c_str());
return err;

View File

@ -107,7 +107,6 @@ LIB_API size_t os_cpu_MemoryAvailable();
/**
* restrict the current thread to a set of processors.
* it will not be rescheduled until affinity is again changed.
*
* @param processorMask a bit mask of acceptable processors
* (bit index i corresponds to processor i)