x86
Find it yourself in 4.1.3 x86 and the Intel manual
arch/x86/include/asm/cpufeature.h
contains the full list.
The define values are of type:
X*32 + Y
E.g.:
#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */
The features flags, extracted from CPUID, are stored inside the:
__u32 x86_capability[NCAPINTS + NBUGINTS];
field
- of
struct cpuinfo_x86 boot_cpu_data
- defined at
x86/kernel/setup.c
which is initialized through __init
functions.
Where each x86_capability
array element comes from:
| index | eax | ecx | output | file |
|-------|----------|-----|--------|-------------|
| 0 | 1 | 0 | edx | common.c |
| 1 | 80000001 | | edx | common.c |
| 2 | 80860001 | | edx | transmeta.c |
| 3 | | | | |
| 4 | 1 | 0 | ecx | common.c |
| 5 | C0000001 | | edx | centaur.c |
| 6 | 80000001 | | ecx | common.c |
| 7 | | | | scattered.c |
| 8 | | | | |
| 9 | 7 | 0 | ebx | common.c |
| 10 | D | 1 | eax | common.c |
| 11 | F | 0 | edx | common.c |
| 12 | F | 1 | edx | common.c |
Notes:
Conclusions:
most entries come directly from CPUID output registers and are set in common.c
by something like:
c->x86_capability[0] = edx;
Those are easy to find in batch on the Intel manual for CPUID.
the others are scattered throughout the source, and are set bit by bit with set_cpu_cap
.
To find them, use git grep X86_FEATURE_XXX
inside arch/x86
.
You can usually deduce what CPUID bit they correspond to from the surrounding code.
Other fun facts
The flags are actually printed at arch/x86/kernel/cpu/proc.c
with the code:
seq_puts(m, "flags\t\t:");
for (i = 0; i < 32*NCAPINTS; i++)
if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
seq_printf(m, " %s", x86_cap_flags[i]);
Where:
cpu_has
does the main check for the feature.
x86_cap_flags[i]
contains strings that correspond to each flags.
This gets passed as a callback to the proc
system setup. The entry point is at fs/proc/cpuinfo.c
.
x86_cap_flags
strings are generated by arch/x86/kernel/cpu/mkcapflags.h
directly from arch/x86/include/asm/cpufeature.h
by "parsing" it with sed
...
The output goes to arch/x86/kernel/cpu/capflags.c
of the build directory, and resulting array looks like:
const char * const x86_cap_flags[NCAPINTS*32] = {
[X86_FEATURE_FPU] = "fpu",
[X86_FEATURE_VME] = "vme",
so for example X86_FEATURE_FPU
corresponds to the string "fpu"
and so on.
cpu_has
breaks down into two cases with code:
#define cpu_has(c, bit) \
(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
test_cpu_cap(c, bit))
They are:
__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit)
: the flag is required for the kernel to run.
This is determined by data inside required-features.h
, which comments:
Define minimum CPUID feature set for kernel These bits are checked
really early to actually display a visible error message before the
kernel dies. Make sure to assign features to the proper mask!
Since those are known at compile time (kernel requirements), have already been checked at startup, the check can be resolved at compile time if bit
is known at compile time.
Thus the __builtin_constant_p(bit)
which checks if bit
is a compile time constant.
test_cpu_cap
: this uses up CPUID
data from the struct cpuinfo_x86 boot_cpu_data
global