[PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config

Xin Li (Intel) posted 5 patches 9 months, 3 weeks ago
There is a newer version of this series
[PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Xin Li (Intel) 9 months, 3 weeks ago
From: "H. Peter Anvin (Intel)" <hpa@zytor.com>

Introduce an AWK script to auto-generate a header with required and
disabled feature masks based on <asm/cpufeatures.h> and 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 ]

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
---

Change in v6:
* Make the AWK script work for mawk and BusyBox awk (Borislav Petkov).

Change in v5:
* More polishes (Nikolay Borisov).

Changes in v4:
* Add a few high-level comments to the AWK script (Nikolay Borisov).
* Enforce CPU feature mask values to be unsigned.

Changes in v3:
* Remove AWK code that generates extra debugging comments (Brian Gerst).
* Move SSE_MASK to verify_cpu.S, the only place it is used (Brian Gerst).

Change in v2:
* Remove code generating unused macros {REQUIRED,DISABLED}_FEATURE(x)
  to tell if a CPU feature, e.g., X86_FEATURE_FRED, is a required or
  disabled feature for this particular compile-time configuration.
---
 arch/x86/Makefile                  | 17 ++++++-
 arch/x86/boot/cpucheck.c           |  3 +-
 arch/x86/boot/cpuflags.c           |  1 -
 arch/x86/boot/mkcpustr.c           |  3 +-
 arch/x86/include/asm/Kbuild        |  1 +
 arch/x86/include/asm/cpufeature.h  |  1 +
 arch/x86/include/asm/cpufeatures.h |  8 ---
 arch/x86/kernel/verify_cpu.S       |  4 ++
 arch/x86/tools/featuremasks.awk    | 81 ++++++++++++++++++++++++++++++
 9 files changed, 105 insertions(+), 14 deletions(-)
 create mode 100755 arch/x86/tools/featuremasks.awk

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 6784129328f6..60583987d320 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -263,9 +263,22 @@ archscripts: scripts_basic
 	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
 ###
-# Syscall table generation
+# Feature masks header and syscall table generation
 
-archheaders:
+out := arch/x86/include/generated/asm
+featuremasks_hdr := featuremasks.h
+featuremasks_awk := $(srctree)/arch/x86/tools/featuremasks.awk
+cpufeatures_hdr := $(srctree)/arch/x86/include/asm/cpufeatures.h
+quiet_cmd_gen_featuremasks = GEN     $@
+      cmd_gen_featuremasks = $(AWK) -f $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) > $@
+
+$(out)/$(featuremasks_hdr): $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) FORCE
+	$(shell mkdir -p $(out))
+	$(call if_changed,gen_featuremasks)
+
+targets += $(out)/$(featuremasks_hdr)
+
+archheaders: $(out)/$(featuremasks_hdr)
 	$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
 
 ###
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index 0aae4d4ed615..8d03a741d1b2 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -22,10 +22,11 @@
 # include "boot.h"
 #endif
 #include <linux/types.h>
+#include <asm/featuremasks.h>
 #include <asm/intel-family.h>
 #include <asm/processor-flags.h>
-#include <asm/required-features.h>
 #include <asm/msr-index.h>
+
 #include "string.h"
 #include "msr.h"
 
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index d75237ba7ce9..0cabdacb2a2f 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -3,7 +3,6 @@
 #include "bitops.h"
 
 #include <asm/processor-flags.h>
-#include <asm/required-features.h>
 #include <asm/msr-index.h>
 #include "cpuflags.h"
 
diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c
index da0ccc5de538..b90110109675 100644
--- a/arch/x86/boot/mkcpustr.c
+++ b/arch/x86/boot/mkcpustr.c
@@ -12,8 +12,6 @@
 
 #include <stdio.h>
 
-#include "../include/asm/required-features.h"
-#include "../include/asm/disabled-features.h"
 #include "../include/asm/cpufeatures.h"
 #include "../include/asm/vmxfeatures.h"
 #include "../kernel/cpu/capflags.c"
@@ -23,6 +21,7 @@ int main(void)
 	int i, j;
 	const char *str;
 
+	printf("#include <asm/featuremasks.h>\n\n");
 	printf("static const char x86_cap_strs[] =\n");
 
 	for (i = 0; i < NCAPINTS; i++) {
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 58f4ddecc5fa..51022d21003e 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -8,6 +8,7 @@ generated-y += syscalls_x32.h
 generated-y += unistd_32_ia32.h
 generated-y += unistd_64_x32.h
 generated-y += xen-hypercalls.h
+generated-y += featuremasks.h
 
 generic-y += early_ioremap.h
 generic-y += fprobe.h
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index de1ad09fe8d7..077a5bbd1cc5 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -9,6 +9,7 @@
 #include <asm/asm.h>
 #include <linux/bitops.h>
 #include <asm/alternative.h>
+#include <asm/featuremasks.h>
 
 enum cpuid_leafs
 {
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index c8701abb7752..b9b7329f4ac4 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -2,14 +2,6 @@
 #ifndef _ASM_X86_CPUFEATURES_H
 #define _ASM_X86_CPUFEATURES_H
 
-#ifndef _ASM_X86_REQUIRED_FEATURES_H
-#include <asm/required-features.h>
-#endif
-
-#ifndef _ASM_X86_DISABLED_FEATURES_H
-#include <asm/disabled-features.h>
-#endif
-
 /*
  * Defines x86 CPU feature bits
  */
diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
index 1258a5872d12..a23a65d5d177 100644
--- a/arch/x86/kernel/verify_cpu.S
+++ b/arch/x86/kernel/verify_cpu.S
@@ -29,8 +29,12 @@
  */
 
 #include <asm/cpufeatures.h>
+#include <asm/featuremasks.h>
 #include <asm/msr-index.h>
 
+#define SSE_MASK	\
+	(REQUIRED_MASK0 & ((1<<(X86_FEATURE_XMM & 31)) | (1<<(X86_FEATURE_XMM2 & 31))))
+
 SYM_FUNC_START_LOCAL(verify_cpu)
 	pushf				# Save caller passed flags
 	push	$0			# Kill any dangerous flags
diff --git a/arch/x86/tools/featuremasks.awk b/arch/x86/tools/featuremasks.awk
new file mode 100755
index 000000000000..fd3e72147157
--- /dev/null
+++ b/arch/x86/tools/featuremasks.awk
@@ -0,0 +1,81 @@
+#!/usr/bin/awk
+#
+# Convert cpufeatures.h to a list of compile-time masks
+# Note: this blithly assumes that each word has at least one
+# feature defined in it; if not, something else is wrong!
+#
+
+BEGIN {
+	printf "#ifndef _ASM_X86_FEATUREMASKS_H\n";
+	printf "#define _ASM_X86_FEATUREMASKS_H\n\n";
+
+	file = 0
+}
+
+FNR == 1 {
+	++file;
+
+	# arch/x86/include/asm/cpufeatures.h
+	if (file == 1)
+		FS = "[ \t()*+]+";
+
+	# .config
+	if (file == 2)
+		FS = "=";
+}
+
+# Create a dictionary of sorts, containing all defined feature bits
+file == 1 && $1 ~ /^#define$/ && $2 ~ /^X86_FEATURE_/ {
+	nfeat = $3 * $4 + $5;
+	feat = $2;
+	sub(/^X86_FEATURE_/, "", feat);
+	feats[nfeat] = feat;
+}
+file == 1 && $1 ~ /^#define$/ && $2 == "NCAPINTS" {
+	ncapints = int($3);
+}
+
+# Create a dictionary featstat[REQUIRED|DISABLED, FEATURE_NAME] = on | off
+file == 2 && $1 ~ /^CONFIG_X86_(REQUIRED|DISABLED)_FEATURE_/ {
+	on = ($2 == "y");
+	if (split($1, fs, "CONFIG_X86_|_FEATURE_") == 3)
+		featstat[fs[2], fs[3]] = on;
+}
+
+END {
+	sets[1] = "REQUIRED";
+	sets[2] = "DISABLED";
+
+	for (ns in sets) {
+		s = sets[ns];
+
+		printf "/*\n";
+		printf " * %s features:\n", s;
+		printf " *\n";
+		fstr = "";
+		for (i = 0; i < ncapints; i++) {
+			mask = 0;
+			for (j = 0; j < 32; j++) {
+				feat = feats[i*32 + j];
+				if (featstat[s, feat]) {
+					nfstr = fstr " " feat;
+					if (length(nfstr) > 72) {
+						printf " *   %s\n", fstr;
+						nfstr = " " feat;
+					}
+					fstr = nfstr;
+					mask += (2 ^ j);
+				}
+			}
+			masks[i] = mask;
+		}
+		printf " *   %s\n */\n", fstr;
+
+		for (i = 0; i < ncapints; i++)
+			printf "#define %s_MASK%d\t0x%08xU\n", s, i, masks[i];
+
+		printf "#define %s_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != %d)\n\n", s, ncapints;
+	}
+
+	printf "#endif /* _ASM_X86_FEATUREMASKS_H */\n";
+}
-- 
2.48.1
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Aithal, Srikanth 9 months, 2 weeks ago
On 2/28/2025 1:53 PM, Xin Li (Intel) wrote:
> From: "H. Peter Anvin (Intel)" <hpa@zytor.com>
> 
> Introduce an AWK script to auto-generate a header with required and
> disabled feature masks based on <asm/cpufeatures.h> and 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 ]
> 
> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> Signed-off-by: Xin Li (Intel) <xin@zytor.com>
> Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
> ---
> 
> Change in v6:
> * Make the AWK script work for mawk and BusyBox awk (Borislav Petkov).
> 
> Change in v5:
> * More polishes (Nikolay Borisov).
> 
> Changes in v4:
> * Add a few high-level comments to the AWK script (Nikolay Borisov).
> * Enforce CPU feature mask values to be unsigned.
> 
> Changes in v3:
> * Remove AWK code that generates extra debugging comments (Brian Gerst).
> * Move SSE_MASK to verify_cpu.S, the only place it is used (Brian Gerst).
> 
> Change in v2:
> * Remove code generating unused macros {REQUIRED,DISABLED}_FEATURE(x)
>    to tell if a CPU feature, e.g., X86_FEATURE_FRED, is a required or
>    disabled feature for this particular compile-time configuration.
> ---
>   arch/x86/Makefile                  | 17 ++++++-
>   arch/x86/boot/cpucheck.c           |  3 +-
>   arch/x86/boot/cpuflags.c           |  1 -
>   arch/x86/boot/mkcpustr.c           |  3 +-
>   arch/x86/include/asm/Kbuild        |  1 +
>   arch/x86/include/asm/cpufeature.h  |  1 +
>   arch/x86/include/asm/cpufeatures.h |  8 ---
>   arch/x86/kernel/verify_cpu.S       |  4 ++
>   arch/x86/tools/featuremasks.awk    | 81 ++++++++++++++++++++++++++++++
>   9 files changed, 105 insertions(+), 14 deletions(-)
>   create mode 100755 arch/x86/tools/featuremasks.awk
> 
> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
> index 6784129328f6..60583987d320 100644
> --- a/arch/x86/Makefile
> +++ b/arch/x86/Makefile
> @@ -263,9 +263,22 @@ archscripts: scripts_basic
>   	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
>   
>   ###
> -# Syscall table generation
> +# Feature masks header and syscall table generation
>   
> -archheaders:
> +out := arch/x86/include/generated/asm
> +featuremasks_hdr := featuremasks.h
> +featuremasks_awk := $(srctree)/arch/x86/tools/featuremasks.awk
> +cpufeatures_hdr := $(srctree)/arch/x86/include/asm/cpufeatures.h
> +quiet_cmd_gen_featuremasks = GEN     $@
> +      cmd_gen_featuremasks = $(AWK) -f $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) > $@
> +
> +$(out)/$(featuremasks_hdr): $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) FORCE
> +	$(shell mkdir -p $(out))
> +	$(call if_changed,gen_featuremasks)
> +
> +targets += $(out)/$(featuremasks_hdr)
> +
> +archheaders: $(out)/$(featuremasks_hdr)
>   	$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
>   
>   ###
> diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
> index 0aae4d4ed615..8d03a741d1b2 100644
> --- a/arch/x86/boot/cpucheck.c
> +++ b/arch/x86/boot/cpucheck.c
> @@ -22,10 +22,11 @@
>   # include "boot.h"
>   #endif
>   #include <linux/types.h>
> +#include <asm/featuremasks.h>
>   #include <asm/intel-family.h>
>   #include <asm/processor-flags.h>
> -#include <asm/required-features.h>
>   #include <asm/msr-index.h>
> +
>   #include "string.h"
>   #include "msr.h"
>   
> diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
> index d75237ba7ce9..0cabdacb2a2f 100644
> --- a/arch/x86/boot/cpuflags.c
> +++ b/arch/x86/boot/cpuflags.c
> @@ -3,7 +3,6 @@
>   #include "bitops.h"
>   
>   #include <asm/processor-flags.h>
> -#include <asm/required-features.h>
>   #include <asm/msr-index.h>
>   #include "cpuflags.h"
>   
> diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c
> index da0ccc5de538..b90110109675 100644
> --- a/arch/x86/boot/mkcpustr.c
> +++ b/arch/x86/boot/mkcpustr.c
> @@ -12,8 +12,6 @@
>   
>   #include <stdio.h>
>   
> -#include "../include/asm/required-features.h"
> -#include "../include/asm/disabled-features.h"
>   #include "../include/asm/cpufeatures.h"
>   #include "../include/asm/vmxfeatures.h"
>   #include "../kernel/cpu/capflags.c"
> @@ -23,6 +21,7 @@ int main(void)
>   	int i, j;
>   	const char *str;
>   
> +	printf("#include <asm/featuremasks.h>\n\n");
>   	printf("static const char x86_cap_strs[] =\n");
>   
>   	for (i = 0; i < NCAPINTS; i++) {
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 58f4ddecc5fa..51022d21003e 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -8,6 +8,7 @@ generated-y += syscalls_x32.h
>   generated-y += unistd_32_ia32.h
>   generated-y += unistd_64_x32.h
>   generated-y += xen-hypercalls.h
> +generated-y += featuremasks.h
>   
>   generic-y += early_ioremap.h
>   generic-y += fprobe.h
> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
> index de1ad09fe8d7..077a5bbd1cc5 100644
> --- a/arch/x86/include/asm/cpufeature.h
> +++ b/arch/x86/include/asm/cpufeature.h
> @@ -9,6 +9,7 @@
>   #include <asm/asm.h>
>   #include <linux/bitops.h>
>   #include <asm/alternative.h>
> +#include <asm/featuremasks.h>
>   
>   enum cpuid_leafs
>   {
> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
> index c8701abb7752..b9b7329f4ac4 100644
> --- a/arch/x86/include/asm/cpufeatures.h
> +++ b/arch/x86/include/asm/cpufeatures.h
> @@ -2,14 +2,6 @@
>   #ifndef _ASM_X86_CPUFEATURES_H
>   #define _ASM_X86_CPUFEATURES_H
>   
> -#ifndef _ASM_X86_REQUIRED_FEATURES_H
> -#include <asm/required-features.h>
> -#endif
> -
> -#ifndef _ASM_X86_DISABLED_FEATURES_H
> -#include <asm/disabled-features.h>
> -#endif
> -
>   /*
>    * Defines x86 CPU feature bits
>    */
> diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
> index 1258a5872d12..a23a65d5d177 100644
> --- a/arch/x86/kernel/verify_cpu.S
> +++ b/arch/x86/kernel/verify_cpu.S
> @@ -29,8 +29,12 @@
>    */
>   
>   #include <asm/cpufeatures.h>
> +#include <asm/featuremasks.h>
>   #include <asm/msr-index.h>
>   
> +#define SSE_MASK	\
> +	(REQUIRED_MASK0 & ((1<<(X86_FEATURE_XMM & 31)) | (1<<(X86_FEATURE_XMM2 & 31))))
> +
>   SYM_FUNC_START_LOCAL(verify_cpu)
>   	pushf				# Save caller passed flags
>   	push	$0			# Kill any dangerous flags
> diff --git a/arch/x86/tools/featuremasks.awk b/arch/x86/tools/featuremasks.awk
> new file mode 100755
> index 000000000000..fd3e72147157
> --- /dev/null
> +++ b/arch/x86/tools/featuremasks.awk
> @@ -0,0 +1,81 @@
> +#!/usr/bin/awk
> +#
> +# Convert cpufeatures.h to a list of compile-time masks
> +# Note: this blithly assumes that each word has at least one
> +# feature defined in it; if not, something else is wrong!
> +#
> +
> +BEGIN {
> +	printf "#ifndef _ASM_X86_FEATUREMASKS_H\n";
> +	printf "#define _ASM_X86_FEATUREMASKS_H\n\n";
> +
> +	file = 0
> +}
> +
> +FNR == 1 {
> +	++file;
> +
> +	# arch/x86/include/asm/cpufeatures.h
> +	if (file == 1)
> +		FS = "[ \t()*+]+";
> +
> +	# .config
> +	if (file == 2)
> +		FS = "=";
> +}
> +
> +# Create a dictionary of sorts, containing all defined feature bits
> +file == 1 && $1 ~ /^#define$/ && $2 ~ /^X86_FEATURE_/ {
> +	nfeat = $3 * $4 + $5;
> +	feat = $2;
> +	sub(/^X86_FEATURE_/, "", feat);
> +	feats[nfeat] = feat;
> +}
> +file == 1 && $1 ~ /^#define$/ && $2 == "NCAPINTS" {
> +	ncapints = int($3);
> +}
> +
> +# Create a dictionary featstat[REQUIRED|DISABLED, FEATURE_NAME] = on | off
> +file == 2 && $1 ~ /^CONFIG_X86_(REQUIRED|DISABLED)_FEATURE_/ {
> +	on = ($2 == "y");
> +	if (split($1, fs, "CONFIG_X86_|_FEATURE_") == 3)
> +		featstat[fs[2], fs[3]] = on;
> +}
> +
> +END {
> +	sets[1] = "REQUIRED";
> +	sets[2] = "DISABLED";
> +
> +	for (ns in sets) {
> +		s = sets[ns];
> +
> +		printf "/*\n";
> +		printf " * %s features:\n", s;
> +		printf " *\n";
> +		fstr = "";
> +		for (i = 0; i < ncapints; i++) {
> +			mask = 0;
> +			for (j = 0; j < 32; j++) {
> +				feat = feats[i*32 + j];
> +				if (featstat[s, feat]) {
> +					nfstr = fstr " " feat;
> +					if (length(nfstr) > 72) {
> +						printf " *   %s\n", fstr;
> +						nfstr = " " feat;
> +					}
> +					fstr = nfstr;
> +					mask += (2 ^ j);
> +				}
> +			}
> +			masks[i] = mask;
> +		}
> +		printf " *   %s\n */\n", fstr;
> +
> +		for (i = 0; i < ncapints; i++)
> +			printf "#define %s_MASK%d\t0x%08xU\n", s, i, masks[i];
> +
> +		printf "#define %s_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != %d)\n\n", s, ncapints;
> +	}
> +
> +	printf "#endif /* _ASM_X86_FEATUREMASKS_H */\n";
> +}



Building kselftests is regressing with this commit on next-20250303.

# make headers
   HOSTCC  scripts/basic/fixdep
   HOSTCC  scripts/unifdef
   WRAP    arch/x86/include/generated/uapi/asm/bpf_perf_event.h
   WRAP    arch/x86/include/generated/uapi/asm/errno.h
   WRAP    arch/x86/include/generated/uapi/asm/fcntl.h
   WRAP    arch/x86/include/generated/uapi/asm/ioctl.h
   WRAP    arch/x86/include/generated/uapi/asm/ioctls.h
   WRAP    arch/x86/include/generated/uapi/asm/ipcbuf.h
   WRAP    arch/x86/include/generated/uapi/asm/param.h
   WRAP    arch/x86/include/generated/uapi/asm/poll.h
   WRAP    arch/x86/include/generated/uapi/asm/resource.h
   WRAP    arch/x86/include/generated/uapi/asm/socket.h
   WRAP    arch/x86/include/generated/uapi/asm/sockios.h
   WRAP    arch/x86/include/generated/uapi/asm/termbits.h
   WRAP    arch/x86/include/generated/uapi/asm/termios.h
   WRAP    arch/x86/include/generated/uapi/asm/types.h
make[1]: *** No rule to make target '.config', needed by 
'arch/x86/include/generated/asm/featuremasks.h'.  Stop.
make: *** [Makefile:251: __sub-make] Error 2

The same used to work fine until next-20250228.

Recreation steps:
1. Clone next-20250303
2. make distclean
3. make headers

Srikanth Aithal <sraithal@amd.com>
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by H. Peter Anvin 9 months, 2 weeks ago
On March 3, 2025 3:38:05 AM PST, "Aithal, Srikanth" <sraithal@amd.com> wrote:
>On 2/28/2025 1:53 PM, Xin Li (Intel) wrote:
>> From: "H. Peter Anvin (Intel)" <hpa@zytor.com>
>> 
>> Introduce an AWK script to auto-generate a header with required and
>> disabled feature masks based on <asm/cpufeatures.h> and 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 ]
>> 
>> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
>> Signed-off-by: Xin Li (Intel) <xin@zytor.com>
>> Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
>> ---
>> 
>> Change in v6:
>> * Make the AWK script work for mawk and BusyBox awk (Borislav Petkov).
>> 
>> Change in v5:
>> * More polishes (Nikolay Borisov).
>> 
>> Changes in v4:
>> * Add a few high-level comments to the AWK script (Nikolay Borisov).
>> * Enforce CPU feature mask values to be unsigned.
>> 
>> Changes in v3:
>> * Remove AWK code that generates extra debugging comments (Brian Gerst).
>> * Move SSE_MASK to verify_cpu.S, the only place it is used (Brian Gerst).
>> 
>> Change in v2:
>> * Remove code generating unused macros {REQUIRED,DISABLED}_FEATURE(x)
>>    to tell if a CPU feature, e.g., X86_FEATURE_FRED, is a required or
>>    disabled feature for this particular compile-time configuration.
>> ---
>>   arch/x86/Makefile                  | 17 ++++++-
>>   arch/x86/boot/cpucheck.c           |  3 +-
>>   arch/x86/boot/cpuflags.c           |  1 -
>>   arch/x86/boot/mkcpustr.c           |  3 +-
>>   arch/x86/include/asm/Kbuild        |  1 +
>>   arch/x86/include/asm/cpufeature.h  |  1 +
>>   arch/x86/include/asm/cpufeatures.h |  8 ---
>>   arch/x86/kernel/verify_cpu.S       |  4 ++
>>   arch/x86/tools/featuremasks.awk    | 81 ++++++++++++++++++++++++++++++
>>   9 files changed, 105 insertions(+), 14 deletions(-)
>>   create mode 100755 arch/x86/tools/featuremasks.awk
>> 
>> diff --git a/arch/x86/Makefile b/arch/x86/Makefile
>> index 6784129328f6..60583987d320 100644
>> --- a/arch/x86/Makefile
>> +++ b/arch/x86/Makefile
>> @@ -263,9 +263,22 @@ archscripts: scripts_basic
>>   	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
>>     ###
>> -# Syscall table generation
>> +# Feature masks header and syscall table generation
>>   -archheaders:
>> +out := arch/x86/include/generated/asm
>> +featuremasks_hdr := featuremasks.h
>> +featuremasks_awk := $(srctree)/arch/x86/tools/featuremasks.awk
>> +cpufeatures_hdr := $(srctree)/arch/x86/include/asm/cpufeatures.h
>> +quiet_cmd_gen_featuremasks = GEN     $@
>> +      cmd_gen_featuremasks = $(AWK) -f $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) > $@
>> +
>> +$(out)/$(featuremasks_hdr): $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) FORCE
>> +	$(shell mkdir -p $(out))
>> +	$(call if_changed,gen_featuremasks)
>> +
>> +targets += $(out)/$(featuremasks_hdr)
>> +
>> +archheaders: $(out)/$(featuremasks_hdr)
>>   	$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
>>     ###
>> diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
>> index 0aae4d4ed615..8d03a741d1b2 100644
>> --- a/arch/x86/boot/cpucheck.c
>> +++ b/arch/x86/boot/cpucheck.c
>> @@ -22,10 +22,11 @@
>>   # include "boot.h"
>>   #endif
>>   #include <linux/types.h>
>> +#include <asm/featuremasks.h>
>>   #include <asm/intel-family.h>
>>   #include <asm/processor-flags.h>
>> -#include <asm/required-features.h>
>>   #include <asm/msr-index.h>
>> +
>>   #include "string.h"
>>   #include "msr.h"
>>   diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
>> index d75237ba7ce9..0cabdacb2a2f 100644
>> --- a/arch/x86/boot/cpuflags.c
>> +++ b/arch/x86/boot/cpuflags.c
>> @@ -3,7 +3,6 @@
>>   #include "bitops.h"
>>     #include <asm/processor-flags.h>
>> -#include <asm/required-features.h>
>>   #include <asm/msr-index.h>
>>   #include "cpuflags.h"
>>   diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c
>> index da0ccc5de538..b90110109675 100644
>> --- a/arch/x86/boot/mkcpustr.c
>> +++ b/arch/x86/boot/mkcpustr.c
>> @@ -12,8 +12,6 @@
>>     #include <stdio.h>
>>   -#include "../include/asm/required-features.h"
>> -#include "../include/asm/disabled-features.h"
>>   #include "../include/asm/cpufeatures.h"
>>   #include "../include/asm/vmxfeatures.h"
>>   #include "../kernel/cpu/capflags.c"
>> @@ -23,6 +21,7 @@ int main(void)
>>   	int i, j;
>>   	const char *str;
>>   +	printf("#include <asm/featuremasks.h>\n\n");
>>   	printf("static const char x86_cap_strs[] =\n");
>>     	for (i = 0; i < NCAPINTS; i++) {
>> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
>> index 58f4ddecc5fa..51022d21003e 100644
>> --- a/arch/x86/include/asm/Kbuild
>> +++ b/arch/x86/include/asm/Kbuild
>> @@ -8,6 +8,7 @@ generated-y += syscalls_x32.h
>>   generated-y += unistd_32_ia32.h
>>   generated-y += unistd_64_x32.h
>>   generated-y += xen-hypercalls.h
>> +generated-y += featuremasks.h
>>     generic-y += early_ioremap.h
>>   generic-y += fprobe.h
>> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
>> index de1ad09fe8d7..077a5bbd1cc5 100644
>> --- a/arch/x86/include/asm/cpufeature.h
>> +++ b/arch/x86/include/asm/cpufeature.h
>> @@ -9,6 +9,7 @@
>>   #include <asm/asm.h>
>>   #include <linux/bitops.h>
>>   #include <asm/alternative.h>
>> +#include <asm/featuremasks.h>
>>     enum cpuid_leafs
>>   {
>> diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
>> index c8701abb7752..b9b7329f4ac4 100644
>> --- a/arch/x86/include/asm/cpufeatures.h
>> +++ b/arch/x86/include/asm/cpufeatures.h
>> @@ -2,14 +2,6 @@
>>   #ifndef _ASM_X86_CPUFEATURES_H
>>   #define _ASM_X86_CPUFEATURES_H
>>   -#ifndef _ASM_X86_REQUIRED_FEATURES_H
>> -#include <asm/required-features.h>
>> -#endif
>> -
>> -#ifndef _ASM_X86_DISABLED_FEATURES_H
>> -#include <asm/disabled-features.h>
>> -#endif
>> -
>>   /*
>>    * Defines x86 CPU feature bits
>>    */
>> diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
>> index 1258a5872d12..a23a65d5d177 100644
>> --- a/arch/x86/kernel/verify_cpu.S
>> +++ b/arch/x86/kernel/verify_cpu.S
>> @@ -29,8 +29,12 @@
>>    */
>>     #include <asm/cpufeatures.h>
>> +#include <asm/featuremasks.h>
>>   #include <asm/msr-index.h>
>>   +#define SSE_MASK	\
>> +	(REQUIRED_MASK0 & ((1<<(X86_FEATURE_XMM & 31)) | (1<<(X86_FEATURE_XMM2 & 31))))
>> +
>>   SYM_FUNC_START_LOCAL(verify_cpu)
>>   	pushf				# Save caller passed flags
>>   	push	$0			# Kill any dangerous flags
>> diff --git a/arch/x86/tools/featuremasks.awk b/arch/x86/tools/featuremasks.awk
>> new file mode 100755
>> index 000000000000..fd3e72147157
>> --- /dev/null
>> +++ b/arch/x86/tools/featuremasks.awk
>> @@ -0,0 +1,81 @@
>> +#!/usr/bin/awk
>> +#
>> +# Convert cpufeatures.h to a list of compile-time masks
>> +# Note: this blithly assumes that each word has at least one
>> +# feature defined in it; if not, something else is wrong!
>> +#
>> +
>> +BEGIN {
>> +	printf "#ifndef _ASM_X86_FEATUREMASKS_H\n";
>> +	printf "#define _ASM_X86_FEATUREMASKS_H\n\n";
>> +
>> +	file = 0
>> +}
>> +
>> +FNR == 1 {
>> +	++file;
>> +
>> +	# arch/x86/include/asm/cpufeatures.h
>> +	if (file == 1)
>> +		FS = "[ \t()*+]+";
>> +
>> +	# .config
>> +	if (file == 2)
>> +		FS = "=";
>> +}
>> +
>> +# Create a dictionary of sorts, containing all defined feature bits
>> +file == 1 && $1 ~ /^#define$/ && $2 ~ /^X86_FEATURE_/ {
>> +	nfeat = $3 * $4 + $5;
>> +	feat = $2;
>> +	sub(/^X86_FEATURE_/, "", feat);
>> +	feats[nfeat] = feat;
>> +}
>> +file == 1 && $1 ~ /^#define$/ && $2 == "NCAPINTS" {
>> +	ncapints = int($3);
>> +}
>> +
>> +# Create a dictionary featstat[REQUIRED|DISABLED, FEATURE_NAME] = on | off
>> +file == 2 && $1 ~ /^CONFIG_X86_(REQUIRED|DISABLED)_FEATURE_/ {
>> +	on = ($2 == "y");
>> +	if (split($1, fs, "CONFIG_X86_|_FEATURE_") == 3)
>> +		featstat[fs[2], fs[3]] = on;
>> +}
>> +
>> +END {
>> +	sets[1] = "REQUIRED";
>> +	sets[2] = "DISABLED";
>> +
>> +	for (ns in sets) {
>> +		s = sets[ns];
>> +
>> +		printf "/*\n";
>> +		printf " * %s features:\n", s;
>> +		printf " *\n";
>> +		fstr = "";
>> +		for (i = 0; i < ncapints; i++) {
>> +			mask = 0;
>> +			for (j = 0; j < 32; j++) {
>> +				feat = feats[i*32 + j];
>> +				if (featstat[s, feat]) {
>> +					nfstr = fstr " " feat;
>> +					if (length(nfstr) > 72) {
>> +						printf " *   %s\n", fstr;
>> +						nfstr = " " feat;
>> +					}
>> +					fstr = nfstr;
>> +					mask += (2 ^ j);
>> +				}
>> +			}
>> +			masks[i] = mask;
>> +		}
>> +		printf " *   %s\n */\n", fstr;
>> +
>> +		for (i = 0; i < ncapints; i++)
>> +			printf "#define %s_MASK%d\t0x%08xU\n", s, i, masks[i];
>> +
>> +		printf "#define %s_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != %d)\n\n", s, ncapints;
>> +	}
>> +
>> +	printf "#endif /* _ASM_X86_FEATUREMASKS_H */\n";
>> +}
>
>
>
>Building kselftests is regressing with this commit on next-20250303.
>
># make headers
>  HOSTCC  scripts/basic/fixdep
>  HOSTCC  scripts/unifdef
>  WRAP    arch/x86/include/generated/uapi/asm/bpf_perf_event.h
>  WRAP    arch/x86/include/generated/uapi/asm/errno.h
>  WRAP    arch/x86/include/generated/uapi/asm/fcntl.h
>  WRAP    arch/x86/include/generated/uapi/asm/ioctl.h
>  WRAP    arch/x86/include/generated/uapi/asm/ioctls.h
>  WRAP    arch/x86/include/generated/uapi/asm/ipcbuf.h
>  WRAP    arch/x86/include/generated/uapi/asm/param.h
>  WRAP    arch/x86/include/generated/uapi/asm/poll.h
>  WRAP    arch/x86/include/generated/uapi/asm/resource.h
>  WRAP    arch/x86/include/generated/uapi/asm/socket.h
>  WRAP    arch/x86/include/generated/uapi/asm/sockios.h
>  WRAP    arch/x86/include/generated/uapi/asm/termbits.h
>  WRAP    arch/x86/include/generated/uapi/asm/termios.h
>  WRAP    arch/x86/include/generated/uapi/asm/types.h
>make[1]: *** No rule to make target '.config', needed by 'arch/x86/include/generated/asm/featuremasks.h'.  Stop.
>make: *** [Makefile:251: __sub-make] Error 2
>
>The same used to work fine until next-20250228.
>
>Recreation steps:
>1. Clone next-20250303
>2. make distclean
>3. make headers
>
>Srikanth Aithal <sraithal@amd.com>

"make headers" on an unconfigured tree should presumably only produce the uapi headers, not kernel-internal ones, one could surmise?
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Borislav Petkov 9 months, 2 weeks ago
On Mon, Mar 03, 2025 at 04:05:54AM -0800, H. Peter Anvin wrote:
> "make headers" on an unconfigured tree should presumably only produce the uapi headers, not kernel-internal ones, one could surmise?

Well, that's kinda a question for you guys:

cfc7686900a87   (H. Peter Anvin (Intel) 2025-02-28 00:23:36 -0800       281)archheaders: $(out)/$(featuremasks_hdr)
1f57d5d85ba7f   (Ingo Molnar    2015-06-03 18:36:41 +0200       282)    $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all

and the headers target has

headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts

as its prereq.

Judging by

59b2bd05f5f4 ("kbuild: add 'headers' target to build up uapi headers in usr/include")

it sure looks like "make headers" should be for uapi headers only.

Oh, and it should be documented in "make help" output btw.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Xin Li 9 months, 2 weeks ago
On 3/3/2025 5:25 AM, Borislav Petkov wrote:
> On Mon, Mar 03, 2025 at 04:05:54AM -0800, H. Peter Anvin wrote:
>> "make headers" on an unconfigured tree should presumably only produce the uapi headers, not kernel-internal ones, one could surmise?
> 
> Well, that's kinda a question for you guys:
> 
> cfc7686900a87   (H. Peter Anvin (Intel) 2025-02-28 00:23:36 -0800       281)archheaders: $(out)/$(featuremasks_hdr)
> 1f57d5d85ba7f   (Ingo Molnar    2015-06-03 18:36:41 +0200       282)    $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
> 
> and the headers target has
> 
> headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
> 
> as its prereq.
> 
> Judging by
> 
> 59b2bd05f5f4 ("kbuild: add 'headers' target to build up uapi headers in usr/include")

It seems that 'archprepare' works, however I'm not sure if it's the best
choice.  Any suggestion?

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 60583987d320..2db535958b8d 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -276,9 +276,9 @@ $(out)/$(featuremasks_hdr): $(featuremasks_awk) 
$(cpufeatures_hdr) $(KCONFIG_CON
	$(shell mkdir -p $(out))
	$(call if_changed,gen_featuremasks)

-targets += $(out)/$(featuremasks_hdr)
+archprepare: $(out)/$(featuremasks_hdr)

-archheaders: $(out)/$(featuremasks_hdr)
+archheaders:
	$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all

  ###

> 
> it sure looks like "make headers" should be for uapi headers only.
> 
> Oh, and it should be documented in "make help" output btw.

Want me to add it btw?

Thanks!
     Xin
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Borislav Petkov 9 months, 2 weeks ago
On Tue, Mar 04, 2025 at 02:18:51AM -0800, Xin Li wrote:
> It seems that 'archprepare' works, however I'm not sure if it's the best
> choice.  Any suggestion?

Why do you even need featuremasks_hdr as a prereq?

I still don't get the dependency there.

In any case, you'd have to redo your patches - we've zapped them from tip.

> Want me to add it btw?

Yes pls.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Xin Li 9 months, 2 weeks ago
On 3/4/2025 2:29 AM, Borislav Petkov wrote:
> On Tue, Mar 04, 2025 at 02:18:51AM -0800, Xin Li wrote:
>> It seems that 'archprepare' works, however I'm not sure if it's the best
>> choice.  Any suggestion?
> 
> Why do you even need featuremasks_hdr as a prereq?

I'm not sure I'm calling it a prereq; it needs to be generated after we
have a build config and before any kernel source file is built.

"perpare" is defined as a post config build target used before starting
building the kernel or the modules, and "archprepare" is used in arch
Makefiles.  E.g., on x86, "archprepare" is already used for ORC header
generation:

ifdef CONFIG_UNWINDER_ORC
orc_hash_h := arch/$(SRCARCH)/include/generated/asm/orc_hash.h
orc_hash_sh := $(srctree)/scripts/orc_hash.sh
targets += $(orc_hash_h)
quiet_cmd_orc_hash = GEN     $@
	cmd_orc_hash = mkdir -p $(dir $@); \
                      $(CONFIG_SHELL) $(orc_hash_sh) < $< > $@
$(orc_hash_h): $(srctree)/arch/x86/include/asm/orc_types.h 
$(orc_hash_sh) FORCE
	$(call if_changed,orc_hash)
archprepare: $(orc_hash_h)
endif

> 
> In any case, you'd have to redo your patches - we've zapped them from tip.

Sorry for the build noise.  Ofc they should be zapped.

BTW, I'm asking if this build check could be added to Intel-LKP.

> 
>> Want me to add it btw?
> 
> Yes pls.

Sure.

However it needs to change Makefile in the root directory, which is not
maintained in tip, so I will send a separate patch to KERNEL BUILD
maintainers and list.  Make sense?

Thanks!
     Xin
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Borislav Petkov 9 months, 2 weeks ago
On Tue, Mar 04, 2025 at 11:30:43PM -0800, Xin Li wrote:
> > Why do you even need featuremasks_hdr as a prereq?
> 
> I'm not sure I'm calling it a prereq; 

That's what this is called:

https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html

A prerequisite to a target, latter being "archheaders" in this case.

> Sorry for the build noise.  Ofc they should be zapped.
> 
> BTW, I'm asking if this build check could be added to Intel-LKP.

Good idea.

> However it needs to change Makefile in the root directory, which is not
> maintained in tip, so I will send a separate patch to KERNEL BUILD
> maintainers and list.  Make sense?

Ditto.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by Xin Li 8 months, 4 weeks ago
On 3/5/2025 2:04 PM, Borislav Petkov wrote:
>> Sorry for the build noise.  Ofc they should be zapped.
>>
>> BTW, I'm asking if this build check could be added to Intel-LKP.
> Good idea.

FYI, Philip has confirmed that the build check is added to Intel-LKP.

Thanks!
      Xin
Re: [PATCH v6 3/5] x86/cpufeatures: Generate a feature mask header based on build config
Posted by H. Peter Anvin 9 months, 2 weeks ago
On March 3, 2025 5:25:05 AM PST, Borislav Petkov <bp@alien8.de> wrote:
>On Mon, Mar 03, 2025 at 04:05:54AM -0800, H. Peter Anvin wrote:
>> "make headers" on an unconfigured tree should presumably only produce the uapi headers, not kernel-internal ones, one could surmise?
>
>Well, that's kinda a question for you guys:
>
>cfc7686900a87   (H. Peter Anvin (Intel) 2025-02-28 00:23:36 -0800       281)archheaders: $(out)/$(featuremasks_hdr)
>1f57d5d85ba7f   (Ingo Molnar    2015-06-03 18:36:41 +0200       282)    $(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
>
>and the headers target has
>
>headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
>
>as its prereq.
>
>Judging by
>
>59b2bd05f5f4 ("kbuild: add 'headers' target to build up uapi headers in usr/include")
>
>it sure looks like "make headers" should be for uapi headers only.
>
>Oh, and it should be documented in "make help" output btw.
>

Yes, it was more of a statement. Generating internal headers sans config is utterly bogus.
[tip: x86/cpu] x86/cpufeatures: Generate a feature mask header based on build config
Posted by tip-bot2 for H. Peter Anvin (Intel) 9 months, 2 weeks ago
The following commit has been merged into the x86/cpu branch of tip:

Commit-ID:     cfc7686900a87ad8220bceb6b7862c6fcc00bff0
Gitweb:        https://git.kernel.org/tip/cfc7686900a87ad8220bceb6b7862c6fcc00bff0
Author:        H. Peter Anvin (Intel) <hpa@zytor.com>
AuthorDate:    Fri, 28 Feb 2025 00:23:36 -08:00
Committer:     Borislav Petkov (AMD) <bp@alien8.de>
CommitterDate: Fri, 28 Feb 2025 12:09:47 +01:00

x86/cpufeatures: Generate a feature mask header based on build config

Introduce an AWK script to auto-generate a header with required and
disabled feature masks based on <asm/cpufeatures.h> and 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 ]

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>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20250228082338.73859-4-xin@zytor.com
---
 arch/x86/Makefile                  | 17 +++++-
 arch/x86/boot/cpucheck.c           |  3 +-
 arch/x86/boot/cpuflags.c           |  1 +-
 arch/x86/boot/mkcpustr.c           |  3 +-
 arch/x86/include/asm/Kbuild        |  1 +-
 arch/x86/include/asm/cpufeature.h  |  1 +-
 arch/x86/include/asm/cpufeatures.h |  8 +---
 arch/x86/kernel/verify_cpu.S       |  4 +-
 arch/x86/tools/featuremasks.awk    | 81 +++++++++++++++++++++++++++++-
 9 files changed, 105 insertions(+), 14 deletions(-)
 create mode 100755 arch/x86/tools/featuremasks.awk

diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 8120085..ce6efad 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -259,9 +259,22 @@ archscripts: scripts_basic
 	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
 ###
-# Syscall table generation
+# Feature masks header and syscall table generation
 
-archheaders:
+out := arch/x86/include/generated/asm
+featuremasks_hdr := featuremasks.h
+featuremasks_awk := $(srctree)/arch/x86/tools/featuremasks.awk
+cpufeatures_hdr := $(srctree)/arch/x86/include/asm/cpufeatures.h
+quiet_cmd_gen_featuremasks = GEN     $@
+      cmd_gen_featuremasks = $(AWK) -f $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) > $@
+
+$(out)/$(featuremasks_hdr): $(featuremasks_awk) $(cpufeatures_hdr) $(KCONFIG_CONFIG) FORCE
+	$(shell mkdir -p $(out))
+	$(call if_changed,gen_featuremasks)
+
+targets += $(out)/$(featuremasks_hdr)
+
+archheaders: $(out)/$(featuremasks_hdr)
 	$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
 
 ###
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index 0aae4d4..8d03a74 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -22,10 +22,11 @@
 # include "boot.h"
 #endif
 #include <linux/types.h>
+#include <asm/featuremasks.h>
 #include <asm/intel-family.h>
 #include <asm/processor-flags.h>
-#include <asm/required-features.h>
 #include <asm/msr-index.h>
+
 #include "string.h"
 #include "msr.h"
 
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index d75237b..0cabdac 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -3,7 +3,6 @@
 #include "bitops.h"
 
 #include <asm/processor-flags.h>
-#include <asm/required-features.h>
 #include <asm/msr-index.h>
 #include "cpuflags.h"
 
diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c
index da0ccc5..b901101 100644
--- a/arch/x86/boot/mkcpustr.c
+++ b/arch/x86/boot/mkcpustr.c
@@ -12,8 +12,6 @@
 
 #include <stdio.h>
 
-#include "../include/asm/required-features.h"
-#include "../include/asm/disabled-features.h"
 #include "../include/asm/cpufeatures.h"
 #include "../include/asm/vmxfeatures.h"
 #include "../kernel/cpu/capflags.c"
@@ -23,6 +21,7 @@ int main(void)
 	int i, j;
 	const char *str;
 
+	printf("#include <asm/featuremasks.h>\n\n");
 	printf("static const char x86_cap_strs[] =\n");
 
 	for (i = 0; i < NCAPINTS; i++) {
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 58f4dde..51022d2 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -8,6 +8,7 @@ generated-y += syscalls_x32.h
 generated-y += unistd_32_ia32.h
 generated-y += unistd_64_x32.h
 generated-y += xen-hypercalls.h
+generated-y += featuremasks.h
 
 generic-y += early_ioremap.h
 generic-y += fprobe.h
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index e5fc003..c5e68da 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -9,6 +9,7 @@
 #include <asm/asm.h>
 #include <linux/bitops.h>
 #include <asm/alternative.h>
+#include <asm/featuremasks.h>
 
 enum cpuid_leafs
 {
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 508c0da..d5985e8 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -2,14 +2,6 @@
 #ifndef _ASM_X86_CPUFEATURES_H
 #define _ASM_X86_CPUFEATURES_H
 
-#ifndef _ASM_X86_REQUIRED_FEATURES_H
-#include <asm/required-features.h>
-#endif
-
-#ifndef _ASM_X86_DISABLED_FEATURES_H
-#include <asm/disabled-features.h>
-#endif
-
 /*
  * Defines x86 CPU feature bits
  */
diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
index 1258a58..a23a65d 100644
--- a/arch/x86/kernel/verify_cpu.S
+++ b/arch/x86/kernel/verify_cpu.S
@@ -29,8 +29,12 @@
  */
 
 #include <asm/cpufeatures.h>
+#include <asm/featuremasks.h>
 #include <asm/msr-index.h>
 
+#define SSE_MASK	\
+	(REQUIRED_MASK0 & ((1<<(X86_FEATURE_XMM & 31)) | (1<<(X86_FEATURE_XMM2 & 31))))
+
 SYM_FUNC_START_LOCAL(verify_cpu)
 	pushf				# Save caller passed flags
 	push	$0			# Kill any dangerous flags
diff --git a/arch/x86/tools/featuremasks.awk b/arch/x86/tools/featuremasks.awk
new file mode 100755
index 0000000..fd3e721
--- /dev/null
+++ b/arch/x86/tools/featuremasks.awk
@@ -0,0 +1,81 @@
+#!/usr/bin/awk
+#
+# Convert cpufeatures.h to a list of compile-time masks
+# Note: this blithly assumes that each word has at least one
+# feature defined in it; if not, something else is wrong!
+#
+
+BEGIN {
+	printf "#ifndef _ASM_X86_FEATUREMASKS_H\n";
+	printf "#define _ASM_X86_FEATUREMASKS_H\n\n";
+
+	file = 0
+}
+
+FNR == 1 {
+	++file;
+
+	# arch/x86/include/asm/cpufeatures.h
+	if (file == 1)
+		FS = "[ \t()*+]+";
+
+	# .config
+	if (file == 2)
+		FS = "=";
+}
+
+# Create a dictionary of sorts, containing all defined feature bits
+file == 1 && $1 ~ /^#define$/ && $2 ~ /^X86_FEATURE_/ {
+	nfeat = $3 * $4 + $5;
+	feat = $2;
+	sub(/^X86_FEATURE_/, "", feat);
+	feats[nfeat] = feat;
+}
+file == 1 && $1 ~ /^#define$/ && $2 == "NCAPINTS" {
+	ncapints = int($3);
+}
+
+# Create a dictionary featstat[REQUIRED|DISABLED, FEATURE_NAME] = on | off
+file == 2 && $1 ~ /^CONFIG_X86_(REQUIRED|DISABLED)_FEATURE_/ {
+	on = ($2 == "y");
+	if (split($1, fs, "CONFIG_X86_|_FEATURE_") == 3)
+		featstat[fs[2], fs[3]] = on;
+}
+
+END {
+	sets[1] = "REQUIRED";
+	sets[2] = "DISABLED";
+
+	for (ns in sets) {
+		s = sets[ns];
+
+		printf "/*\n";
+		printf " * %s features:\n", s;
+		printf " *\n";
+		fstr = "";
+		for (i = 0; i < ncapints; i++) {
+			mask = 0;
+			for (j = 0; j < 32; j++) {
+				feat = feats[i*32 + j];
+				if (featstat[s, feat]) {
+					nfstr = fstr " " feat;
+					if (length(nfstr) > 72) {
+						printf " *   %s\n", fstr;
+						nfstr = " " feat;
+					}
+					fstr = nfstr;
+					mask += (2 ^ j);
+				}
+			}
+			masks[i] = mask;
+		}
+		printf " *   %s\n */\n", fstr;
+
+		for (i = 0; i < ncapints; i++)
+			printf "#define %s_MASK%d\t0x%08xU\n", s, i, masks[i];
+
+		printf "#define %s_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != %d)\n\n", s, ncapints;
+	}
+
+	printf "#endif /* _ASM_X86_FEATUREMASKS_H */\n";
+}