CPUID

CPUID is an assembler instruction to identify Intel compatible CPUs. Calling that instruction with register EAX set to 1 returns information about the CPU model in register EBX.

Processor Info and Feature Bits

EAX 31..28 15..14 13..12 27..20 11..8 19..16 7..4 3..0 Model Hosts
  res. res. P.Type Ext.Family Family Ext.Model Model Stepping    
000106a5       00000000 0110 0001 1010 0101 Intel(R) Xeon(R) CPU E5504 hejne, skepp
000106a5       00000000 0110 0001 1010 0101 Intel(R) Xeon(R) CPU E5506 frosta, smarta
000106a5       00000000 0110 0001 1010 0101 Intel(R) Xeon(R) CPU E5520 utby
000206c2       00000000 0110 0010 1010 0010 Intel(R) Xeon(R) CPU E5606 xen1
000206d7       00000000 0110 0010 1101 0111 Intel(R) Xeon(R) CPU E5-2620 krus
000306e4       00000000 0110 0011 1110 0100 Intel(R) Xeon(R) CPU E5-2650 v2 spoka
000306f2       00000000 0110 0011 1111 0010 Intel(R) Xeon(R) CPU E5-2620 lattjo, sparka
000806e9       00000000 0110 1000 1110 1001 Intel(R) Core(TM) i5-7200U CPU ivar

Extended Family is used instead of Family only if the later one if 15. Extended Model provides 4 additional upper bits for Model only if Family is 6 or 15.

The Linux kernel shows this in /proc/cpuinfo:

vendor_id	: GenuineIntel
cpu family	: 6
model		: 142
model name	: Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz
stepping	: 9
microcode	: 0x8e

Here is some C example code to decode the CPUID information on Linux:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <cpuid.h>

static void proc(void) {
  char buf[4 << 10];
  int fd = open("/proc/cpuinfo", O_RDONLY);
  if (fd < 0) {
    perror("open() failed");
    return;
  }
  while (1) {
    ssize_t nread = read(fd, buf, sizeof buf);
    if (nread == 0)
      break;
    if (nread < 0) {
      perror("read() failed");
      goto out;
    }
    char *begin, *end;
    for (begin = end = buf; end < buf + nread && *end; end++) {
      if (*end == '\n') {
        *end = '\0';
        if (!strncmp(begin, "model name  : ", 13)) {
          printf("%s\n", begin + 13);
          goto out;
        }
        begin = end + 1;
      }
    }
  }
out:
  if (close(fd)) {
    perror("close() failed");
    return;
  }
}

static void cpuid(void) {
  union {
    struct {
      uint8_t step: 4;
      uint8_t model: 4;
      uint8_t family: 4;
      uint8_t type: 2;
      uint8_t pad1: 2;
      uint8_t emodel: 4;
      uint8_t efamily: 8;
      uint8_t pad2: 4;
    };
    uint32_t reg;
  } eax;
  uint32_t ebx, ecx, edx;

  if (!__get_cpuid (1 /* Processor Info and Feature Bits */, &eax.reg, &ebx, &ecx, &edx))
    return;

  printf("EAX: %08x\nEBX: %08x\nECX: %08x\nEDX: %08x\n", eax.reg, ebx, ecx, edx);
  printf("stepping=%d model=%d|%d family=%d|%d ptype=%d\n", eax.step, eax.emodel, eax.model, eax.efamily, eax.family, eax.type);

  int model = eax.model, family = eax.family;
  if (eax.family >= 6)
      model |= eax.emodel << 4;
  if (eax.family == 15)
    family += eax.efamily;
  printf("model=%d family=%d\n", model, family);
}

int main(void) {
  cpuid();
  proc();
  return EXIT_SUCCESS;
}

http://www.sandpile.org/x86/cpuid.htm

Written on October 24, 2018