diff options
| author | TANG Tiancheng <lyndra@linux.alibaba.com> | 2025-09-11 17:56:15 +0800 |
|---|---|---|
| committer | Alistair Francis <alistair.francis@wdc.com> | 2025-10-03 13:15:14 +1000 |
| commit | 09f89ccc9763a20c0cf9030661af2c04647c1eec (patch) | |
| tree | 52242f58998a589cf6174a21cbedf11f493c1101 | |
| parent | 30478e2ff7839a692c3894ae5f6c28e780f0bc6d (diff) | |
| download | focaccia-qemu-09f89ccc9763a20c0cf9030661af2c04647c1eec.tar.gz focaccia-qemu-09f89ccc9763a20c0cf9030661af2c04647c1eec.zip | |
hw/intc: Save timers array in RISC-V mtimer VMState
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 <zhiwei_liu@linux.alibaba.com> Signed-off-by: TANG Tiancheng <lyndra@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20250911-timers-v3-3-60508f640050@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
| -rw-r--r-- | hw/intc/riscv_aclint.c | 6 | ||||
| -rw-r--r-- | 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 318a9c8248..9f4c36e965 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 693415eb6d..4b7406eec0 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 |