@samitouri / QOSamiQemu / commits / 07ec1a7235

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>

Trieu Huynh committed Mar 29, 2026 at 20:37 UTC 07ec1a723558b6a11aee6d56da24a71adf763cde
1 file changed +22
target/mips/system/machine.c
+22
@@ -3,6 +3,7 @@
3 #include "internal.h"
4 #include "migration/cpu.h"
5 #include "fpu_helper.h"
6 +#include "qemu/timer.h"
7
8 static int cpu_post_load(void *opaque, int version_id)
9 {
@@ -219,6 +220,23 @@ static const VMStateDescription vmstate_tlb = {
220
221 /* MIPS CPU state */
222
223 +static bool mips_timer_needed(void *opaque)
224 +{
225 + MIPSCPU *cpu = opaque;
226 + return cpu->env.timer != NULL;
227 +}
228 +
229 +static const VMStateDescription mips_vmstate_timer = {
230 + .name = "cpu/timer",
231 + .version_id = 1,
232 + .minimum_version_id = 1,
233 + .needed = mips_timer_needed,
234 + .fields = (const VMStateField[]) {
235 + VMSTATE_TIMER_PTR(env.timer, MIPSCPU),
236 + VMSTATE_END_OF_LIST()
237 + }
238 +};
239 +
240 const VMStateDescription vmstate_mips_cpu = {
241 .name = "cpu",
242 .version_id = 21,
@@ -333,4 +351,8 @@ const VMStateDescription vmstate_mips_cpu = {
351
352 VMSTATE_END_OF_LIST()
353 },
354 + .subsections = (const VMStateDescription * const []) {
355 + &mips_vmstate_timer,
356 + NULL
357 + }
358 };