forked from 0ad/0ad
# fix CPU detection issue
i3 CPUs report a *maximum* of 8 cores/package, which caused the number of processors to be misreported as 0 (but only because the APIC IDs were skipped because the CPU generation was deemed to low, which was due to failing to consider extended family/model) thanks to titanforever for reporting this. This was SVN commit r7626.
This commit is contained in:
parent
7eeacaab2d
commit
4fa5f1892b
@ -148,22 +148,28 @@ static const u8* ApicIds()
|
||||
|
||||
if(apicIds == uninitialized)
|
||||
{
|
||||
apicIds = 0; // return zero from now on unless the below succeeds
|
||||
apicIds = 0; // return zero from now on unless everything below succeeds
|
||||
|
||||
// requires xAPIC (see x86_x64_ApicId for details)
|
||||
if(x86_x64_Generation() >= 8)
|
||||
// store each processor's APIC ID in turn
|
||||
static u8 apicIdStorage[os_cpu_MaxProcessors];
|
||||
struct StoreApicId
|
||||
{
|
||||
// store each processor's APIC ID in turn
|
||||
static u8 apicIdStorage[os_cpu_MaxProcessors];
|
||||
struct StoreApicId
|
||||
static void Callback(size_t processor, uintptr_t UNUSED(cbData))
|
||||
{
|
||||
static void Callback(size_t processor, uintptr_t UNUSED(cbData))
|
||||
{
|
||||
apicIdStorage[processor] = x86_x64_ApicId();
|
||||
}
|
||||
};
|
||||
if(os_cpu_CallByEachCPU(StoreApicId::Callback, (uintptr_t)&apicIds) == INFO::OK)
|
||||
apicIds = apicIdStorage; // success, return valid array from now on
|
||||
apicIdStorage[processor] = x86_x64_ApicId();
|
||||
}
|
||||
};
|
||||
if(os_cpu_CallByEachCPU(StoreApicId::Callback, (uintptr_t)&apicIds) == INFO::OK)
|
||||
{
|
||||
const size_t numProcessors = os_cpu_NumProcessors();
|
||||
u8* end = std::unique(apicIdStorage, apicIdStorage+numProcessors);
|
||||
if(end == apicIdStorage+1) // exactly one unique value
|
||||
debug_assert(apicIdStorage[0]); // all 0 (no APIC supported)
|
||||
else
|
||||
{
|
||||
debug_assert(end == apicIdStorage+numProcessors); // all unique
|
||||
apicIds = apicIdStorage; // return valid array from now on
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,22 +175,28 @@ x86_x64_Vendors x86_x64_Vendor()
|
||||
}
|
||||
|
||||
|
||||
static void DetectSignature(size_t* model, size_t* family)
|
||||
static void DetectSignature(size_t& model, size_t& family)
|
||||
{
|
||||
x86_x64_CpuidRegs regs;
|
||||
regs.eax = 1;
|
||||
regs.ecx = 0;
|
||||
if(!x86_x64_cpuid(®s))
|
||||
DEBUG_WARN_ERR(ERR::CPU_FEATURE_MISSING);
|
||||
*model = bits(regs.eax, 4, 7);
|
||||
*family = bits(regs.eax, 8, 11);
|
||||
model = bits(regs.eax, 4, 7);
|
||||
family = bits(regs.eax, 8, 11);
|
||||
const size_t extendedModel = bits(regs.eax, 16, 19);
|
||||
const size_t extendedFamily = bits(regs.eax, 20, 27);
|
||||
if(family == 0xF)
|
||||
family += extendedFamily;
|
||||
if(family == 0xF || (x86_x64_Vendor() == X86_X64_VENDOR_INTEL && family == 6))
|
||||
model += extendedModel << 4;
|
||||
}
|
||||
|
||||
|
||||
static size_t DetectGeneration()
|
||||
{
|
||||
size_t model, family;
|
||||
DetectSignature(&model, &family);
|
||||
DetectSignature(model, family);
|
||||
|
||||
switch(x86_x64_Vendor())
|
||||
{
|
||||
@ -218,7 +224,7 @@ static size_t DetectGeneration()
|
||||
return 5; // Pentium
|
||||
|
||||
case 6:
|
||||
if(model <= 0xD)
|
||||
if(model < 0xF)
|
||||
return 6; // Pentium Pro/II/III/M
|
||||
else
|
||||
return 8; // Core2Duo
|
||||
@ -227,6 +233,8 @@ static size_t DetectGeneration()
|
||||
if(model <= 6)
|
||||
return 7; // Pentium 4/D
|
||||
}
|
||||
if(family >= 0x10)
|
||||
return 9;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -779,7 +787,7 @@ static void DetectIdentifierString(char* identifierString, size_t maxChars)
|
||||
if(!have_brand_string || strncmp(identifierString, "Unknow", 6) == 0)
|
||||
{
|
||||
size_t model, family;
|
||||
DetectSignature(&model, &family);
|
||||
DetectSignature(model, family);
|
||||
|
||||
switch(x86_x64_Vendor())
|
||||
{
|
||||
@ -849,8 +857,7 @@ u8 x86_x64_ApicId()
|
||||
regs.eax = 1;
|
||||
regs.ecx = 0;
|
||||
// note: CPUID function 1 should be available everywhere, but only
|
||||
// processors with an xAPIC (8th generation or above, e.g. P4/Athlon XP)
|
||||
// will return a nonzero value.
|
||||
// processors with an xAPIC (e.g. P4/Athlon XP) will return a nonzero value.
|
||||
if(!x86_x64_cpuid(®s))
|
||||
DEBUG_WARN_ERR(ERR::CPU_FEATURE_MISSING);
|
||||
const u8 apicId = (u8)bits(regs.ebx, 24, 31);
|
||||
|
@ -46,6 +46,7 @@ uintptr_t os_cpu_ProcessorMask()
|
||||
DWORD_PTR processAffinity, systemAffinity;
|
||||
const BOOL ok = GetProcessAffinityMask(hProcess, &processAffinity, &systemAffinity);
|
||||
debug_assert(ok);
|
||||
debug_assert(processAffinity != 0);
|
||||
processorMask = processAffinity;
|
||||
}
|
||||
|
||||
@ -65,6 +66,7 @@ size_t os_cpu_NumProcessors()
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si); // guaranteed to succeed
|
||||
debug_assert(numProcessors <= (size_t)si.dwNumberOfProcessors);
|
||||
debug_assert(numProcessors >= 1);
|
||||
}
|
||||
|
||||
return numProcessors;
|
||||
|
Loading…
Reference in New Issue
Block a user