[PATCH v6 13/90] x86/cpu/intel: Rescan CPUID table after leaf unlock
From: Ahmed S. Darwish
Date: Thu Mar 26 2026 - 22:22:53 EST
Intel CPUs have a "limit CPUID" MSR bit to limit CPUID enumeration only up
to CPUID(0x2). This can be set by old BIOSen before booting Linux.
If that MSR bit was set, refresh the cached CPUID table after clearing it.
Scan only the newly-found CPUID leaves, not to override any of the kernel's
previously force-set or unset CPUID bits.
References: 066941bd4eeb ("x86: unmask CPUID levels on Intel CPUs")
References: 0c2f6d04619e ("x86/topology/intel: Unlock CPUID before evaluating anything")
Signed-off-by: Ahmed S. Darwish <darwi@xxxxxxxxxxxxx>
---
arch/x86/kernel/cpu/intel.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 646ff33c4651..08869fecdf30 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -183,20 +183,34 @@ static void detect_tme_early(struct cpuinfo_x86 *c)
keyid_bits);
}
+/*
+ * Intel CPUs have an MSR bit to limit CPUID enumeration to CPUID(0x2), which
+ * can be set by old BIOSes before booting Linux. Clear that bit.
+ *
+ * Scan any newly-found CPUID leaves afterwards.
+ */
void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
{
+ const struct leaf_0x0_0 *l0;
+ unsigned int rescan_from;
+
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
return;
if (c->x86_vfm < INTEL_PENTIUM_M_DOTHAN)
return;
- /*
- * The BIOS can have limited CPUID to leaf 2, which breaks feature
- * enumeration. Unlock it and update the maximum leaf info.
- */
- if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0)
- c->cpuid_level = cpuid_eax(0);
+ if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) <= 0)
+ return;
+
+ cpuid_refresh_leaf(c, 0x0);
+ l0 = cpuid_leaf(c, 0x0);
+ if (!l0)
+ return;
+
+ rescan_from = min_t(int, l0->max_std_leaf, c->cpuid_level) + 1;
+ cpuid_refresh_range(c, rescan_from, CPUID_BASE_END);
+ c->cpuid_level = l0->max_std_leaf;
}
static void early_init_intel(struct cpuinfo_x86 *c)
--
2.53.0