8.1-PRERELEASE: CPU packages not detected correctly

Andriy Gapon avg at icyb.net.ua
Fri Aug 27 21:25:20 UTC 2010


on 27/08/2010 23:18 pluknet said the following:
> First, sorry for late replay, and thanks Andriy for kicking me ;)
> 
> Something really weird there .
> topo_probe_0xb() falls early on 1st iteration back to topo_probe_0x4().
> topo_probe_0x4() returns incorrect data as well.
> 
> topo_probe: cpu_high = b
> topo_probe: cpu_vendor_id = 8086
> topo_probe_0xb: i = 0, p[1] = 0
> topo_probe_0x4: cpu_procinfo = 200800
> topo_probe_0x4: cpu_logical = 32
> topo_probe_0x4: i = 0, type = 1
> topo_probe_0x4: i = 0, level = 1
> topo_probe_0x4: i = 0, logical = 1
> topo_probe_0x4: i = 0, cores = 16
> topo_probe_0x4: i = 1, type = 2
> topo_probe_0x4: i = 1, level = 1
> topo_probe_0x4: i = 1, logical = 1
> topo_probe_0x4: i = 1, cores = 16
> topo_probe_0x4: i = 2, type = 3
> topo_probe_0x4: i = 2, level = 2
> topo_probe_0x4: i = 2, logical = 1
> topo_probe_0x4: i = 2, cores = 16
> topo_probe#1: mp_ncpus = 3
> topo_probe#1: cpu_cores = 1
> topo_probe#1: cpu_logical = 32
> topo_probe#1: hyperthreading_cpus = 32
> topo_probe#2: mp_ncpus = 3
> topo_probe#2: cpu_cores = 1
> topo_probe#2: cpu_logical = 32
> topo_probe#2: hyperthreading_cpus = 32


My interpretation:

1. Current (unpatched) code reports correct results either by a chance or
because Jeff knows some magic patterns.
cpu_high (CPUID_Leaf_Max in Intel's lingo) is 0xb,
but CPUID.(EAX=11, ECX=0):EBX == 0,
which means that we should fallback to 0x4 method.
But the code doesn't do that and instead simply sets cpu_logical to 1 and
cpu_cores stays zero, which is later translated to mp_ncpus, which happens to
match the reality.

2. Intel reports correct results, because it properly probes the topology.
It binds to each of the logical processors available and checks their APIC IDs
against masks and builds topology info.

3. Patched code works incorrectly, because essentially it only calculates masks
for CPU (and cache, for some reason) topology building.  Instead of checking IDs
against those masks, the code assumes numbers of cores and threads are at their
maximum values allowed by the masks[*].  But that is not true and the numbers do
not add up and we get that strange incorrect result.

Things like that probably do not happen with real hardware much, but they could.
The only way to deal with this is by following the correct procedure instead of
making assumptions based on BSP.  But that may be hard.

[*] E.g. that page says:
CPUID.1:EBX[23:16] represents the maximum number of addressable IDs (initial
APIC ID) that can be assigned to logical processors in a physical package. The
value may not be the same as the number of logical processors that are present
in the hardware of a physical package. The value of (1 + (CPUID.(EAX=4,
ECX=0):EAX[31:26] )) represents the maximum number of addressable IDs (Core_ID)
that can be used to enumerate different processor cores in a physical package.
The value also can be different than the actual number of processor cores that
are present in the hardware of a physical package.

-- 
Andriy Gapon


More information about the freebsd-stable mailing list