Implemented handler for HVMSG_X64_HALT exit messages from the
hypervisor.

Signed-off-by: Magnus Kulke <magnusku...@linux.microsoft.com>
---
 accel/mshv/mshv-all.c       |  3 +++
 include/system/mshv.h       |  1 +
 target/i386/mshv/mshv-cpu.c | 26 ++++++++++++++++++++++++++
 3 files changed, 30 insertions(+)

diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c
index e9f880b83e..f6ad2b6d2b 100644
--- a/accel/mshv/mshv-all.c
+++ b/accel/mshv/mshv-all.c
@@ -506,6 +506,9 @@ static int mshv_cpu_exec(CPUState *cpu)
         switch (exit_reason) {
         case MshvVmExitIgnore:
             break;
+        case MshvVmExitHlt:
+            ret = EXCP_HLT;
+            break;
         default:
             ret = EXCP_INTERRUPT;
             break;
diff --git a/include/system/mshv.h b/include/system/mshv.h
index 63104af68c..27d7e3dff3 100644
--- a/include/system/mshv.h
+++ b/include/system/mshv.h
@@ -99,6 +99,7 @@ typedef enum MshvVmExit {
     MshvVmExitIgnore   = 0,
     MshvVmExitShutdown = 1,
     MshvVmExitSpecial  = 2,
+    MshvVmExitHlt      = 3,
 } MshvVmExit;
 
 void mshv_init_mmio_emu(void);
diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
index 353073ed50..41a3398ec8 100644
--- a/target/i386/mshv/mshv-cpu.c
+++ b/target/i386/mshv/mshv-cpu.c
@@ -14,6 +14,7 @@
 #include "qemu/error-report.h"
 #include "qemu/memalign.h"
 #include "qemu/typedefs.h"
+#include "qemu/main-loop.h"
 
 #include "system/mshv.h"
 #include "system/address-spaces.h"
@@ -1413,6 +1414,26 @@ static int handle_pio(CPUState *cpu, const struct 
hyperv_message *msg)
     return handle_pio_non_str(cpu, &info);
 }
 
+static int handle_halt(CPUState *cpu)
+{
+    int ret = 0;
+    X86CPU *x86cpu = X86_CPU(cpu);
+    CPUX86State *env = &x86cpu->env;
+    uint32_t hw_irq = cpu->interrupt_request & CPU_INTERRUPT_HARD;
+    uint32_t nmi_irq = cpu->interrupt_request & CPU_INTERRUPT_NMI;
+    bool irqs_enabled = (env->eflags & IF_MASK) != 0;
+
+    bql_lock();
+    if (!nmi_irq && (!hw_irq || !irqs_enabled)) {
+        cpu->exception_index = EXCP_HLT;
+        cpu->halted = true;
+        ret = 1;
+    }
+    bql_unlock();
+
+    return ret;
+}
+
 int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message *msg, MshvVmExit *exit)
 {
     int ret;
@@ -1441,6 +1462,11 @@ int mshv_run_vcpu(int vm_fd, CPUState *cpu, hv_message 
*msg, MshvVmExit *exit)
             return MshvVmExitSpecial;
         }
         return MshvVmExitIgnore;
+    case HVMSG_X64_HALT:
+        ret = handle_halt(cpu);
+        if (ret < 0) {
+            return MshvVmExitHlt;
+        }
     default:
         break;
     }
-- 
2.34.1


Reply via email to