Commit 07ec1a7235 for qemu.org

commit 07ec1a723558b6a11aee6d56da24a71adf763cde
Author: Trieu Huynh <vikingtc4@gmail.com>
Date:   Sun Mar 29 20:37:32 2026 +0900

    target/mips: save CP0 timer in vmstate

    The MIPS R4K CP0 timer (env->timer) is not included in vmstate_mips_cpu,
    so after loadvm the QEMUTimer has no scheduled expiry. This causes
    qemu_poll_ns() to block indefinitely and the guest to freeze until an
    external I/O event (e.g. a keypress) wakes the main loop.

    Fix by adding an optional vmstate subsection for the timer, following
    the same pattern used by ARM (gt_timer), RISC-V (env.stimer), SPARC
    (qtimer), and OpenRISC (timer).

    The .needed callback returns false when env->timer is NULL (KVM mode),
    keeping the subsection optional for backwards compatibility with
    existing snapshots.

    Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1987
    Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
    Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
    Message-ID: <20260329113732.482619-1-vikingtc4@gmail.com>
    Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>

diff --git a/target/mips/system/machine.c b/target/mips/system/machine.c
index 8af11fd896..473d3ab036 100644
--- a/target/mips/system/machine.c
+++ b/target/mips/system/machine.c
@@ -3,6 +3,7 @@
 #include "internal.h"
 #include "migration/cpu.h"
 #include "fpu_helper.h"
+#include "qemu/timer.h"

 static int cpu_post_load(void *opaque, int version_id)
 {
@@ -219,6 +220,23 @@ static const VMStateDescription vmstate_tlb = {

 /* MIPS CPU state */

+static bool mips_timer_needed(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    return cpu->env.timer != NULL;
+}
+
+static const VMStateDescription mips_vmstate_timer = {
+    .name = "cpu/timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = mips_timer_needed,
+    .fields = (const VMStateField[]) {
+        VMSTATE_TIMER_PTR(env.timer, MIPSCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 const VMStateDescription vmstate_mips_cpu = {
     .name = "cpu",
     .version_id = 21,
@@ -333,4 +351,8 @@ const VMStateDescription vmstate_mips_cpu = {

         VMSTATE_END_OF_LIST()
     },
+    .subsections = (const VMStateDescription * const []) {
+        &mips_vmstate_timer,
+        NULL
+    }
 };