Skip to content

Conversation

@dlenski
Copy link
Contributor

@dlenski dlenski commented Nov 21, 2025

(This PR also includes #349, but I can factor that out if preferred.)

As Intel puts it: "CPUID, by design, returns different values depending on the core it is executed on" (see https://www.intel.com/content/www/us/en/developer/articles/guide/12th-gen-intel-core-processor-gamedev-guide.html#inpage-nav-1-5-2:~:text=CPUID%2C%20by%20design%2C%20returns%20different%20values%20depending%20on%20the%20core%20it%20is%20executed%20on)

In particular, leaves 1, 4, 0x0b, 0x1a, and 0x1f are known to vary by core. Leaf 0x1a differentiates core types on hybrid CPUs

In order to aid in exploration of CPUID contents, cpuid-dump should dump CPUID results from all CPUs, rather than just one. This is currently implemented for Linux only, using the sched_setaffinity(2) system call.

Per https://en.wikipedia.org/wiki/CPUID#EAX=4000'0000h-4FFFF'FFFh:_Reserved_for_Hypervisors:

> CPUID leaves 40000000h to 4FFFFFFFh are not implemented in hardware, and
> are reserved for use by hypervisors to provide hypervisor-specific
> identification and feature information through this interception
> mechanism.
>
> For leaf 40000000h, the hypervisor is expected to return the index of the
> highest supported hypervisor CPUID leaf in EAX, and a 12-character
> hypervisor ID string in EBX,ECX,EDX (in that order).  For leaf 40000001h,
> the hypervisor may return an interface identification signature in EAX -
> e.g. hypervisors that wish to advertise that they are Hyper-V compatible
> may return 0x31237648—"Hv#1" in EAX.

For example, running with user-mode QEMU:

```
$ qemu-x86_64 cpuid-dump
…
CPUID 40000000: 40000001-54474354-43544743-47435447 [TCGTCGTCGTCG]
CPUID 40000001: 00000000-00000000-00000000-00000000
…
```

Running under a recent version of WSL2 (Microsoft Hyper-V):
```
$ cpuid-dump
…
CPUID 40000000: 4000000B-7263694D-666F736F-76482074 [Microsoft Hv]
CPUID 40000001: 31237648-00000000-00000000-00000000 [Hv#1]
…
CPUID 4000000B: 00000000-00000000-00000000-00000000
```
Per Intel's April 2023 documentation
(https://cdrdv2-public.intel.com/775917/intel-64-architecture-processor-topology-enumeration.pdf):

> The extended topology enumeration leaf of CPUID (leaf 0BH) was introduced
> in 2009 along with the x2APIC IDs.  This leaf has been superseded by the
> v2 extended topology enumeration leaf (CPUID leaf 1FH), which is the
> preferred interface for system topology enumeration for current Intel 64
> processors
As Intel puts it: "CPUID, by design, returns different values depending on
the core it is executed on"
(see https://www.intel.com/content/www/us/en/developer/articles/guide/12th-gen-intel-core-processor-gamedev-guide.html#inpage-nav-1-5-2:~:text=CPUID%2C%20by%20design%2C%20returns%20different%20values%20depending%20on%20the%20core%20it%20is%20executed%20on)

In particular, leaves 1, 4, 0x0b, 0x1a, and 0x1f are known to vary by core.
Leaf 0x1a differentiates core types on hybrid CPUs.

In order to aid in exploration of CPUID contents, `cpuid-dump` should dump
CPUID results from *all* CPUs, rather than just one.  This is currently
implemented for Linux only, using the `sched_setaffinity(2)` system call.
@meta-cla meta-cla bot added the cla signed label Nov 21, 2025
@dlenski
Copy link
Contributor Author

dlenski commented Nov 21, 2025

The results can be easily deduplicated by piping through sort and uniq. For example:

./cpuid-dump | sort -sk6 -sk3 -sk1 | uniq -s4
cpu0: CPUID 00000000: 00000023-756E6547-6C65746E-49656E69 [GenuineIntel]
…
# High byte of EBX identifies each core's ID
#                               |
cpu0: CPUID 00000001: 000B06D1-00800800-FFFAF38B-BFCBFBFF
cpu1: CPUID 00000001: 000B06D1-08800800-FFFAF38B-BFCBFBFF
cpu2: CPUID 00000001: 000B06D1-10800800-FFFAF38B-BFCBFBFF
cpu3: CPUID 00000001: 000B06D1-18800800-FFFAF38B-BFCBFBFF
cpu4: CPUID 00000001: 000B06D1-40800800-FFFAF38B-BFCBFBFF
cpu5: CPUID 00000001: 000B06D1-42800800-FFFAF38B-BFCBFBFF
cpu6: CPUID 00000001: 000B06D1-44800800-FFFAF38B-BFCBFBFF
cpu7: CPUID 00000001: 000B06D1-46800800-FFFAF38B-BFCBFBFF
…
# High bytes of EAX indicates that cpu[0-3] are P-cores, and cpu[4-7] are E-cores
# The rest of EAX contains the "native model ID" (https://codebrowser.dev/linux/linux/arch/x86/include/asm/intel-family.h.html#intel_native_id)
cpu0: CPUID 0000001A: 40000003-00000000-00000000-00000000
cpu4: CPUID 0000001A: 20000003-00000000-00000000-00000000

This topology enumeration process is very complex
(https://web.archive.org/web/20160306203252/https://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration)
and easy to get wrong.

We have to rely on the operating system to allow us to switch CPUs, so we
may as well rely on it to *count* CPUs as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant