[PATCH 2/3] whpx: x86: kick out of HLT manually when using the kernel-irqchip

Mohamed Mediouni posted 3 patches 3 days, 14 hours ago
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Paolo Bonzini <pbonzini@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Eduardo Habkost <eduardo@habkost.net>, Pedro Barbuda <pbarbuda@microsoft.com>, Mohamed Mediouni <mohamed@unpredictable.fr>
[PATCH 2/3] whpx: x86: kick out of HLT manually when using the kernel-irqchip
Posted by Mohamed Mediouni 3 days, 14 hours ago
Otherwise, interrupts processed through the cancel vCPU and inject path will not cause the vCPU to go out of its halt state.

Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
---
 target/i386/whpx/whpx-all.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index bd3a1c49c6..650d65c61e 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -1475,6 +1475,16 @@ static void whpx_vcpu_post_run(CPUState *cpu)
         !vcpu->exit_ctx.VpContext.ExecutionState.InterruptShadow;
 }
 
+static void whpx_vcpu_kick_out_of_hlt(CPUState *cpu) 
+{
+    WHV_REGISTER_VALUE reg;
+    whpx_get_reg(cpu, WHvRegisterInternalActivityState, &reg);
+    if (reg.InternalActivity.HaltSuspend) {
+        reg.InternalActivity.HaltSuspend = 0;
+        whpx_set_reg(cpu, WHvRegisterInternalActivityState, reg);
+    }
+}
+
 static void whpx_vcpu_process_async_events(CPUState *cpu)
 {
     X86CPU *x86_cpu = X86_CPU(cpu);
@@ -1760,6 +1770,25 @@ int whpx_vcpu_run(CPUState *cpu)
                 cpu->exception_index = EXCP_INTERRUPT;
                 ret = 1;
             }
+            /* 
+             * When the Hyper-V APIC is enabled, to get out of HLT we
+             * either have to request an interrupt or manually get it away
+             * from HLT.
+             *
+             * We also manually do inject some interrupts via WHvRegisterPendingEvent
+             * instead of WHVRequestInterrupt, which does not reset the HLT state.
+             *
+             * However, even with this done, if the guest does an HLT without
+             * interrupts enabled (which the test_sti_inhibit KVM unit test does)
+             * then the guest will stay in HLT forever.
+             *
+             * Keep it this way for now, with perhaps adding a heartbeat later
+             * so that we get the CPU time savings from having Hyper-V handle HLT
+             * instead of going away from it as soon as possible.
+             */
+            if (whpx_irqchip_in_kernel()) {
+                whpx_vcpu_kick_out_of_hlt(cpu);
+            }
             break;
         case WHvRunVpExitReasonX64MsrAccess: {
             WHV_REGISTER_VALUE reg_values[3] = {0};
-- 
2.50.1 (Apple Git-155)
Re: [PATCH 2/3] whpx: x86: kick out of HLT manually when using the kernel-irqchip
Posted by Bernhard Beschow 3 days, 11 hours ago

Am 26. Februar 2026 18:19:29 UTC schrieb Mohamed Mediouni <mohamed@unpredictable.fr>:
>Otherwise, interrupts processed through the cancel vCPU and inject path will not cause the vCPU to go out of its halt state.

Yay, thanks for tackling this!

>
>Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>

It probably resolves https://gitlab.com/qemu-project/qemu/-/issues/346 , though that would need to be confirmed by testing.

Best regards,
Bernhard

>---
> target/i386/whpx/whpx-all.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
>diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
>index bd3a1c49c6..650d65c61e 100644
>--- a/target/i386/whpx/whpx-all.c
>+++ b/target/i386/whpx/whpx-all.c
>@@ -1475,6 +1475,16 @@ static void whpx_vcpu_post_run(CPUState *cpu)
>         !vcpu->exit_ctx.VpContext.ExecutionState.InterruptShadow;
> }
> 
>+static void whpx_vcpu_kick_out_of_hlt(CPUState *cpu) 
>+{
>+    WHV_REGISTER_VALUE reg;
>+    whpx_get_reg(cpu, WHvRegisterInternalActivityState, &reg);
>+    if (reg.InternalActivity.HaltSuspend) {
>+        reg.InternalActivity.HaltSuspend = 0;
>+        whpx_set_reg(cpu, WHvRegisterInternalActivityState, reg);
>+    }
>+}
>+
> static void whpx_vcpu_process_async_events(CPUState *cpu)
> {
>     X86CPU *x86_cpu = X86_CPU(cpu);
>@@ -1760,6 +1770,25 @@ int whpx_vcpu_run(CPUState *cpu)
>                 cpu->exception_index = EXCP_INTERRUPT;
>                 ret = 1;
>             }
>+            /* 
>+             * When the Hyper-V APIC is enabled, to get out of HLT we
>+             * either have to request an interrupt or manually get it away
>+             * from HLT.
>+             *
>+             * We also manually do inject some interrupts via WHvRegisterPendingEvent
>+             * instead of WHVRequestInterrupt, which does not reset the HLT state.
>+             *
>+             * However, even with this done, if the guest does an HLT without
>+             * interrupts enabled (which the test_sti_inhibit KVM unit test does)
>+             * then the guest will stay in HLT forever.
>+             *
>+             * Keep it this way for now, with perhaps adding a heartbeat later
>+             * so that we get the CPU time savings from having Hyper-V handle HLT
>+             * instead of going away from it as soon as possible.
>+             */
>+            if (whpx_irqchip_in_kernel()) {
>+                whpx_vcpu_kick_out_of_hlt(cpu);
>+            }
>             break;
>         case WHvRunVpExitReasonX64MsrAccess: {
>             WHV_REGISTER_VALUE reg_values[3] = {0};