The VMSTATE_PTIMER macro is defined to pass a 'version' argument of 1
to VMSTATE_STRUCT_POINTER_TEST_V. This means that the field will
only be used in migration when the vmstate struct that uses
VMSTATE_PTIMER has a version_id of at least 1. This doesn't match
how we define other VMSTATE_FOO which don't take an explicit
version_id, which is to use a version argument of 0 (e.g. all the
common macros like VMSTATE_UINT32 are written to pass 0 to their
VMSTATE_UINT32_V counterparts, and so on). It also doesn't match
how we define VMSTATE_PTIMER_ARRAY.
The practical effect of this is that users of VMSTATE_PTIMER in
vmstate structs which explicitly or implicitly have a version_id of 0
were actually not getting their ptimers migrated.
This affects:
vmstate_xlnx_csu_dma in wh/dma/xlnx_csu_dma.c
vmstate_k230_wdt in hw/watchdog/k230_wdt.c
which are used in:
* Arm Xilinx versal and zynq machines
* RISC-V K230 machine
Most ptimer users are unaffected because they took the usual approach
of explicitly setting their starting version_id to 1.
Fix the version_id in this field. This is a migration compatibility
break for all the above listed devices/machines. Since the timers
involved are in devices where the timer is usually stopped (e.g. the
watchdogs only have the timer active when the watchdog is enabled and
counting down), the consequences of the bug are likely not visible to
most users.
We could perhaps attempt to preserve migration compatibility here,
but none of the affected machine types are versioned and so we do not
promise cross-version compatibility, so do the simple thing. Bump
the version_id and version_id on the two affected vmstate structs so
that attempted migration between old and new QEMU fails cleanly.
Fixes: 852f771ec9e5c ("vmstate: port pmtimer")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4705
Signed-off-by: Peter Maydell <[email protected]>
---
Not cc: stable because it's a migration format change and we
don't generally backport those
---
include/hw/core/ptimer.h | 2 +-
hw/dma/xlnx_csu_dma.c | 4 ++--
hw/watchdog/k230_wdt.c | 2 ++
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/include/hw/core/ptimer.h b/include/hw/core/ptimer.h
index 4dc02b0de47..8513f8917e3 100644
--- a/include/hw/core/ptimer.h
+++ b/include/hw/core/ptimer.h
@@ -300,7 +300,7 @@ void ptimer_stop(ptimer_state *s);
extern const VMStateDescription vmstate_ptimer;
#define VMSTATE_PTIMER(_field, _state) \
- VMSTATE_STRUCT_POINTER_V(_field, _state, 1, vmstate_ptimer, ptimer_state)
+ VMSTATE_STRUCT_POINTER_V(_field, _state, 0, vmstate_ptimer, ptimer_state)
#define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \
VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \
diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c
index 436f9915e02..ea703dc00ce 100644
--- a/hw/dma/xlnx_csu_dma.c
+++ b/hw/dma/xlnx_csu_dma.c
@@ -679,8 +679,8 @@ static void xlnx_csu_dma_realize(DeviceState *dev, Error
**errp)
static const VMStateDescription vmstate_xlnx_csu_dma = {
.name = TYPE_XLNX_CSU_DMA,
- .version_id = 0,
- .minimum_version_id = 0,
+ .version_id = 1,
+ .minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_PTIMER(src_timer, XlnxCSUDMA),
VMSTATE_UINT16(width, XlnxCSUDMA),
diff --git a/hw/watchdog/k230_wdt.c b/hw/watchdog/k230_wdt.c
index 1f83b499e82..fba2013b8f3 100644
--- a/hw/watchdog/k230_wdt.c
+++ b/hw/watchdog/k230_wdt.c
@@ -234,6 +234,8 @@ static const MemoryRegionOps k230_wdt_ops = {
static const VMStateDescription vmstate_k230_wdt = {
.name = "k230.wdt",
+ .version_id = 1,
+ .minimum_version_id = 1,
.fields = (const VMStateField[]) {
VMSTATE_PTIMER(timer, K230WdtState),
VMSTATE_UINT32(cr, K230WdtState),
--
2.43.0