Skip to content

Commit 0c2f6d0

Browse files
KAGA-KOKObp3tk0v
authored andcommitted
x86/topology/intel: Unlock CPUID before evaluating anything
Intel CPUs have a MSR bit to limit CPUID enumeration to leaf two. If this bit is set by the BIOS then CPUID evaluation including topology enumeration does not work correctly as the evaluation code does not try to analyze any leaf greater than two. This went unnoticed before because the original topology code just repeated evaluation several times and managed to overwrite the initial limited information with the correct one later. The new evaluation code does it once and therefore ends up with the limited and wrong information. Cure this by unlocking CPUID right before evaluating anything which depends on the maximum CPUID leaf being greater than two instead of rereading stuff after unlock. Fixes: 22d6366 ("x86/cpu: Use common topology code for Intel") Reported-by: Peter Schneider <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Tested-by: Peter Schneider <[email protected]> Cc: <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 2a38e4c commit 0c2f6d0

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

arch/x86/kernel/cpu/common.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
15891589
if (have_cpuid_p()) {
15901590
cpu_detect(c);
15911591
get_cpu_vendor(c);
1592+
intel_unlock_cpuid_leafs(c);
15921593
get_cpu_cap(c);
15931594
setup_force_cpu_cap(X86_FEATURE_CPUID);
15941595
get_cpu_address_sizes(c);
@@ -1748,7 +1749,7 @@ static void generic_identify(struct cpuinfo_x86 *c)
17481749
cpu_detect(c);
17491750

17501751
get_cpu_vendor(c);
1751-
1752+
intel_unlock_cpuid_leafs(c);
17521753
get_cpu_cap(c);
17531754

17541755
get_cpu_address_sizes(c);

arch/x86/kernel/cpu/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ extern __ro_after_init enum tsx_ctrl_states tsx_ctrl_state;
6161

6262
extern void __init tsx_init(void);
6363
void tsx_ap_init(void);
64+
void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c);
6465
#else
6566
static inline void tsx_init(void) { }
6667
static inline void tsx_ap_init(void) { }
68+
static inline void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c) { }
6769
#endif /* CONFIG_CPU_SUP_INTEL */
6870

6971
extern void init_spectral_chicken(struct cpuinfo_x86 *c);

arch/x86/kernel/cpu/intel.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -269,19 +269,26 @@ static void detect_tme_early(struct cpuinfo_x86 *c)
269269
c->x86_phys_bits -= keyid_bits;
270270
}
271271

272+
void intel_unlock_cpuid_leafs(struct cpuinfo_x86 *c)
273+
{
274+
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
275+
return;
276+
277+
if (c->x86 < 6 || (c->x86 == 6 && c->x86_model < 0xd))
278+
return;
279+
280+
/*
281+
* The BIOS can have limited CPUID to leaf 2, which breaks feature
282+
* enumeration. Unlock it and update the maximum leaf info.
283+
*/
284+
if (msr_clear_bit(MSR_IA32_MISC_ENABLE, MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0)
285+
c->cpuid_level = cpuid_eax(0);
286+
}
287+
272288
static void early_init_intel(struct cpuinfo_x86 *c)
273289
{
274290
u64 misc_enable;
275291

276-
/* Unmask CPUID levels if masked: */
277-
if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
278-
if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
279-
MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT) > 0) {
280-
c->cpuid_level = cpuid_eax(0);
281-
get_cpu_cap(c);
282-
}
283-
}
284-
285292
if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
286293
(c->x86 == 0x6 && c->x86_model >= 0x0e))
287294
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);

0 commit comments

Comments
 (0)