CPUID

From Wikipedia, the free encyclopedia

Jump to: navigation, search

The CPUID opcode is a processor supplementary instruction (its name derived from CPU IDentification) for the x86 architecture. It was introduced by Intel in 1993 when it introduced the Pentium and SL-Enhanced 486 processors.[1]

By using the CPUID opcode, software can determine processor type and the presence of features (like MMX/SSE). The CPUID opcode is 0FA2h and the value in the EAX register specifies what information to return.

Prior to the general availability of the CPUID instruction, programmers would write esoteric machine code which exploited minor differences in CPU behavior in order to determine the processor make and model.[2][3]

Contents

[edit] Calling CPUID

In assembly language the CPUID instruction takes no parameters as CPUID implicitly uses the EAX register. The EAX register should be loaded with a value specifying what information to return. CPUID should be called with EAX = 0 first, as this will return the highest calling parameter that the CPU supports. To obtain extended function information CPUID should be called with bit 31 of EAX set. To determine the highest extended function calling parameter, call CPUID with EAX = 80000000h.

[edit] EAX=0: Get vendor ID

This returns the CPU's manufacturer ID string - a twelve character ASCII string stored in EBX, EDX, ECX - in that order. The highest basic calling parameter is returned in EAX.

The following are known processor manufacturer ID strings:

For instance, on a GenuineIntel processor values returned in EBX is 0x756e6547, EDX is 0x49656e69 and ECX is 0x6c65746e.

.section .data
s0: .string "Largest Standard Function Number Supported: %i\n"
s1: .string "Vendor ID: %s\n"
.text
 .global main
 
 .type main, @function
main:
 push rbp
 mov rbp, rsp
 
 sub rsp, 16
 xor eax, eax
 mov [rsp + 12], eax
 cpuid
 
 mov [rsp], ebx
 mov [rsp + 4], edx
 mov [rsp + 8], ecx
 mov edi, $s0
 mov esi, eax
 xor eax, eax
 call printf
 
 mov rdi, $s1
 mov rsi, rsp
 xor eax, eax
 call printf
 
 xor eax, eax
 mov rsp, rbp
 pop rbp
 ret

[edit] EAX=1: Processor Info and Feature Bits

This returns the CPU's stepping, model, and family information in EAX (also called the signature of a CPU), feature flags in EDX and ECX, and additional feature info in EBX.

The format of the information in EAX is as follows:

  • 3:0 - Stepping
  • 7:4 - Model
  • 11:8 - Family
  • 13:12 - Processor Type
  • 19:16 - Extended Model
  • 27:20 - Extended Family

Intel has suggested applications to display the family of a CPU as the sum of the "Family" and the "Extended Family" fields shown above, and the model as the sum of the "Model" and the 4-bit left-shifted "Extended Model" fields.[4]

AMD recommends the same only if "Family" or "Model" is equal to 15 (e.g. all bits set to 1). If "Family" is lower than 15, only "Family" field should be used while "Extended Family" bits are reserved. The same applies to "Model" and "Extended Model" fields [5].

The processor info and feature flags are manufacturer specific but usually the Intel values are used by other manufacturers for the sake of compatibility.

[edit] EAX=2: Cache and TLB Descriptor information

This returns a list of descriptors indicating cache and TLB capabilities in EAX, EBX, ECX and EDX registers.

[edit] EAX=3: Processor Serial Number

This returns the processor's serial number. The processor serial number was introduced on Intel Pentium III, but due to privacy concern, this feature is no longer implemented on later models (PSN feature bit is always cleared). Transmeta's Efficeon and Crusoe processors also provide this feature. AMD CPUs however, do not implement this feature in any CPU models.

For Intel Pentium III CPUs, the serial number is returned in EDX:ECX registers. For Transmeta Efficeon CPUs, it is returned in EBX:EAX registers. And for Transmeta Crusoe CPUs, it is returned in EBX register only.

Note that the processor serial number feature must be enabled in the BIOS setting in order to function.

[edit] EAX=80000000h: Get Highest Extended Function Supported

The highest calling parameter is returned in EAX.

[edit] EAX=80000001h: Extended Processor Info and Feature Bits

This returns extended feature flags in EDX and ECX.

[edit] EAX=80000002h,80000003h,80000004h: Processor Brand String

These return the processor brand string in EAX, EBX, ECX and EDX. CPUID must be issued with each parameter in sequence to get the entire 48-byte null-terminated ASCII processor brand string.

.section .data
s0: .string "Processor Brand String: %s\n"
.text
 .global main
 
 .type main, @function
main:
 pushq %rbp
 movq %rsp, %rbp
 
 subq $48, %rsp
 movl $0x80000002, %eax
 cpuid
 
 movl %eax, (%rsp)
 movl %ebx, 4(%rsp)
 movl %ecx, 8(%rsp)
 movl %edx, 12(%rsp)
 
 movl $0x80000003, %eax
 cpuid
 
 movl %eax, 16(%rsp)
 movl %ebx, 20(%rsp)
 movl %ecx, 24(%rsp)
 movl %edx, 28(%rsp)
 
 movl $0x80000004, %eax
 cpuid
 
 movl %eax, 32(%rsp)
 movl %ebx, 36(%rsp)
 movl %ecx, 40(%rsp)
 movl %edx, 44(%rsp)
 
 movl $s0, %edi
 movq %rsp, %rsi
 subl %eax, %eax
 call printf
 
 subl %eax, %eax
 movq %rbp, %rsp
 popq %rbp
 ret

[edit] EAX=80000005h: L1 Cache and TLB Identifiers

This function contains the processor’s L1 cache and TLB characteristics.

[edit] EAX=80000006h: Extended L2 Cache Features

Returns details of the L2 cache in ECX, including two different ways to express cache size and codes for cache associativity.

.section .data
s0: .string "L2 Cache: %iMB\n"
.text
 .global main
 
 .type main, @function
main:
 pushq %rbp
 movq %rsp, %rbp
 
 movl $0x80000006, %eax
 cpuid
 
 subl %edx, %edx
 movl %ecx, (%rsp)
 movl 2(%rsp), %eax
 movl $1024, %ecx
 divl %ecx
 
 movl $s0, %edi
 movl %eax, %esi
 subl %eax, %eax
 call printf
 
 subl %eax, %eax
 movq %rbp, %rsp
 popq %rbp
 ret

[edit] EAX=80000007h: Advanced Power Management Information

This function provides advanced power management feature identifiers.

[edit] EAX=80000008h: Virtual and Physical address Sizes

Returns largest virtual and physical address sizes in EAX.

[edit] Accessing the id from other languages

This information is easy to access from other languages as well. For instance, the C++ (gcc) code below prints the first five values, returned by the cpuid:

#include <iostream>
 
int main(int argc, char **argv) {
  int b;
  for (int a = 0; a < 5; a++) {
    asm ( "mov %1, %%eax; " // a into eax
          "cpuid;"
          "mov %%eax, %0;" // eeax into b
          :"=r"(b) /* output */
          :"r"(a) /* input */
          :"%eax" /* clobbered register */
         );
    std::cout << "The code " << a << " gives " << b << std::endl;
  }
}


Microsoft Visual C compiler has builtin function __cpuid() so cpuid instruction may be embedded without using inline assembly. This is handy since x64 version of MSVC doesn't allow inline assembly at all. The same program for MSVC would be:

#include <iostream>
#include <intrin.h>
 
int main(int argc, char **argv) {
  int b[4];
  for (int a = 0; a < 5; a++) {
    __cpuid(b,a);
    std::cout << "The code " << a << " gives " << b[0] << std::endl;
  }
}

[edit] See also

[edit] References

  1. ^ Intel 64 and IA-32 Architectures Software Developer’s Manual
  2. ^ Detecting Intel Processors -- Knowing the generation of a system CPU
  3. ^ http://lxr.linux.no/source/arch/i386/kernel/head.S?v=1.2.13#L92
  4. ^ http://download.intel.com/design/processor/applnots/24161832.pdf
  5. ^ http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf

[edit] External links