public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check
@ 2026-03-27 15:10 Maciej Wieczor-Retman
  2026-03-27 15:10 ` [PATCH v12 1/4] x86/cpu: Clear feature bits disabled at compile-time Maciej Wieczor-Retman
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 15:10 UTC (permalink / raw)
  To: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86, m.wieczorretman

Series aims to fix the inconsistency between the cpuinfo behavior and
the documentation. Specifically the features that are not compiled are
still present in the cpuinfo bitmasks as enabled. This is not in line
with the documentation which specifies that not-compiled features are
not present in /proc/cpuinfo.

Along adding the disabled feature bitmask initializer array, the
complementary required bitmask initializer is also added. It can be used
to provide a sanity check, after the cpu identification is finished, to
make sure every required bit is set in the final bitmask. A warning with
the cpu number and all required bits that were not set is emitted in
case of the sanity check failure.

Before adding the sanity check a small cleanup can be done. Three places
open code an operation that retrieves either a feature string or, if the
string is not present, the feature number in word:bit format. One of
these places also doesn't check whether the string is actually there or
not. While currently not a problem (all the features in the checked list
have corresponding strings) it may cause a failure if more entries are
added. The cleanup patch fixes that and simplifies the other two
instances.

Patches are based on v7.0-rc5

Previous patchset versions:
v11: https://lore.kernel.org/all/cover.1774008873.git.m.wieczorretman@pm.me/
v10: https://lore.kernel.org/all/cover.1773771353.git.m.wieczorretman@pm.me/
v9:  https://lore.kernel.org/all/cover.1773165421.git.m.wieczorretman@pm.me/
v8:  https://lore.kernel.org/all/cover.1772453012.git.m.wieczorretman@pm.me/
v7:  https://lore.kernel.org/all/cover.1771936214.git.m.wieczorretman@pm.me/
v6:  https://lore.kernel.org/all/cover.1771590895.git.m.wieczorretman@pm.me/
v5:  https://lore.kernel.org/all/cover.1770908783.git.m.wieczorretman@pm.me/
v4:  https://lore.kernel.org/all/20250724125346.2792543-1-maciej.wieczor-retman@intel.com/
v3:  https://lore.kernel.org/all/20250724094554.2153919-1-maciej.wieczor-retman@intel.com/
v2:  https://lore.kernel.org/all/20250723092250.3411923-1-maciej.wieczor-retman@intel.com/
v1:  https://lore.kernel.org/all/20250722074439.4069992-1-maciej.wieczor-retman@intel.com/

Maciej Wieczor-Retman (4):
  x86/cpu: Clear feature bits disabled at compile-time
  x86/cpu: Check if feature string is non-zero
  x86/cpu: Do a sanity check on required feature bits
  x86/cpu: Clear feature bits whose dependencies were cleared

 arch/x86/include/asm/cpufeature.h  |  1 +
 arch/x86/kernel/cpu/common.c       | 63 +++++++++++++++++++++++++++---
 arch/x86/kernel/cpu/cpu.h          |  4 ++
 arch/x86/kernel/cpu/cpuid-deps.c   | 21 +++++-----
 arch/x86/tools/cpufeaturemasks.awk |  6 +++
 5 files changed, 79 insertions(+), 16 deletions(-)

-- 
2.53.0



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v12 1/4] x86/cpu: Clear feature bits disabled at compile-time
  2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
@ 2026-03-27 15:10 ` Maciej Wieczor-Retman
  2026-03-27 15:10 ` [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero Maciej Wieczor-Retman
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 15:10 UTC (permalink / raw)
  To: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86, m.wieczorretman, Farrah Chen

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

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, user_shstk and
enqcmd.

Initialize cpu_caps_cleared[] with an autogenerated disabled bitmask.
During CPU init, apply_forced_caps() will clear the corresponding bits
in struct cpuinfo_x86 for each CPU. Thus features disabled at compile
time won't show up in /proc/cpuinfo.

No BUGS are defined to be cleared at compile time, therefore only the
NCAPINTS part of cpu_caps_cleared[] is initialized using the macro. The
NBUGINTS part is set to zero.

Reported-by: Farrah Chen <farrah.chen@intel.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220348
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Reviewed-by: Sohil Mehta <sohil.mehta@intel.com>
---
Changelog v10:
- Remove examples of feature flags that came from stable kernels.
- Redo the patch message a bit with Sohil's suggestions.
- Add Sohil's Reviewed-by tag.

Changelog v9:
- *_MASK_INITIALIZER -> *_MASK_INIT
- Remove Cc stable.
- Note that the BUGS part of cpu_caps_cleared[] is zeroed.

Changelog v6:
- Remove patch message portions that are not just describing the diff.

 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 a8ff4376c286..76339e988304 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -735,7 +735,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_INIT;
 __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..9382bd15279a 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_INIT\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



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero
  2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
  2026-03-27 15:10 ` [PATCH v12 1/4] x86/cpu: Clear feature bits disabled at compile-time Maciej Wieczor-Retman
@ 2026-03-27 15:10 ` Maciej Wieczor-Retman
  2026-03-27 17:50   ` Sohil Mehta
  2026-03-27 15:10 ` [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits Maciej Wieczor-Retman
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 15:10 UTC (permalink / raw)
  To: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86, m.wieczorretman

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

In filter_cpuid_features(), x86_cap_flags[] is accessed based on the
features from cpuid_dependent_features[]. However it's not verified
whether the string in x86_cap_flags[] is non-zero which could lead to
unwanted output. While currently it's not a problem (all the features in
the checked list have non-zero strings) it may cause a failure if an
entry is added that doesn't have a feature string defined.

There are two other places that open code a similar operation of
printing out the feature string or if it's not present, the word:bit
feature format.

Reuse x86_feature_name() as a common helper to validate the presence of
feature strings in filter_cpuid_features() as well as unify similar open
coded cases.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v12:
- Remove Reviewed-by tags.
- Redo the patch message so it points out that the problem is not here
  now but may happen.
- Rename
	- X86_CAP_BUF_SIZE -> X86_NAMELSS_FEAT_BUFLEN
	- x86_cap_name() -> x86_feature_name()
- Move exporting the header to arch/x86/kernel/cpu/cpu.h
- Remove x86_bug_flags[] handling from x86_feature_name() since it
  doesn't interact with the array anywhere.

Changelog v11:
- Remove one extra tab after X86_CAP_BUF_SIZE.
- Add Reviewed-by tags from Sohil and Pawan.

Changelog v10:
- Reword the patch message a bit.
- Move x86_cap_name() declaration and X86_CAP_BUF_SIZE define to
  asm/cpufeature.h.
- Don't include asm/cpu.h in cpuid-deps.c
- Extend the comment above x86_cap_name to include information on buffer
  size that needs to be prepared before calling the function.
- Remove the likely(), unlikely() calls since this is not a hot path.

Changelog v9:
- 16 -> X86_CAP_BUF_SIZE.
- Add comment to the x86_cap_name().

Changelog v8:
- Move x86_cap_name() declaration from linux/cpu.h to the arch/cpu.h.
  Include arch/cpu.h in the cpuid-deps.c file instead of linux/cpu.h.

Changelog v7:
- sizeof(buf) -> 16
- Rebase onto 7.01-rc1.

Changelog v6:
- Remove parts of the patch message that are redundant and just copy
  what's visible in the diff.
- Redo the helper to use an external char buffer instead of a local
  static string.

 arch/x86/kernel/cpu/common.c     | 30 +++++++++++++++++++++++++-----
 arch/x86/kernel/cpu/cpu.h        |  4 ++++
 arch/x86/kernel/cpu/cpuid-deps.c | 19 +++----------------
 3 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 76339e988304..7cfd124b3fbf 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -678,6 +678,7 @@ cpuid_dependent_features[] = {
 static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
 {
 	const struct cpuid_dependent_feature *df;
+	char feature_buf[X86_NAMELESS_FEAT_BUFLEN];
 
 	for (df = cpuid_dependent_features; df->feature; df++) {
 
@@ -700,7 +701,7 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
 			continue;
 
 		pr_warn("CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
-			x86_cap_flags[df->feature], df->level);
+			x86_feature_name(df->feature, feature_buf), df->level);
 	}
 }
 
@@ -1637,6 +1638,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
 
 	while (arg) {
 		bool found __maybe_unused = false;
+		char name_buf[X86_NAMELESS_FEAT_BUFLEN];
 		unsigned int bit;
 
 		opt = strsep(&arg, ",");
@@ -1657,10 +1659,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
 					setup_clear_cpu_cap(bit);
 				}
 				/* empty-string, i.e., ""-defined feature flags */
-				if (!x86_cap_flags[bit])
-					pr_cont(" %d:%d\n", bit >> 5, bit & 31);
-				else
-					pr_cont(" %s\n", x86_cap_flags[bit]);
+				pr_cont(" %s\n", x86_feature_name(bit, name_buf));
 
 				taint++;
 			}
@@ -1983,6 +1982,27 @@ static void generic_identify(struct cpuinfo_x86 *c)
 #endif
 }
 
+/*
+ * Return the feature "name" if available, otherwise return the
+ * X86_FEATURE_* numerals to make it easier to identify the feature.
+ * Callers of this function need to pass a char * buffer of size
+ * X86_NAMELESS_FEAT_BUFLEN.
+ */
+const char *x86_feature_name(unsigned int bit, char *buf)
+{
+	unsigned int word = bit >> 5;
+	const char *name = NULL;
+
+	if (word < NCAPINTS)
+		name = x86_cap_flags[bit];
+
+	if (name)
+		return name;
+
+	snprintf(buf, X86_NAMELESS_FEAT_BUFLEN, "%u:%u", word, bit & 31);
+	return buf;
+}
+
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 5c7a3a71191a..0ce29ee56442 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -91,4 +91,8 @@ static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
 	       mode == SPECTRE_V2_EIBRS_LFENCE;
 }
 
+#define X86_NAMELESS_FEAT_BUFLEN	16
+
+const char *x86_feature_name(unsigned int bit, char *buf);
+
 #endif /* ARCH_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 146f6f8b0650..4354c0dd6d66 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -4,6 +4,8 @@
 #include <linux/module.h>
 #include <asm/cpufeature.h>
 
+#include "cpu.h"
+
 struct cpuid_dep {
 	unsigned int	feature;
 	unsigned int	depends;
@@ -156,24 +158,9 @@ void setup_clear_cpu_cap(unsigned int feature)
 	do_clear_cpu_cap(NULL, feature);
 }
 
-/*
- * Return the feature "name" if available, otherwise return
- * the X86_FEATURE_* numerals to make it easier to identify
- * the feature.
- */
-static const char *x86_feature_name(unsigned int feature, char *buf)
-{
-	if (x86_cap_flags[feature])
-		return x86_cap_flags[feature];
-
-	snprintf(buf, 16, "%d*32+%2d", feature / 32, feature % 32);
-
-	return buf;
-}
-
 void check_cpufeature_deps(struct cpuinfo_x86 *c)
 {
-	char feature_buf[16], depends_buf[16];
+	char feature_buf[X86_NAMELESS_FEAT_BUFLEN], depends_buf[X86_NAMELESS_FEAT_BUFLEN];
 	const struct cpuid_dep *d;
 
 	for (d = cpuid_deps; d->feature; d++) {
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits
  2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
  2026-03-27 15:10 ` [PATCH v12 1/4] x86/cpu: Clear feature bits disabled at compile-time Maciej Wieczor-Retman
  2026-03-27 15:10 ` [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero Maciej Wieczor-Retman
@ 2026-03-27 15:10 ` Maciej Wieczor-Retman
  2026-03-27 17:10   ` Pawan Gupta
  2026-03-27 15:11 ` [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared Maciej Wieczor-Retman
  2026-03-30  6:11 ` [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Andi Kleen
  4 siblings, 1 reply; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 15:10 UTC (permalink / raw)
  To: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86, m.wieczorretman

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

After CPU identification concludes, do a sanity check by comparing the
final x86_capability bitmask with the pre-defined required feature bits.

The NCAPINTS + 1 size of the required_features[] array results from
for_each_set_bit() parsing data in 64-bit chunks. In case NCAPINTS is an
odd number it will still reserve and zero out a 64-bit aligned chunk of
memory which will prevent false positives due to unaligned accesses.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v12:
- Redo the function into a one loop system instead of two loops
  according to Pawan Gupta's suggestion.
- Add a paragraph to the patch message about the NCAPINTS + 1 array
  size.

Changelog v11:
- Use DECLARE_BITMAP() on missing[] and recast to a u32 pointer for
  iterating. Do it to avoid unaligned memory accesses when later using
  for_each_set_bit() if NCAPINTS is going to ever become an odd number.
  missing[] was previously an u32 array and for_each_set_bit() works on
  unsigned long chunks of memory.
- Add a paragraph about the above to the patch message.
- Remove Peter's acked-by due to more changes.

Changelog v10:
- Shorten the comment before the sanity check.
- cpu -> CPU in the warning.
- NCAPINTS << 5 -> NCAPINTS * 32

Changelog v9:
- REQUIRED_MASK_INITIALIZER -> REQUIRED_MASK_INIT
- Redo the comments.
- Fix reverse xmas order.
- Inside for_each_set_bit: (void *) -> (unsigned long *).
- 16 -> X86_CAP_BUF_SIZE.

Changelog v6:
- Add Peter's acked-by tag.
- Rename patch subject to imperative form.
- Add a char buffer to the x86_cap_name() call.

 arch/x86/kernel/cpu/common.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 7cfd124b3fbf..8ad0da7012dd 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -2003,6 +2003,32 @@ const char *x86_feature_name(unsigned int bit, char *buf)
 	return buf;
 }
 
+/*
+ * As a sanity check compare the final x86_capability bitmask with the initial
+ * predefined required feature bits.
+ */
+static void verify_required_features(const struct cpuinfo_x86 *c)
+{
+	u32 required_features[NCAPINTS + 1] = REQUIRED_MASK_INIT;
+	char cap_buf[X86_NAMELESS_FEAT_BUFLEN];
+	int i, error = 0;
+
+	for_each_set_bit(i, (unsigned long *)required_features, NCAPINTS * 32) {
+		if (test_bit(i, (unsigned long *)c->x86_capability))
+			continue;
+		if (!error)
+			pr_warn("CPU %d: missing required feature(s):", c->cpu_index);
+		pr_cont(" %s", x86_feature_name(i, cap_buf));
+		error = 1;
+	}
+
+	if (!error)
+		return;
+
+	pr_cont("\n");
+	add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+}
+
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
@@ -2132,6 +2158,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 	mcheck_cpu_init(c);
 
 	numa_add_cpu(smp_processor_id());
+
+	verify_required_features(c);
 }
 
 /*
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared
  2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
                   ` (2 preceding siblings ...)
  2026-03-27 15:10 ` [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits Maciej Wieczor-Retman
@ 2026-03-27 15:11 ` Maciej Wieczor-Retman
  2026-03-28  2:22   ` H. Peter Anvin
  2026-03-30  6:11 ` [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Andi Kleen
  4 siblings, 1 reply; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 15:11 UTC (permalink / raw)
  To: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86, m.wieczorretman

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

After cpu_caps_cleared[] is initialized with DISABLED_MASK_INIT,
features present in disabled bitmasks are cleared from x86_capability[].
However features that depend on them and are not part of any disabled
mask are not cleared by anything. They can trigger the warning in
check_cpufeature_deps(), as before both features would show up as
enabled even though they weren't. The uncleared features can also still
falsely show up in /proc/cpuinfo.

Take such cases into account before applying the cpu_caps_cleared[]
array.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v12:
- Move the check from check_cpufeature_deps() to apply_forced_caps().
  Redo last paragraph of the patch message.

Changelog v11:
- Add this patch to the series.

 arch/x86/include/asm/cpufeature.h |  1 +
 arch/x86/kernel/cpu/common.c      |  2 ++
 arch/x86/kernel/cpu/cpuid-deps.c  | 14 ++++++++++++++
 3 files changed, 17 insertions(+)

diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 3ddc1d33399b..e7a62990a9c2 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -77,6 +77,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 
 extern void setup_clear_cpu_cap(unsigned int bit);
 extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);
+void clear_feature_disabled_deps(struct cpuinfo_x86 *c);
 void check_cpufeature_deps(struct cpuinfo_x86 *c);
 
 #define setup_force_cpu_cap(bit) do {			\
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8ad0da7012dd..2e24bdb3acaa 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -955,6 +955,8 @@ static void apply_forced_caps(struct cpuinfo_x86 *c)
 {
 	int i;
 
+	clear_feature_disabled_deps(c);
+
 	for (i = 0; i < NCAPINTS + NBUGINTS; i++) {
 		c->x86_capability[i] &= ~cpu_caps_cleared[i];
 		c->x86_capability[i] |= cpu_caps_set[i];
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 4354c0dd6d66..83060c0013c1 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -158,6 +158,20 @@ void setup_clear_cpu_cap(unsigned int feature)
 	do_clear_cpu_cap(NULL, feature);
 }
 
+/*
+ * If the dependency was cleared through the disabled bitmasks while the
+ * feature wasn't it also needs to be cleared.
+ */
+void clear_feature_disabled_deps(struct cpuinfo_x86 *c)
+{
+	const struct cpuid_dep *d;
+
+	for (d = cpuid_deps; d->feature; d++) {
+		if (!DISABLED_MASK_BIT_SET(d->feature) && DISABLED_MASK_BIT_SET(d->depends))
+			set_bit(d->feature, (unsigned long *)cpu_caps_cleared);
+	}
+}
+
 void check_cpufeature_deps(struct cpuinfo_x86 *c)
 {
 	char feature_buf[X86_NAMELESS_FEAT_BUFLEN], depends_buf[X86_NAMELESS_FEAT_BUFLEN];
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits
  2026-03-27 15:10 ` [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits Maciej Wieczor-Retman
@ 2026-03-27 17:10   ` Pawan Gupta
  2026-03-27 17:22     ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 13+ messages in thread
From: Pawan Gupta @ 2026-03-27 17:10 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pmladek,
	nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak,
	linux-kernel, x86

On Fri, Mar 27, 2026 at 03:10:58PM +0000, Maciej Wieczor-Retman wrote:
> +static void verify_required_features(const struct cpuinfo_x86 *c)
> +{
> +	u32 required_features[NCAPINTS + 1] = REQUIRED_MASK_INIT;
> +	char cap_buf[X86_NAMELESS_FEAT_BUFLEN];
> +	int i, error = 0;
> +
> +	for_each_set_bit(i, (unsigned long *)required_features, NCAPINTS * 32) {
> +		if (test_bit(i, (unsigned long *)c->x86_capability))

This can be simplified to:

		if (test_cpu_cap(c, i))

> +			continue;
> +		if (!error)
> +			pr_warn("CPU %d: missing required feature(s):", c->cpu_index);
> +		pr_cont(" %s", x86_feature_name(i, cap_buf));
> +		error = 1;
> +	}
> +
> +	if (!error)
> +		return;
> +
> +	pr_cont("\n");
> +	add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
> +}

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits
  2026-03-27 17:10   ` Pawan Gupta
@ 2026-03-27 17:22     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 17:22 UTC (permalink / raw)
  To: Pawan Gupta
  Cc: Maciej Wieczor-Retman, bp, dave.hansen, hpa, xin, chang.seok.bae,
	mingo, elena.reshetova, babu.moger, sohil.mehta, pmladek,
	nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak,
	linux-kernel, x86

On 2026-03-27 at 10:10:33 -0700, Pawan Gupta wrote:
>On Fri, Mar 27, 2026 at 03:10:58PM +0000, Maciej Wieczor-Retman wrote:
>> +static void verify_required_features(const struct cpuinfo_x86 *c)
>> +{
>> +	u32 required_features[NCAPINTS + 1] = REQUIRED_MASK_INIT;
>> +	char cap_buf[X86_NAMELESS_FEAT_BUFLEN];
>> +	int i, error = 0;
>> +
>> +	for_each_set_bit(i, (unsigned long *)required_features, NCAPINTS * 32) {
>> +		if (test_bit(i, (unsigned long *)c->x86_capability))
>
>This can be simplified to:
>
>		if (test_cpu_cap(c, i))
>

Oh, right, thanks! I'll correct that for v13.

-- 
Kind regards
Maciej Wieczór-Retman

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero
  2026-03-27 15:10 ` [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero Maciej Wieczor-Retman
@ 2026-03-27 17:50   ` Sohil Mehta
  2026-03-27 21:28     ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 13+ messages in thread
From: Sohil Mehta @ 2026-03-27 17:50 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, bp, dave.hansen, hpa, xin, chang.seok.bae,
	mingo, elena.reshetova, maciej.wieczor-retman, babu.moger,
	pawan.kumar.gupta, pmladek, nik.borisov, ptesarik, darwi, tglx,
	peterz, jpoimboe, ak
  Cc: linux-kernel, x86

On 3/27/2026 8:10 AM, Maciej Wieczor-Retman wrote:

>  arch/x86/kernel/cpu/common.c     | 30 +++++++++++++++++++++++++-----
>  arch/x86/kernel/cpu/cpu.h        |  4 ++++
>  arch/x86/kernel/cpu/cpuid-deps.c | 19 +++----------------
>  3 files changed, 32 insertions(+), 21 deletions(-)
> 

Reviewed-by: Sohil Mehta <sohil.mehta@intel.com>

A couple of minor points below:


> @@ -1637,6 +1638,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
>  
>  	while (arg) {
>  		bool found __maybe_unused = false;
> +		char name_buf[X86_NAMELESS_FEAT_BUFLEN];
>  		unsigned int bit;
>  
>  		opt = strsep(&arg, ",");
> @@ -1657,10 +1659,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
>  					setup_clear_cpu_cap(bit);
>  				}
>  				/* empty-string, i.e., ""-defined feature flags */

Can you delete this comment as well. It doesn't make sense now.

> -				if (!x86_cap_flags[bit])
> -					pr_cont(" %d:%d\n", bit >> 5, bit & 31);
> -				else
> -					pr_cont(" %s\n", x86_cap_flags[bit]);
> +				pr_cont(" %s\n", x86_feature_name(bit, name_buf));

All the other equivalent buffers are defined as feature_buf, but this
one is named as name_buf. Just curious, any specific reason?

>  
>  				taint++;
>  			}

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero
  2026-03-27 17:50   ` Sohil Mehta
@ 2026-03-27 21:28     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-27 21:28 UTC (permalink / raw)
  To: Sohil Mehta
  Cc: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, pawan.kumar.gupta, pmladek,
	nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak,
	linux-kernel, x86

On 2026-03-27 at 10:50:29 -0700, Sohil Mehta wrote:
>On 3/27/2026 8:10 AM, Maciej Wieczor-Retman wrote:
>
>>  arch/x86/kernel/cpu/common.c     | 30 +++++++++++++++++++++++++-----
>>  arch/x86/kernel/cpu/cpu.h        |  4 ++++
>>  arch/x86/kernel/cpu/cpuid-deps.c | 19 +++----------------
>>  3 files changed, 32 insertions(+), 21 deletions(-)
>> 
>
>Reviewed-by: Sohil Mehta <sohil.mehta@intel.com>
>
>A couple of minor points below:
>
>
>> @@ -1637,6 +1638,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
>>  
>>  	while (arg) {
>>  		bool found __maybe_unused = false;
>> +		char name_buf[X86_NAMELESS_FEAT_BUFLEN];
>>  		unsigned int bit;
>>  
>>  		opt = strsep(&arg, ",");
>> @@ -1657,10 +1659,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
>>  					setup_clear_cpu_cap(bit);
>>  				}
>>  				/* empty-string, i.e., ""-defined feature flags */
>
>Can you delete this comment as well. It doesn't make sense now.

Right, will do, thanks!

>
>> -				if (!x86_cap_flags[bit])
>> -					pr_cont(" %d:%d\n", bit >> 5, bit & 31);
>> -				else
>> -					pr_cont(" %s\n", x86_cap_flags[bit]);
>> +				pr_cont(" %s\n", x86_feature_name(bit, name_buf));
>
>All the other equivalent buffers are defined as feature_buf, but this
>one is named as name_buf. Just curious, any specific reason?

I think I was experimenting with cleaning up a further part of
parse_set_clear_cpuid() that printed a string from either x86_bug_flags or
x86_cap_flags. It looked ugly so I scrapped it but I guess I forgot to change
the name_buf to feature_buf. I'll correct that, thanks for noticing it :)

>>  
>>  				taint++;
>>  			}

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared
  2026-03-27 15:11 ` [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared Maciej Wieczor-Retman
@ 2026-03-28  2:22   ` H. Peter Anvin
  2026-03-30 10:40     ` Maciej Wieczor-Retman
  0 siblings, 1 reply; 13+ messages in thread
From: H. Peter Anvin @ 2026-03-28  2:22 UTC (permalink / raw)
  To: Maciej Wieczor-Retman, bp, dave.hansen, xin, chang.seok.bae,
	mingo, elena.reshetova, maciej.wieczor-retman, babu.moger,
	sohil.mehta, pawan.kumar.gupta, pmladek, nik.borisov, ptesarik,
	darwi, tglx, peterz, jpoimboe, ak
  Cc: linux-kernel, x86

On 2026-03-27 08:11, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> 
> After cpu_caps_cleared[] is initialized with DISABLED_MASK_INIT,
> features present in disabled bitmasks are cleared from x86_capability[].
> However features that depend on them and are not part of any disabled
> mask are not cleared by anything. They can trigger the warning in
> check_cpufeature_deps(), as before both features would show up as
> enabled even though they weren't. The uncleared features can also still
> falsely show up in /proc/cpuinfo.
> 
> Take such cases into account before applying the cpu_caps_cleared[]
> array.
> 
> +/*
> + * If the dependency was cleared through the disabled bitmasks while the
> + * feature wasn't it also needs to be cleared.
> + */
> +void clear_feature_disabled_deps(struct cpuinfo_x86 *c)
> +{
> +	const struct cpuid_dep *d;
> +
> +	for (d = cpuid_deps; d->feature; d++) {
> +		if (!DISABLED_MASK_BIT_SET(d->feature) && DISABLED_MASK_BIT_SET(d->depends))
> +			set_bit(d->feature, (unsigned long *)cpu_caps_cleared);
> +	}
> +}
> +

Thinking about it, if this is discovered at runtime, it is really too late,
because in a sense we have miscompiled the kernel with unwanted code (as we
should have compiled out these features just as with other DISABLED features.)

This ultimately reflects a failed dependency in Kconfig.cpufeatures, which may
have caused kconfig to do the Wrong Thing[TM]. So at the very least it might
be a good thing to print a message here saying Kconfig.cpufeatures should be
fixed.

The better option, which I don't know how difficult it would be, would be to
make the dependencies available to Kconfig. This sounds like something that
would fall in the scope of Ahmed's rework rather than this patchset, though
(Ahmed, would you agree?)

	-hpa



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check
  2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
                   ` (3 preceding siblings ...)
  2026-03-27 15:11 ` [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared Maciej Wieczor-Retman
@ 2026-03-30  6:11 ` Andi Kleen
  2026-03-30  8:52   ` Maciej Wieczor-Retman
  4 siblings, 1 reply; 13+ messages in thread
From: Andi Kleen @ 2026-03-30  6:11 UTC (permalink / raw)
  To: Maciej Wieczor-Retman
  Cc: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe,
	linux-kernel, x86


I'm not sure what the point of this check is. Obviously the kernel cannot
handle it, short of refusing to boot which would be far too drastic.

And if it's just for having something in the kernel log, who would look
for this? Any possible symptoms from a bogus cpuid will be far
disconnected from that particular log location.

Further, there's also no evidence that it is a real practical problem.
If anything it could likely only come from rogue VMMs, but these don't 
seem to be common. But VMMs normally don't really disable ISA, so even if the 
CPUID is inconsistent things will still likely work because the actual
instructions are fine.

Assuming it was a real problem, you could just do it in a user program, why
put it into the kernel and waste everyone's memory? (this cannot be
initcode due to hotplug)

Also it seems to violate Steinbach's system programing maxim
(never check for something you don't know how to handle)

-Andi

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check
  2026-03-30  6:11 ` [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Andi Kleen
@ 2026-03-30  8:52   ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-30  8:52 UTC (permalink / raw)
  To: Andi Kleen
  Cc: bp, dave.hansen, hpa, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe,
	linux-kernel, x86

On 2026-03-29 at 23:11:19 -0700, Andi Kleen wrote:
>
>I'm not sure what the point of this check is. Obviously the kernel cannot
>handle it, short of refusing to boot which would be far too drastic.
>
>And if it's just for having something in the kernel log, who would look
>for this? Any possible symptoms from a bogus cpuid will be far
>disconnected from that particular log location.
>
>Further, there's also no evidence that it is a real practical problem.
>If anything it could likely only come from rogue VMMs, but these don't 
>seem to be common. But VMMs normally don't really disable ISA, so even if the 
>CPUID is inconsistent things will still likely work because the actual
>instructions are fine.
>
>Assuming it was a real problem, you could just do it in a user program, why
>put it into the kernel and waste everyone's memory? (this cannot be
>initcode due to hotplug)
>
>Also it seems to violate Steinbach's system programing maxim
>(never check for something you don't know how to handle)
>
>-Andi

According to hpa [1] one could for example boot with PAE disabled and it might
go unnoticed. In that thread it was also mentioned that the BIOS might have
something required disabled and even if the system will not get to boot fully a
user could get a clue what failed.

Also a user could technically disable required features through clearcpuid. I
know it will also taint the kernel but no warning is produced if the cleared
feature was required.

[1] https://lore.kernel.org/all/207ba0a6-5ebc-465a-8d54-6e5a99622a72@zytor.com/

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared
  2026-03-28  2:22   ` H. Peter Anvin
@ 2026-03-30 10:40     ` Maciej Wieczor-Retman
  0 siblings, 0 replies; 13+ messages in thread
From: Maciej Wieczor-Retman @ 2026-03-30 10:40 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: bp, dave.hansen, xin, chang.seok.bae, mingo, elena.reshetova,
	maciej.wieczor-retman, babu.moger, sohil.mehta, pawan.kumar.gupta,
	pmladek, nik.borisov, ptesarik, darwi, tglx, peterz, jpoimboe, ak,
	linux-kernel, x86

On 2026-03-27 at 19:22:27 -0700, H. Peter Anvin wrote:
>On 2026-03-27 08:11, Maciej Wieczor-Retman wrote:
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>> 
>> After cpu_caps_cleared[] is initialized with DISABLED_MASK_INIT,
>> features present in disabled bitmasks are cleared from x86_capability[].
>> However features that depend on them and are not part of any disabled
>> mask are not cleared by anything. They can trigger the warning in
>> check_cpufeature_deps(), as before both features would show up as
>> enabled even though they weren't. The uncleared features can also still
>> falsely show up in /proc/cpuinfo.
>> 
>> Take such cases into account before applying the cpu_caps_cleared[]
>> array.
>> 
>> +/*
>> + * If the dependency was cleared through the disabled bitmasks while the
>> + * feature wasn't it also needs to be cleared.
>> + */
>> +void clear_feature_disabled_deps(struct cpuinfo_x86 *c)
>> +{
>> +	const struct cpuid_dep *d;
>> +
>> +	for (d = cpuid_deps; d->feature; d++) {
>> +		if (!DISABLED_MASK_BIT_SET(d->feature) && DISABLED_MASK_BIT_SET(d->depends))
>> +			set_bit(d->feature, (unsigned long *)cpu_caps_cleared);
>> +	}
>> +}
>> +
>
>Thinking about it, if this is discovered at runtime, it is really too late,
>because in a sense we have miscompiled the kernel with unwanted code (as we
>should have compiled out these features just as with other DISABLED features.)
>
>This ultimately reflects a failed dependency in Kconfig.cpufeatures, which may
>have caused kconfig to do the Wrong Thing[TM]. So at the very least it might
>be a good thing to print a message here saying Kconfig.cpufeatures should be
>fixed.

So how about a warning (for any future cases) and add a new patch to fix SGX (so
the current known problem is solved)?

>The better option, which I don't know how difficult it would be, would be to
>make the dependencies available to Kconfig. This sounds like something that
>would fall in the scope of Ahmed's rework rather than this patchset, though
>(Ahmed, would you agree?)
>
>	-hpa
>
>

-- 
Kind regards
Maciej Wieczór-Retman


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-03-30 10:40 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-27 15:10 [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Maciej Wieczor-Retman
2026-03-27 15:10 ` [PATCH v12 1/4] x86/cpu: Clear feature bits disabled at compile-time Maciej Wieczor-Retman
2026-03-27 15:10 ` [PATCH v12 2/4] x86/cpu: Check if feature string is non-zero Maciej Wieczor-Retman
2026-03-27 17:50   ` Sohil Mehta
2026-03-27 21:28     ` Maciej Wieczor-Retman
2026-03-27 15:10 ` [PATCH v12 3/4] x86/cpu: Do a sanity check on required feature bits Maciej Wieczor-Retman
2026-03-27 17:10   ` Pawan Gupta
2026-03-27 17:22     ` Maciej Wieczor-Retman
2026-03-27 15:11 ` [PATCH v12 4/4] x86/cpu: Clear feature bits whose dependencies were cleared Maciej Wieczor-Retman
2026-03-28  2:22   ` H. Peter Anvin
2026-03-30 10:40     ` Maciej Wieczor-Retman
2026-03-30  6:11 ` [PATCH v12 0/4] x86: Capability bits fix and required bits sanity check Andi Kleen
2026-03-30  8:52   ` Maciej Wieczor-Retman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox