LinuxAsmTools - HowTo read CPU information



Finding CPU information mini-HOWTO
jeff owens, jeff@linuxasmtools.net
v1.01, 06 April 2009

How to find CPU information.
______________________________________________________________________

Table of Contents

1. Disclaimer

2. Introduction

3. Why do we need CPU information?

4. How do we get CPU data?

5. Running the Example program

6. Compiling the example program

7. Finding more information
______________________________________________________________________

1. Disclaimer

The following document is offered in good faith as comprising only
safe programming and procedures. No responsibility is accepted by the
author for any loss or damage caused in any way to any person or
equipment, as a direct or indirect consequence of following these
instructions.


2. Introduction

The most recent version of this document can always be found at
https://thlorenz.com/linuxasmtools-net

The CPU (Central Processing Unit) is the engine that runs
a computer. Over the years this engine has changed and
grown in complexity. This howto describes the X86 family
of CPU's which is found in most comuters.

The sample program used here is built from two files: CPU.asm
and CPU.inc.


3. Why do we need CPU information?

The X86 family started with the 8086 processor and grew as
enhancements were added. Each processer added a few new
instructions that assembly programmers could utilize. When
these new instructions were used, the resulting programs
could not be run on older processors. Additionally, new
features were added to memory handling and modes of operation.

Today, the latest processors can run legacy code from the
8086, but older processors present problems for programmers.
Each program may need to check the CPU and decide it their
program is compatable.


4. How do we Get CPU data?

CPU data is obtained by executing the "cpuid" instruction
and others. By watching how the computer handles various
instructions we can determine the type of processor.

The code to do this can be lengthy, so most programmers
rely on libraries, programs, or other ways of obtaining
the information. On linux we have the /proc file system
which does the job. All we need to do is read /proc/cpuinfo
and we get something like this:

processor : 0
vendor_id : AuthenticAMD
cpu family : 6
model : 8
model name : AMD Athlon(tm) MP
stepping : 1
cpu MHz : 1050.092
cache size : 256 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 mmx fxsr sse syscall mp mmxext 3dnowext 3dnow up ts
bogomips : 2103.10
clflush size : 32

Next, we look at a sample program to read
/proc/cpuinfo.  The sample program consists
of two files which are available as cpu.asm and
cpu.inc


------------ start of source file cpu.asm ----------
extern crt_write
extern block_read_all
extern sys_exit

global _start,main
main:
_start:
mov ecx,cpu_msg ;message ptr
mov edx,cpu_msg_size ;message length
call crt_write ;kernel call

mov ebx,cpuinfo_path
mov ecx,buffer
mov edx,buffer_size
call block_read_all
or eax,eax
js sc_exit ;exit if error

mov edx,eax ;size to edx
mov ecx,buffer ;data ptr
call crt_write

sc_exit:
call sys_exit

;----------
[section .data]
cpuinfo_path: db '/proc/cpuinfo',0
cpu_msg:
incbin "cpu.inc"
cpu_msg_size equ $ - cpu_msg
[section .bss]

buffer resb 200
buffer_size equ $ - buffer

------------- end of source file cpu.asm ---------------

------------- start of source file cpu.inc -------------
The CPU is a computers engine. It executes all programs
after converting them to machine code. A computer can have
multiple cpu's (called multi core's) that work as a team.
When multiple cpu's are found, each one is described.

The following Information about the CPU is obtained from the
Linux proc file system at: /proc/cpuinfo
------------- end of source file cup.inc --------------

Some of the information we want is shown as flags (fpu vme de psc). To
decode these flags we can use the kernel include file cpufeatures_32.h.
See the links for more information. Here is the information from
the include:

/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */
#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */
#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */
#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */
#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */
#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */
#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */
#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */
#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */
#define X86_FEATURE_PN (0*32+18) /* Processor serial number */
#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */
#define X86_FEATURE_DS (0*32+21) /* Debug Store */
#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */
#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */
#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
/* of FPU context), and CR4.OSFXSR available */
#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */
#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */
#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */
#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */
#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */
#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */

/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
/* Don't duplicate feature flags which are redundant with Intel! */
#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */
#define X86_FEATURE_MP (1*32+19) /* MP Capable. */
#define X86_FEATURE_NX (1*32+20) /* Execute Disable */
#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */
#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */

/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */
#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */
#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */

/* Other features, Linux-defined mapping, word 3 */
/* This range is used for feature bits which conflict or are synthesized */
#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */
#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */
#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */
/* cpu types for specific tunings: */
#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */
#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */
#define X86_FEATURE_P3 (3*32+ 6) /* P3 */
#define X86_FEATURE_P4 (3*32+ 7) /* P4 */
#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
#define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */
#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
/* 14 free */
#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */

/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */
#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */
#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */
#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */
#define X86_FEATURE_CID (4*32+10) /* Context ID */
#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
#define X86_FEATURE_DCA (4*32+18) /* Direct Cache Access */

/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */
#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */
#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */
#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */
#define X86_FEATURE_ACE2 (5*32+ 8) /* Advanced Cryptography Engine v2 */
#define X86_FEATURE_ACE2_EN (5*32+ 9) /* ACE v2 enabled */
#define X86_FEATURE_PHE (5*32+ 10) /* PadLock Hash Engine */
#define X86_FEATURE_PHE_EN (5*32+ 11) /* PHE enabled */
#define X86_FEATURE_PMM (5*32+ 12) /* PadLock Montgomery Multiplier */
#define X86_FEATURE_PMM_EN (5*32+ 13) /* PMM enabled */

/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */
#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */

/*
* Auxiliary flags: Linux defined - For features scattered in various
* CPUID levels like 0x6, 0xA etc
*/
#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */


5. Running the example program.

The example program can be started with:

./cpu

To create a file with the CPU data use:

./cpu > file

6. Compiling the example program.

The example program can be compiled with the
following tools:

nasm - assembler
asmlib - library of assembler functions

The easy way to do this is to install, asmide
and start it as follows:

asmide cpu.asm

asmide will provide a menu, with compile and
debug options.

To manually compile the source use the following:

nasm -g -f elf cpu.asm
ld cpu.o -static -o cpu /usr/lib/asmlib.a

7. Finding more information

flag definitions can be found in linux source include
/usr/source/linux-headers.../include/asm-x86/cpufeature-32.h

The various processors and the cpuid instruction can be
researched at:

http://sandpile.org
http://www.x86.org
http://developer.intel.com
http://www.amd.com/support/techdocdir.html
http://www.cyrix.com/products/cyrindex.htm


Fork me on GitHub