[PATCH v9 3/3] x86/cpu: Do a sanity check on required feature bits

From: Maciej Wieczor-Retman

Date: Tue Mar 10 2026 - 14:04:03 EST


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

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

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx>
Acked-by: H. Peter Anvin (Intel) <hpa@xxxxxxxxx>
---
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 | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index cfffbbda3d95..43ee2d55a708 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -2003,6 +2003,34 @@ const char *x86_cap_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. In case of a mismatch emit a warning with
+ * all the missing feature names or X86_FEATURE_* numerals.
+ */
+static void verify_required_features(const struct cpuinfo_x86 *c)
+{
+ u32 missing[NCAPINTS] = REQUIRED_MASK_INIT;
+ char cap_buf[X86_CAP_BUF_SIZE];
+ unsigned int i;
+ u32 error = 0;
+
+ for (i = 0; i < NCAPINTS; i++) {
+ missing[i] &= ~c->x86_capability[i];
+ error |= missing[i];
+ }
+
+ if (!error)
+ return;
+
+ /* At least one required feature is missing */
+ pr_warn("cpu %d: missing required feature(s):", c->cpu_index);
+ for_each_set_bit(i, (unsigned long *)missing, NCAPINTS << 5)
+ pr_cont(" %s", x86_cap_name(i, cap_buf));
+ 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 +2160,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