Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/cpufeatures: Generate the <asm/cpufeaturemasks.h> header based on build config

Introduce an AWK script to auto-generate the <asm/cpufeaturemasks.h> header
with required and disabled feature masks based on <asm/cpufeatures.h>
and the current build config.

Thus for any CPU feature with a build config, e.g., X86_FRED, simply add:

config X86_DISABLED_FEATURE_FRED
def_bool y
depends on !X86_FRED

to arch/x86/Kconfig.cpufeatures, instead of adding a conditional CPU
feature disable flag, e.g., DISABLE_FRED.

Lastly, the generated required and disabled feature masks will be added to
their corresponding feature masks for this particular compile-time
configuration.

[ Xin: build integration improvements ]
[ mingo: Improved changelog and comments ]

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250305184725.3341760-3-xin@zytor.com

authored by

H. Peter Anvin (Intel) and committed by
Ingo Molnar
84132633 3d37d939

+105 -12
+15
arch/x86/Makefile
··· 269 269 $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all 270 270 271 271 ### 272 + # <asm/cpufeaturemasks.h> header generation 273 + 274 + cpufeaturemasks.hdr := arch/x86/include/generated/asm/cpufeaturemasks.h 275 + cpufeaturemasks.awk := $(srctree)/arch/x86/tools/cpufeaturemasks.awk 276 + cpufeatures_hdr := $(srctree)/arch/x86/include/asm/cpufeatures.h 277 + targets += $(cpufeaturemasks.hdr) 278 + quiet_cmd_gen_featuremasks = GEN $@ 279 + cmd_gen_featuremasks = $(AWK) -f $(cpufeaturemasks.awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) > $@ 280 + 281 + $(cpufeaturemasks.hdr): $(cpufeaturemasks.awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) FORCE 282 + $(shell mkdir -p $(dir $@)) 283 + $(call if_changed,gen_featuremasks) 284 + archprepare: $(cpufeaturemasks.hdr) 285 + 286 + ### 272 287 # Kernel objects 273 288 274 289 libs-y += arch/x86/lib/
+2 -1
arch/x86/boot/cpucheck.c
··· 22 22 # include "boot.h" 23 23 #endif 24 24 #include <linux/types.h> 25 + #include <asm/cpufeaturemasks.h> 25 26 #include <asm/intel-family.h> 26 27 #include <asm/processor-flags.h> 27 - #include <asm/required-features.h> 28 28 #include <asm/msr-index.h> 29 + 29 30 #include "string.h" 30 31 #include "msr.h" 31 32
-1
arch/x86/boot/cpuflags.c
··· 3 3 #include "bitops.h" 4 4 5 5 #include <asm/processor-flags.h> 6 - #include <asm/required-features.h> 7 6 #include <asm/msr-index.h> 8 7 #include "cpuflags.h" 9 8
+1 -2
arch/x86/boot/mkcpustr.c
··· 12 12 13 13 #include <stdio.h> 14 14 15 - #include "../include/asm/required-features.h" 16 - #include "../include/asm/disabled-features.h" 17 15 #include "../include/asm/cpufeatures.h" 18 16 #include "../include/asm/vmxfeatures.h" 19 17 #include "../kernel/cpu/capflags.c" ··· 21 23 int i, j; 22 24 const char *str; 23 25 26 + printf("#include <asm/cpufeaturemasks.h>\n\n"); 24 27 printf("static const char x86_cap_strs[] =\n"); 25 28 26 29 for (i = 0; i < NCAPINTS; i++) {
+1
arch/x86/include/asm/Kbuild
··· 8 8 generated-y += unistd_32_ia32.h 9 9 generated-y += unistd_64_x32.h 10 10 generated-y += xen-hypercalls.h 11 + generated-y += cpufeaturemasks.h 11 12 12 13 generic-y += early_ioremap.h 13 14 generic-y += fprobe.h
+1
arch/x86/include/asm/cpufeature.h
··· 9 9 #include <asm/asm.h> 10 10 #include <linux/bitops.h> 11 11 #include <asm/alternative.h> 12 + #include <asm/cpufeaturemasks.h> 12 13 13 14 enum cpuid_leafs 14 15 {
-8
arch/x86/include/asm/cpufeatures.h
··· 2 2 #ifndef _ASM_X86_CPUFEATURES_H 3 3 #define _ASM_X86_CPUFEATURES_H 4 4 5 - #ifndef _ASM_X86_REQUIRED_FEATURES_H 6 - #include <asm/required-features.h> 7 - #endif 8 - 9 - #ifndef _ASM_X86_DISABLED_FEATURES_H 10 - #include <asm/disabled-features.h> 11 - #endif 12 - 13 5 /* 14 6 * Defines x86 CPU feature bits 15 7 */
+4
arch/x86/kernel/verify_cpu.S
··· 29 29 */ 30 30 31 31 #include <asm/cpufeatures.h> 32 + #include <asm/cpufeaturemasks.h> 32 33 #include <asm/msr-index.h> 34 + 35 + #define SSE_MASK \ 36 + (REQUIRED_MASK0 & ((1<<(X86_FEATURE_XMM & 31)) | (1<<(X86_FEATURE_XMM2 & 31)))) 33 37 34 38 SYM_FUNC_START_LOCAL(verify_cpu) 35 39 pushf # Save caller passed flags
+81
arch/x86/tools/cpufeaturemasks.awk
··· 1 + #!/usr/bin/awk 2 + # 3 + # Convert cpufeatures.h to a list of compile-time masks 4 + # Note: this blithely assumes that each word has at least one 5 + # feature defined in it; if not, something else is wrong! 6 + # 7 + 8 + BEGIN { 9 + printf "#ifndef _ASM_X86_CPUFEATUREMASKS_H\n"; 10 + printf "#define _ASM_X86_CPUFEATUREMASKS_H\n\n"; 11 + 12 + file = 0 13 + } 14 + 15 + FNR == 1 { 16 + ++file; 17 + 18 + # arch/x86/include/asm/cpufeatures.h 19 + if (file == 1) 20 + FS = "[ \t()*+]+"; 21 + 22 + # .config 23 + if (file == 2) 24 + FS = "="; 25 + } 26 + 27 + # Create a dictionary of sorts, containing all defined feature bits 28 + file == 1 && $1 ~ /^#define$/ && $2 ~ /^X86_FEATURE_/ { 29 + nfeat = $3 * $4 + $5; 30 + feat = $2; 31 + sub(/^X86_FEATURE_/, "", feat); 32 + feats[nfeat] = feat; 33 + } 34 + file == 1 && $1 ~ /^#define$/ && $2 == "NCAPINTS" { 35 + ncapints = int($3); 36 + } 37 + 38 + # Create a dictionary featstat[REQUIRED|DISABLED, FEATURE_NAME] = on | off 39 + file == 2 && $1 ~ /^CONFIG_X86_(REQUIRED|DISABLED)_FEATURE_/ { 40 + on = ($2 == "y"); 41 + if (split($1, fs, "CONFIG_X86_|_FEATURE_") == 3) 42 + featstat[fs[2], fs[3]] = on; 43 + } 44 + 45 + END { 46 + sets[1] = "REQUIRED"; 47 + sets[2] = "DISABLED"; 48 + 49 + for (ns in sets) { 50 + s = sets[ns]; 51 + 52 + printf "/*\n"; 53 + printf " * %s features:\n", s; 54 + printf " *\n"; 55 + fstr = ""; 56 + for (i = 0; i < ncapints; i++) { 57 + mask = 0; 58 + for (j = 0; j < 32; j++) { 59 + feat = feats[i*32 + j]; 60 + if (featstat[s, feat]) { 61 + nfstr = fstr " " feat; 62 + if (length(nfstr) > 72) { 63 + printf " * %s\n", fstr; 64 + nfstr = " " feat; 65 + } 66 + fstr = nfstr; 67 + mask += (2 ^ j); 68 + } 69 + } 70 + masks[i] = mask; 71 + } 72 + printf " * %s\n */\n", fstr; 73 + 74 + for (i = 0; i < ncapints; i++) 75 + printf "#define %s_MASK%d\t0x%08xU\n", s, i, masks[i]; 76 + 77 + printf "#define %s_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != %d)\n\n", s, ncapints; 78 + } 79 + 80 + printf "#endif /* _ASM_X86_CPUFEATUREMASKS_H */\n"; 81 + }