Commit 480681f916 for qemu.org

commit 480681f91608454ee1bdf925231335e4c7e3435c
Author: Mohamed Mediouni <mohamed@unpredictable.fr>
Date:   Wed Apr 22 23:42:10 2026 +0200

    whpx: i386: add HV_X64_MSR_GUEST_IDLE when !kernel-irqchip

    Add support for an oddball HV_X64_MSR_GUEST_IDLE not-quite-an-HLT
    that wakes the vCPU even if EFLAGS.IF is set.

    Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
    Link: https://lore.kernel.org/r/20260422214225.2242-23-mohamed@unpredictable.fr
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index bc8d673c31..593a707e21 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -52,6 +52,7 @@
 /* for kernel-irqchip=off */
 #define HV_X64_MSR_APIC_FREQUENCY       0x40000023
 #define HV_X64_MSR_VP_ASSIST_PAGE       0x40000073
+#define HV_X64_MSR_GUEST_IDLE           0x400000f0

 static bool is_modern_os = true;

@@ -1648,6 +1649,15 @@ static int whpx_handle_halt(CPUState *cpu)
     return ret;
 }

+static int whpx_handle_hyperv_guestidle(CPUState *cpu)
+{
+    X86CPU *x86_cpu = X86_CPU(cpu);
+    CPUX86State *env = &x86_cpu->env;
+
+    env->hflags2 |= HF2_HYPERV_HLT_MASK;
+    return whpx_handle_halt(cpu);
+}
+
 static void whpx_vcpu_kick_out_of_hlt(CPUState *cpu)
 {
     WHV_REGISTER_VALUE reg;
@@ -1851,9 +1861,10 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)
     }

     if ((cpu_test_interrupt(cpu, CPU_INTERRUPT_HARD) &&
-         (env->eflags & IF_MASK)) ||
+         ((env->eflags & IF_MASK) || (env->hflags2 & HF2_HYPERV_HLT_MASK))) ||
         cpu_test_interrupt(cpu, CPU_INTERRUPT_NMI)) {
         cpu->halted = false;
+        env->hflags2 &= ~HF2_HYPERV_HLT_MASK;
     }

     if (cpu_test_interrupt(cpu, CPU_INTERRUPT_SIPI)) {
@@ -2128,6 +2139,20 @@ int whpx_vcpu_run(CPUState *cpu)
                 }
             }

+            /*
+             * Windows and Linux both use this MSR.
+             * Windows 11 25H2 uses it even when not advertised.
+             */
+            if (vcpu->exit_ctx.MsrAccess.MsrNumber == HV_X64_MSR_GUEST_IDLE
+                && !vcpu->exit_ctx.MsrAccess.AccessInfo.IsWrite
+                && !whpx_irqchip_in_kernel()
+                && whpx->hyperv_enlightenments_enabled) {
+                is_known_msr = 1;
+                whpx_bump_rip(cpu, &vcpu->exit_ctx);
+                ret = whpx_handle_hyperv_guestidle(cpu);
+                break;
+            }
+
             /*
              * Linux tries to use it anyway even when not exposed.
              * Ignore the write as the VP assist page is not used.