# 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:
janwas 2010-06-12 20:21:28 +00:00
parent 7eeacaab2d
commit 4fa5f1892b
3 changed files with 36 additions and 21 deletions

View File

@ -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
}
}
}

View File

@ -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(&regs))
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(&regs))
DEBUG_WARN_ERR(ERR::CPU_FEATURE_MISSING);
const u8 apicId = (u8)bits(regs.ebx, 24, 31);

View File

@ -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;