[PATCH v5 1/3] x86/cpu: Clear feature bits disabled at compile-time

From: Maciej Wieczor-Retman

Date: Thu Feb 12 2026 - 10:35:56 EST


From: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>

If some config options are disabled during compile time, they still are
enumerated in macros that use the x86_capability bitmask - cpu_has() or
this_cpu_has().

The features are also visible in /proc/cpuinfo even though they are not
enabled - which is contrary to what the documentation states about the
file. Examples of such feature flags are lam, fred, sgx, ibrs_enhanced,
split_lock_detect, user_shstk, avx_vnni and enqcmd.

Through the cpufeaturemasks.awk script add a DISABLED_MASK_INITIALIZER
macro that creates an initializer list filled with DISABLED_MASKx
bitmasks.

At the same time add a REQUIRED_MASK_INITIALIZER that can be used for a
sanity check of whether all the required feature bits are set at the end
of cpu identification.

Initialize the cpu_caps_cleared array with the autogenerated disabled
bitmask. apply_forced_caps() will clear the corresponding bits in
boot_cpu_data.x86_capability[] and other secondary cpus'
cpu_data.x86_capability[]. Thus features disabled at compile time won't
show up in /proc/cpuinfo.

Reported-by: Farrah Chen <farrah.chen@xxxxxxxxx>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220348
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> # 6.18.x
---
arch/x86/kernel/cpu/common.c | 3 ++-
arch/x86/tools/cpufeaturemasks.awk | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index e7ab22fce3b5..8d12c5722245 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -732,7 +732,8 @@ static const char *table_lookup_model(struct cpuinfo_x86 *c)
}

/* Aligned to unsigned long to avoid split lock in atomic bitmap ops */
-__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));
+__u32 cpu_caps_cleared[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long)) =
+ DISABLED_MASK_INITIALIZER;
__u32 cpu_caps_set[NCAPINTS + NBUGINTS] __aligned(sizeof(unsigned long));

#ifdef CONFIG_X86_32
diff --git a/arch/x86/tools/cpufeaturemasks.awk b/arch/x86/tools/cpufeaturemasks.awk
index 173d5bf2d999..b7f4e775a365 100755
--- a/arch/x86/tools/cpufeaturemasks.awk
+++ b/arch/x86/tools/cpufeaturemasks.awk
@@ -82,6 +82,12 @@ END {
}
printf " 0\t\\\n";
printf "\t) & (1U << ((x) & 31)))\n\n";
+
+ printf "\n#define %s_MASK_INITIALIZER\t\t\t\\", s;
+ printf "\n\t{\t\t\t\t\t\t\\";
+ for (i = 0; i < ncapints; i++)
+ printf "\n\t\t%s_MASK%d,\t\t\t\\", s, i;
+ printf "\n\t}\n\n";
}

printf "#endif /* _ASM_X86_CPUFEATUREMASKS_H */\n";
--
2.53.0