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
>
>

Reply via email to