Geoff Chappell - Software Analyst
Among the output from executing the cpuid instruction with 0 in eax is a 12-character representation of the processor’s manufacturer. If what’s produced in ebx, edx and ecx are stored at successive memory locations, they read as a string of single-byte characters, hereafter termed the vendor string. The following vendor strings have at least some recognition by the Windows kernel:
Vendor String | Versions (x86) | Versions (x64) |
---|---|---|
GenuineIntel | 3.50 and higher | all |
AuthenticAMD | 3.50 and higher | all |
CyrixInstead | 4.0 and higher | |
GenuineTMx86 | 5.1 and higher | |
CentaurHauls | 5.1 and higher | 6.1 and higher |
RiseRiseRise | late 5.1; late 5.2 and higher |
|
HygonGenuine | 1803 and higher |
As usual the service packs that count above as late 5.1 and late 5.2 start with Windows XP SP2 and Windows Server 2003 SP1, respectively. For the x64 versions, “all” starts with late 5.2.
Microsoft’s disposition to manufacturers other than Intel and AMD is very different for 32-bit and 64-bit Windows. The latter has from the start insisted on processors from known vendors. If the 64-bit kernel detects a processor that has any vendor string other than listed above, it stops Windows with the bug check UNSUPPORTED_PROCESSOR (0x5D). The wonder is that anyone has even tried to make an x64-compatible processor, given that whatever they produce, whatever its quality, will forever be constrained only to future versions of the dominant operating system. Even for making an x86-compatible processor, the barrier is high. Although 32-bit Windows does not reject x86 processors from unknown vendors, it has a long and continuing history of recognising new features only on processors from Intel and AMD (and in some cases not even AMD).
As an aside, note that although CyrixInstead is not recognised by Windows as a cpuid vendor string until version 4.0, Cyrix is among the processor manufacturers who had Microsoft’s attention for version 3.50. It’s just not relevant to the table because before version 4.0 Windows does not give Cyrix a thought unless the processor is identified as some sort of 80486 with no cpuid instruction. That such a processor is made by Cyrix is recognised through configuration registers that are accessed through I/O ports 0x22 and 0x23. Configuration registers 0xFE and 0xFF are Device ID Registers that describe the processor much as do the family, model and stepping that the kernel learns for other processors through eax from cpuid leaf 1. Version 4.0 recognises more Device IDs and allows that the processors may have cpuid after all. Thereafter, the kernel’s code to recognise and configure these processors is retained almost unchanged until at least the 1803 release of Windows 10.
Although the kernel does in some cases repeat cpuid leaf 0 just to get the vendor string again, it mostly does not. All versions that look at all for a processor’s vendor string keep it in the processor’s control block (KPRCB):
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x0335 (3.50); 0x034D (3.51); 0x052D (4.0); 0x072D (5.0); 0x0900 (5.1); 0x0A78 (early 5.2); 0x0B60 (late 5.2); 0x1BAC (early 6.0); 0x1C2C (late 6.0); 0x0336C (6.1); 0x03C7C (6.2 to 6.3); 0x3CFC |
0x22B4 (late 5.2); 0x38BC (early 6.0); 0x399C (late 6.0); 0x4BB8 (6.1); 0x5948 (6.2); 0x5958 (6.3); 0x6258 (10.0 to 1607); 0x6358 (1703); 0x6290 |
UCHAR VendorString [13]; |
3.50 and higher |
See that the location varies greatly between versions and even between service packs. (Late 6.0 starts with Windows Vista SP1.) Access from outside the kernel is not known.
Of course, repeated comparison of the VendorString with the known strings for known vendors is inefficient. As early as version 4.0, the kernel started classifying the supported vendors and eventually started keeping this result in the KPRCB:
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x1BA8 (early 6.0); 0x1C28 (late 6.0); 0x03C4 (6.1 to 6.2); 0x03BE |
0x063D (late 5.2 to 1607); 0x8D |
UCHAR CpuVendor; |
6.0 and higher (x86); all (x64) |
The CpuVendor is significantly more stable within the KPRCB than is the VendorString. All versions of 64-bit Windows have it in the architectural section and version 6.1 moved it there for 32-bit Windows. As with much else that’s in the architectural section, the CpuVendor is shared with the HAL (at least).
Though the CpuVendor is formally a UCHAR, it takes values from an enumeration named CPU_VENDORS. This has different members in 32-bit and 64-bit Windows. Even for members that have the same name, the numerical value differs. Microsoft’s names for members of the 32-bit CPU_VENDORS are known from public symbol files in Windows 8 and higher (not just for the kernel but even for some user-mode modules). Some, but not all, are defined in the KS386.INC from the Windows Driver Kit (WDK) starting with Windows Vista. The 64-bit CPU_VENDORS seems never to have found its way into public symbol files. Microsoft’s names have, however, been published in NTOSP.H from the Enterprise WDK for Windows 10 Version 1511.
Value (x86) | Value (x64) | Name | Versions |
---|---|---|---|
0 | CPU_NONE | 4.0 and higher | |
0 | CPU_UNKNOWN | all | |
1 | CPU_INTEL | 4.0 and higher | |
2 | 1 | CPU_AMD | 4.0 and higher (x86); all (x64) |
2 | CPU_INTEL | all | |
3 | CPU_CYRIX | 4.0 and higher | |
4 | CPU_TRANSMETA | 5.1 and higher | |
5 | 3 | CPU_VIA | 5.1 and higher (x86); 6.1 and higher (x64) |
CPU_CENTAUR | 5.1 and higher | ||
6 | CPU_RISE | late 5.1; late 5.2 and higher |
|
4 | unknown | 1803 and higher | |
4 (5.0); 6 (early 5.1, early 5.2); 7 |
CPU_UNKNOWN | 5.0 and higher |
In 32-bit Windows, CPU_NONE means specifically that no vendor string is known, cpuid being absent or unusable. In 64-bit Windows, CPU_NONE means what CPU_UNKNOWN means in 32-bit Windows, i.e., that a vendor string is obtained but is not recognised. Though CPU_VIA and CPU_CENTAUR are established as aliases by symbol files for version 6.2 and higher, it is not known which, if not both, was in use in earlier versions. Microsoft’s name for the value (4) that represents the vendor string HygonGenuine is not known, though CPU_HYGON must be all but certain.
All versions of the Windows kernel save each processor’s vendor string in the registry:
Key: | HKEY_LOCAL_MACHINE\Hardware\Description\System\CentralProcessor\index |
Value: | VendorIdentifier |
Type: | REG_SZ |
Data: | null-terminated vendor string from cpuid leaf 0 |
This is true even of version 3.10. It doesn’t interpret the vendor string or keep it in the KPRCB. It gets the vendor string just to record it in the registry.
Generally, processors that do not have a usable cpuid instruction have no VendorIdentifier. The one exception is for Cyrix processors that have no cpuid instruction. For these, the kernel confects CyrixInstead as the VendorIdentifier to match what would have been set had the processor implemented cpuid.