Re: [PATCH v2] x86/cpu: Skip reading MSR_IA32_PLATFORM_ID in virtualized environment

From: Borislav Petkov

Date: Wed May 13 2026 - 06:18:07 EST


On Tue, May 12, 2026 at 09:57:58AM +0800, Binbin Wu wrote:
> hypervisor_present could be uninitialized if dis_ucode_ldr is true.
> intel_get_platform_id() is also called during the normal cpu initialization.

Right, that needs more surgery. See if the below works instead pls.

We might as well do it - the question whether we run on a HV comes very often
recenly - might as well make it an "official" variable.

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 10b5355b323e..67dd932305db 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -733,6 +733,7 @@ bool xen_set_default_idle(void);
#endif

void __noreturn stop_this_cpu(void *dummy);
+extern bool x86_hypervisor_present;
void microcode_check(struct cpuinfo_x86 *prev_info);
void store_cpu_caps(struct cpuinfo_x86 *info);

diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index e533881284a1..5c0afae75e9f 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -322,7 +322,7 @@ static u32 get_patch_level(void)
{
u32 rev, dummy __always_unused;

- if (IS_ENABLED(CONFIG_MICROCODE_DBG) && hypervisor_present) {
+ if (IS_ENABLED(CONFIG_MICROCODE_DBG) && x86_hypervisor_present) {
int cpu = smp_processor_id();

if (!microcode_rev[cpu]) {
@@ -714,7 +714,7 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
invlpg(p_addr_end);
}

- if (IS_ENABLED(CONFIG_MICROCODE_DBG) && hypervisor_present)
+ if (IS_ENABLED(CONFIG_MICROCODE_DBG) && x86_hypervisor_present)
microcode_rev[smp_processor_id()] = mc->hdr.patch_id;

/* verify patch application was successful */
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 68a1a893246c..f6722c9618e0 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -57,7 +57,7 @@ bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV);
u32 base_rev;
u32 microcode_rev[NR_CPUS] = {};

-bool hypervisor_present;
+bool __ro_after_init x86_hypervisor_present;

/*
* Synchronization.
@@ -118,14 +118,9 @@ bool __init microcode_loader_disabled(void)
/*
* Disable when:
*
- * 1) The CPU does not support CPUID.
- */
- if (!cpuid_feature()) {
- dis_ucode_ldr = true;
- return dis_ucode_ldr;
- }
-
- /*
+ * 1) The CPU does not support CPUID detected below in
+ * load_ucode_bsp().
+ *
* 2) Bit 31 in CPUID[1]:ECX is set
* The bit is reserved for hypervisor use. This is still not
* completely accurate as XEN PV guests don't see that CPUID bit
@@ -135,9 +130,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);
-
- if ((hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) ||
+ if ((x86_hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) ||
amd_check_current_patch_level())
dis_ucode_ldr = true;

@@ -179,6 +172,11 @@ void __init load_ucode_bsp(void)

early_parse_cmdline();

+ if (!cpuid_feature())
+ dis_ucode_ldr = true;
+ else
+ x86_hypervisor_present = native_cpuid_ecx(1) & BIT(31);
+
if (microcode_loader_disabled())
return;

diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 37ac4afe0972..a4c0a0cf928b 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -138,6 +138,9 @@ u32 intel_get_platform_id(void)
{
unsigned int val[2];

+ if (x86_hypervisor_present)
+ return 0;
+
/*
* This can be called early. Use CPUID directly instead of
* relying on cpuinfo_x86 which may not be fully initialized.
diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h
index 3b93c0676b4f..a10b547eda1e 100644
--- a/arch/x86/kernel/cpu/microcode/internal.h
+++ b/arch/x86/kernel/cpu/microcode/internal.h
@@ -48,7 +48,6 @@ extern struct early_load_data early_data;
extern struct ucode_cpu_info ucode_cpu_info[];
extern u32 microcode_rev[NR_CPUS];
extern u32 base_rev;
-extern bool hypervisor_present;

struct cpio_data find_microcode_in_initrd(const char *path);

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette