CPUID: Difference between revisions

970 bytes added ,  26 days ago
m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(15 intermediate revisions by 7 users not shown)
Line 1:
The CPUID instruction can be used to retrieve various amount of information about your cpuCPU, likesuch as its vendor string and model number, the size of internal caches and (more interesting), the list of CPU features supported.
 
== How to use CPUID ==
Line 9:
This assembly routine checks if CPUID is supported:
 
<sourcesyntaxhighlight lang="asm">
pushfd ;Save EFLAGS
pushfd ;Store EFLAGS
Line 20:
and eax,0x00200000 ;eax = zero if ID bit can't be changed, else non-zero
ret
</syntaxhighlight>
</source>
 
Note 1: There are some old CPUs where CPUID is supported but the ID bit in EFLAGS is not (NexGen). TheThere are also CPUs that support CPUID if and only if it has to be enabled first (Cyrix M1).
 
Note 2: You can simply attempt to execute the CPUID instruction and see if you get an invalid opcode exception. This avoids problems with CPUs that do support CPUID but don't support the ID bit in EFLAGS; and is likely to be faster for CPUs that do support CPUID (and slower for CPUs that don't).
 
 
 
=== Basic usage ===
The idea of the CPUID instruction is that you can call it with different values in EAX, and it will return different information about the processor. For example, if we want the Vendor ID String (see below), we should code something like that:
 
<sourcesyntaxhighlight lang="asm">
mov eax, 0x0
cpuid
</syntaxhighlight>
</source>
 
There are differences between AMD and Intel. According to the Intel CPUID application note, we should first check the Vendor ID String for "GenuineIntel" before taking out information, such as the Processor Signature, Processor Feature Flags, etc.
Line 42 ⟶ 40:
When called with EAX = 0, CPUID returns the vendor ID string in EBX, EDX and ECX. Writing these to memory in this order results in a 12-character string. These can be tested against known Vendor ID strings:
 
<sourcesyntaxhighlight lang="c">
/*/ Vendor- strings. */from CPUs.
#define CPUID_VENDOR_AMD "AuthenticAMD"
#define CPUID_VENDOR_OLDAMDCPUID_VENDOR_AMD_OLD "AMDisbetter!" /*/ earlyEarly engineering samples of AMD K5 processor */
#define CPUID_VENDOR_AMD "AuthenticAMD"
#define CPUID_VENDOR_INTEL "GenuineIntel"
#define CPUID_VENDOR_VIA "CentaurHaulsVIA VIA VIA "
#define CPUID_VENDOR_OLDTRANSMETACPUID_VENDOR_TRANSMETA "TransmetaCPUGenuineTMx86"
#define CPUID_VENDOR_TRANSMETA CPUID_VENDOR_TRANSMETA_OLD "GenuineTMx86TransmetaCPU"
#define CPUID_VENDOR_CYRIX "CyrixInstead"
#define CPUID_VENDOR_CENTAUR "CentaurHauls"
#define CPUID_VENDOR_NEXGEN "NexGenDriven"
#define CPUID_VENDOR_UMC "UMC UMC UMC "
#define CPUID_VENDOR_SIS "SiS SiS SiS "
#define CPUID_VENDOR_NSC "Geode by NSC"
#define CPUID_VENDOR_RISE "RiseRiseRise"
#define CPUID_VENDOR_VORTEX "Vortex86 SoC"
#define CPUID_VENDOR_VIA CPUID_VENDOR_AO486 "VIA VIA VIAMiSTer AO486"
#define CPUID_VENDOR_AO486_OLD "GenuineAO486"
 
#define CPUID_VENDOR_ZHAOXIN " Shanghai "
/*Vendor-strings from Virtual Machines.*/
#define CPUID_VENDOR_VMWARECPUID_VENDOR_HYGON "VMwareVMwareHygonGenuine"
#define CPUID_VENDOR_XENHVMCPUID_VENDOR_ELBRUS "XenVMMXenVMME2K MACHINE "
#define CPUID_VENDOR_MICROSOFT_HV "Microsoft Hv"
/*/ Vendor- strings from Virtual Machineshypervisors.*/
#define CPUID_VENDOR_PARALLELS " lrpepyh vr"
#define CPUID_VENDOR_QEMU "TCGTCGTCGTCG"
 
#define CPUID_VENDOR_KVM " KVMKVMKVM "
</source>
#define CPUID_VENDOR_VMWARE "VMwareVMware"
#define CPUID_VENDOR_VIRTUALBOX "VBoxVBoxVBox"
#define CPUID_VENDOR_XEN "XenVMMXenVMM"
#define CPUID_VENDOR_MICROSOFT_HVCPUID_VENDOR_HYPERV "Microsoft Hv"
#define CPUID_VENDOR_PARALLELS " lrpepyhprl hyperv vr"
#define CPUID_VENDOR_PARALLELS_ALT " lrpepyh vr " // Sometimes Parallels incorrectly encodes "prl hyperv" as "lrpepyh vr" due to an endianness mismatch.
#define CPUID_VENDOR_BHYVE "bhyve bhyve "
#define CPUID_VENDOR_QNX " QNXQVMBSQG "
</syntaxhighlight>
You already know that the Vendor ID String is returned in EBX, ECX, EDX. Let us take an Intel processor. It should return "GenuineIntel". Look at the following text to see how the string is placed in the registers:
Line 87 ⟶ 94:
Recent processors also use ECX for features (which form a different set), with which you should be very careful as some old CPUs return bogus information in this register.
 
<sourcesyntaxhighlight lang="c">
enum {
CPUID_FEAT_ECX_SSE3 = 1 << 0,
Line 100 ⟶ 107:
CPUID_FEAT_ECX_SSSE3 = 1 << 9,
CPUID_FEAT_ECX_CID = 1 << 10,
CPUID_FEAT_ECX_SDBG = 1 << 11,
CPUID_FEAT_ECX_FMA = 1 << 12,
CPUID_FEAT_ECX_CX16 = 1 << 13,
CPUID_FEAT_ECX_ETPRDCPUID_FEAT_ECX_XTPR = 1 << 14,
CPUID_FEAT_ECX_PDCM = 1 << 15,
CPUID_FEAT_ECX_PCIDECPUID_FEAT_ECX_PCID = 1 << 17,
CPUID_FEAT_ECX_DCA = 1 << 18,
CPUID_FEAT_ECX_SSE4_1 = 1 << 19,
CPUID_FEAT_ECX_SSE4_2 = 1 << 20,
CPUID_FEAT_ECX_x2APICCPUID_FEAT_ECX_X2APIC = 1 << 21,
CPUID_FEAT_ECX_MOVBE = 1 << 22,
CPUID_FEAT_ECX_POPCNT = 1 << 23,
CPUID_FEAT_ECX_TSC = 1 << 24,
CPUID_FEAT_ECX_AES = 1 << 25,
CPUID_FEAT_ECX_XSAVE = 1 << 26,
CPUID_FEAT_ECX_OSXSAVE = 1 << 27,
CPUID_FEAT_ECX_AVX = 1 << 28,
CPUID_FEAT_ECX_F16C = 1 << 29,
CPUID_FEAT_ECX_RDRAND = 1 << 30,
CPUID_FEAT_ECX_HYPERVISOR = 1 << 31,
 
CPUID_FEAT_EDX_FPU = 1 << 0,
Line 134 ⟶ 146:
CPUID_FEAT_EDX_PSE36 = 1 << 17,
CPUID_FEAT_EDX_PSN = 1 << 18,
CPUID_FEAT_EDX_CLF CPUID_FEAT_EDX_CLFLUSH = 1 << 19,
CPUID_FEAT_EDX_DTESCPUID_FEAT_EDX_DS = 1 << 21,
CPUID_FEAT_EDX_ACPI = 1 << 22,
CPUID_FEAT_EDX_MMX = 1 << 23,
Line 143 ⟶ 155:
CPUID_FEAT_EDX_SS = 1 << 27,
CPUID_FEAT_EDX_HTT = 1 << 28,
CPUID_FEAT_EDX_TM1CPUID_FEAT_EDX_TM = 1 << 29,
CPUID_FEAT_EDX_IA64 = 1 << 30,
CPUID_FEAT_EDX_PBE = 1 << 31
};
</syntaxhighlight>
</source>
 
== Using CPUID from GCC ==
Line 153 ⟶ 165:
Alternatively, one can use the __get_cpuid function that comes with GCC. To use this function, include <cpuid.h>.
 
<sourcesyntaxhighlight lang="c">
#include <cpuid.h>
 
Line 168 ⟶ 180:
{
unsigned int eax, unused, edx;
__get_cpuid(1, &eax, &unused, &unused, %&edx);
return edx & CPUID_FEAT_EDX_APIC;
}
 
</syntaxhighlight>
</source>
 
{{Disputed}}
Line 178 ⟶ 190:
CPUID can be invoked with various request codes (in eax) and will return values in general registers (much as a built-in service interrupt). The following code is made Public Domain out of Clicker's x86/cpu.h
 
<sourcesyntaxhighlight lang="c">
/* DEPRECATED: You should use the <cpuid.h> header that comes with GCC instead. */
 
Line 209 ⟶ 221:
return (int)where[0];
}
</syntaxhighlight>
</source>
 
== See Also ==
Line 227 ⟶ 239:
 
[[Category:X86 CPU]]
[[Category:Hardware Detection]]
[[de:CPUID]]