The Linux kernel now reads MSR_IA32_PLATFORM_ID during CPU init. When running as a guest, if the underlying hypervisor does not emulate the MSR, the RDMSR from 0x17 in intel_get_platform_id() can trigger an unchecked MSR access during early boot. unchecked MSR access error: RDMSR from 0x17 at rIP: 0xffffffffba38d6fc (intel_get_platform_id+0x7c/0xb0) Call Trace: ? early_init_intel+0x28/0x2c0 ? early_cpu_init+0x9b/0x930 ? setup_arch+0xbf/0xbb0 ? _printk+0x6b/0x90 ? start_kernel+0x7f/0xaa0 ? x86_64_start_reservations+0x24/0x30 ? x86_64_start_kernel+0xda/0xe0 ? common_startup_64+0x13e/0x141 Currently, KVM does not support guest reads of MSR_IA32_PLATFORM_ID for TDX. This should be fixed in the hypervisor, but for compatibility with newer guests running on older KVM hosts, skip reading MSR_IA32_PLATFORM_ID and return 0. It's meaningless to read MSR_IA32_PLATFORM_ID since guests are not allowed to do microcode update. cpu_has_old_microcode(), which uses platform ID for CPU match, also skips checking whether the microcode is old or not in a virtualized environment. Since intel_get_platform_id() can be called early before cpuinfo_x86 is fully initialized, check whether it's running in a virtualized environment from CPUID and opportunistically add a helper. Fixes: d8630b67ca1ed ("x86/cpu: Add platform ID to CPU info structure") Reported-by: Vishal Verma Signed-off-by: Binbin Wu --- arch/x86/kernel/cpu/microcode/core.c | 2 +- arch/x86/kernel/cpu/microcode/intel.c | 4 ++++ arch/x86/kernel/cpu/microcode/internal.h | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 651202e6fefb..ee204c8a90bf 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -135,7 +135,7 @@ bool __init microcode_loader_disabled(void) * 3) Certain AMD patch levels are not allowed to be * overwritten. */ - hypervisor_present = native_cpuid_ecx(1) & BIT(31); + hypervisor_present = x86_cpuid_has_hypervisor(); if ((hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) || amd_check_current_patch_level()) diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 37ac4afe0972..cb93e4ea410e 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -147,6 +147,10 @@ u32 intel_get_platform_id(void) if (intel_cpuid_vfm() <= INTEL_PENTIUM_II_KLAMATH) return 0; + /* Don't try to read microcode bits when virtualized. */ + if (x86_cpuid_has_hypervisor()) + return 0; + /* get processor flags from MSR 0x17 */ native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h index 3b93c0676b4f..0233e074d76b 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -100,6 +100,11 @@ static inline unsigned int x86_cpuid_family(void) return x86_family(eax); } +static inline bool x86_cpuid_has_hypervisor(void) +{ + return native_cpuid_ecx(1) & BIT(31); +} + extern bool force_minrev; #ifdef CONFIG_CPU_SUP_AMD -- 2.46.0