On Thu, Sep 11, 2025 at 7:58 PM TANG Tiancheng <[email protected]> wrote: > > The current 'timecmp' field in vmstate_riscv_mtimer is insufficient to keep > timers functional after migration. > > If an mtimer's entry in 'mtimer->timers' is active at the time the snapshot > is taken, it means riscv_aclint_mtimer_write_timecmp() has written to > 'mtimecmp' and scheduled a timer into QEMU's main loop 'timer_list'. > > During snapshot save, these active timers must also be migrated; otherwise, > after snapshot load there is no mechanism to restore 'mtimer->timers' back > into the 'timer_list', and any pending timer events would be lost. > > QEMU's migration framework commonly uses VMSTATE_TIMER_xxx macros to save > and restore 'QEMUTimer' variables. However, 'timers' is a pointer array > with variable length, and vmstate.h did not previously provide a helper > macro for such type. > > This commit adds a new macro, 'VMSTATE_TIMER_PTR_VARRAY', to handle saving > and restoring a variable-length array of 'QEMUTimer *'. We then use this > macro to migrate the 'mtimer->timers' array, ensuring that timer events > remain scheduled correctly after snapshot load. > > Reviewed-by: LIU Zhiwei <[email protected]> > Signed-off-by: TANG Tiancheng <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > hw/intc/riscv_aclint.c | 6 ++++-- > include/hw/intc/riscv_aclint.h | 4 ++++ > 2 files changed, 8 insertions(+), 2 deletions(-) > > diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c > index > 318a9c8248432a8cd4c3f3fa990739917ecf7ca1..9f4c36e965e2aa379d75c0a9f656177f0dd82a45 > 100644 > --- a/hw/intc/riscv_aclint.c > +++ b/hw/intc/riscv_aclint.c > @@ -323,13 +323,15 @@ static void riscv_aclint_mtimer_reset_enter(Object > *obj, ResetType type) > > static const VMStateDescription vmstate_riscv_mtimer = { > .name = "riscv_mtimer", > - .version_id = 2, > - .minimum_version_id = 2, > + .version_id = 3, > + .minimum_version_id = 3, > .fields = (const VMStateField[]) { > VMSTATE_UINT64(time_delta, RISCVAclintMTimerState), > VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState, > num_harts, 0, > vmstate_info_uint64, uint64_t), > + VMSTATE_TIMER_PTR_VARRAY(timers, RISCVAclintMTimerState, > + num_harts), > VMSTATE_END_OF_LIST() > } > }; > diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h > index > 693415eb6defe4454e5731a681e025f3bac3ad2e..4b7406eec005a06b7c040d8483a8790866a39297 > 100644 > --- a/include/hw/intc/riscv_aclint.h > +++ b/include/hw/intc/riscv_aclint.h > @@ -80,4 +80,8 @@ enum { > RISCV_ACLINT_SWI_SIZE = 0x4000 > }; > > +#define VMSTATE_TIMER_PTR_VARRAY(_f, _s, _f_n) \ > +VMSTATE_VARRAY_OF_POINTER_UINT32(_f, _s, _f_n, 0, vmstate_info_timer, \ > + QEMUTimer *) > + > #endif > > -- > 2.43.0 > >
