Some notes on Intel's CPUID and how to get it for your CPUs
In things like Intel's MDS security advisory, Intel likes to identify CPU families with what they call a 'CPUID', which is a hex number. For example, the CPUID of the Sandy Bridge Xeon E5 'Server Embedded' product family is listed by Intel as 206D7, the CPUID of the Westmere Xeon E7 family is 206F2, and the CPUID of the Ivy Bridge Xeon E7 v2 family is 306E7. Given that one of these families has a microcode update theoretically available, one of them is supposed to get it sometime, and one will not get a microcode update, it has become very useful to be able to find out the CPUID of your Intel processors (especially given Intel's confusing Xeon names).
On x86 CPUs, this information comes from the CPU via the CPUID
instruction, which provides
all sorts of information (including the brand name of the processor
itself,
which the processor directly provides in ASCII). Specifically, it
is the 'processor version information' that you get from using CPUID
to query the Processor Info and Feature Bits.
Many things will tell you this information, for example Linux's
/proc/cpuinfo
and lscpu
, but they decode what it represents to
give you the CPU family, model, and stepping (using a complicated
algorithm that is covered in that Wikipedia entry on CPUID). Intel's
'CPUID' is it directly in hex, and I don't know if you can reliably
reverse a given family/model/stepping triplet into the definite
CPUID (I haven't tried to do it).
(Intel's MDS PDF also lists a two-hex-digit 'Platform ID'. I don't know where this comes from or how you find out what yours is. I thought I found some hints, but they don't appear to give the right answer on my test machine.)
There are a variety of ways to get the Intel CPUID in raw hex. The
most brute force method and perhaps the simplest is to write a
program that uses the CPUID
instruction to get this. Keen people
can use C with inline assembly, but I used Go with a third party
package for this
that I found through the obvious godoc.org search:
package mainimport ( "fmt" "sigs.k8s.io/node-feature-discovery/pkg/cpuid" ) func main() { r := cpuid.Cpuid(0x01, 0x00) fmt.Printf("cpuid: %x\n", r.EAX) }
This has the great benefit of Go for busy sysadmins; it compiles to a static binary that will run on any machine regardless of what packages you have installed, and you can pretty much cross-compile it for other Unixes if you need to (at least 64-bit x86 Unixes; people with 32-bit x86 Unixes are out of luck here without some code changes, but this package may help).
(Intel also has a CPUID package for Go, but it wants to decode this information instead of just give it to you literally so you can print the hex that Intel uses in its documentation. I wish Intel's left hand would talk to its right hand here.)
On Linux machines, you may have the cpuid program available as a package, and I believe it's also in FreeBSD ports in the sysutils section (and FreeBSD has another 'cpuid' program that I know nothing about). Cpuid normally decodes this information, as everything does, but you can get it to dump the raw information and then read out the one field of one line you care about, which is the 'eax' field in the line that starts with '0x00000001':
; cpuid -1 -r CPU: 0x00000000 0x00: eax=0x00000016 ebx=0x756e6547 ecx=0x6c65746e edx=0x49656e69 0x00000001 0x00: eax=0x000906ea ebx=0x04100800 ecx=0x7ffafbff edx=0xbfebfbff [...]
(This is my home machine, and the eax of 0x000906ea matches the CPUID of 906EA that Intel's MDS PDF says that an i7-8700K should have.)
Perhaps you see why I think a Go program is simpler and easier.
Comments on this page:
|
|