[PATCH v2] hw/block: Add migration support for pflash_cfi02.c

Om Barkare posted 1 patch 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260827193942.69406-1-ombarkare123@gmail.com
Maintainers: "Philippe Mathieu-Daudé" <philmd@mailo.com>, Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>
hw/block/pflash_cfi02.c | 52 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 51 insertions(+), 1 deletion(-)
[PATCH v2] hw/block: Add migration support for pflash_cfi02.c
Posted by Om Barkare 1 month ago
From: OmBarkare <ombarkare123@gmail.com>

Device did not have migration support, which would result in its
internal state being lost during migration or saves.

Add VMStateDescription to serialize state and set memory regions
romd_mode to rom_mode field in post load hook

total_sectors was changed from uint32_t to int32_t to satisfy the
VMSTATE_BITMAP macro's _field_size argument, but that is OK because
it's a value is calculated using the size of the flash and it will
never be large enough to overflow int32_t

The only boards using pflash_cfi02 are the sh4 r2d and
the arm canon-a1100, musicpal and xilinx-zynq-a9

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4157

Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Om Barkare <ombarkare123@gmail.com>
---
Changes since v1
- Add "bypass" to vmstate
- Remove the vmstate subsection and add these states to the main vmstate
  instead
- Remove the pflash_erase_sector_needed function which was related to
  the subsection as no longer needed

 hw/block/pflash_cfi02.c | 52 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 6f952fe7de..4f72c438c0 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -46,6 +46,7 @@
 #include "qemu/module.h"
 #include "hw/core/sysbus.h"
 #include "migration/vmstate.h"
+#include "system/runstate.h"
 #include "trace.h"
 
 #define PFLASH_LAZY_ROMD_THRESHOLD 42
@@ -71,7 +72,7 @@ struct PFlashCFI02 {
     BlockBackend *blk;
     uint32_t uniform_nb_blocs;
     uint32_t uniform_sector_len;
-    uint32_t total_sectors;
+    int32_t total_sectors;
     uint32_t nb_blocs[PFLASH_MAX_ERASE_REGIONS];
     uint32_t sector_len[PFLASH_MAX_ERASE_REGIONS];
     uint32_t chip_len;
@@ -107,6 +108,29 @@ struct PFlashCFI02 {
     unsigned long *sector_erase_map;
     char *name;
     void *storage;
+    VMChangeStateEntry *vmstate;
+};
+
+static int pflash_post_load(void *opaque, int version_id);
+
+static const VMStateDescription vmstate_pflash = {
+    .name = "pflash_cfi02",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = pflash_post_load,
+    .fields = (const VMStateField[]) {
+        VMSTATE_INT32(wcycle, PFlashCFI02),
+        VMSTATE_INT32(bypass, PFlashCFI02),
+        VMSTATE_UINT8(cmd, PFlashCFI02),
+        VMSTATE_UINT8(status, PFlashCFI02),
+        VMSTATE_TIMER(timer, PFlashCFI02),
+        VMSTATE_BOOL(rom_mode, PFlashCFI02),
+        VMSTATE_INT32(read_counter, PFlashCFI02),
+        VMSTATE_INT32(sectors_to_erase, PFlashCFI02),
+        VMSTATE_UINT64(erase_time_remaining, PFlashCFI02),
+        VMSTATE_BITMAP(sector_erase_map, PFlashCFI02, 1, total_sectors),
+        VMSTATE_END_OF_LIST()
+    }
 };
 
 /*
@@ -976,6 +1000,7 @@ static void pflash_cfi02_class_init(ObjectClass *klass, const void *data)
     device_class_set_legacy_reset(dc, pflash_cfi02_reset);
     dc->unrealize = pflash_cfi02_unrealize;
     device_class_set_props(dc, pflash_cfi02_properties);
+    dc->vmsd = &vmstate_pflash;
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 }
 
@@ -1028,3 +1053,28 @@ PFlashCFI02 *pflash_cfi02_register(hwaddr base,
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
     return PFLASH_CFI02(dev);
 }
+
+static void postload_update_cb(void *opaque, bool running, RunState state)
+{
+    PFlashCFI02 *pfl = opaque;
+
+    /* This is called after bdrv_activate_all.  */
+    qemu_del_vm_change_state_handler(pfl->vmstate);
+    pfl->vmstate = NULL;
+
+    trace_pflash_postload_cb(pfl->name);
+    pflash_update(pfl, 0, pfl->chip_len);
+}
+
+static int pflash_post_load(void *opaque, int version_id)
+{
+    PFlashCFI02 *pfl = opaque;
+
+    if (!pfl->ro) {
+        pfl->vmstate = qemu_add_vm_change_state_handler(postload_update_cb, pfl);
+    }
+
+    memory_region_rom_device_set_romd(&pfl->orig_mem, pfl->rom_mode);
+
+    return 0;
+}
-- 
2.55.0
Re: [PATCH v2] hw/block: Add migration support for pflash_cfi02.c
Posted by Philippe Mathieu-Daudé 3 weeks, 3 days ago
On 27/8/26 21:39, Om Barkare wrote:
> From: OmBarkare <ombarkare123@gmail.com>
> 
> Device did not have migration support, which would result in its
> internal state being lost during migration or saves.
> 
> Add VMStateDescription to serialize state and set memory regions
> romd_mode to rom_mode field in post load hook
> 
> total_sectors was changed from uint32_t to int32_t to satisfy the
> VMSTATE_BITMAP macro's _field_size argument, but that is OK because
> it's a value is calculated using the size of the flash and it will
> never be large enough to overflow int32_t
> 
> The only boards using pflash_cfi02 are the sh4 r2d and
> the arm canon-a1100, musicpal and xilinx-zynq-a9
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4157
> 
> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Om Barkare <ombarkare123@gmail.com>
> ---
> Changes since v1
> - Add "bypass" to vmstate
> - Remove the vmstate subsection and add these states to the main vmstate
>    instead
> - Remove the pflash_erase_sector_needed function which was related to
>    the subsection as no longer needed
> 
>   hw/block/pflash_cfi02.c | 52 ++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 51 insertions(+), 1 deletion(-)

Queued, thanks!
Re: [PATCH v2] hw/block: Add migration support for pflash_cfi02.c
Posted by Peter Maydell 3 weeks, 5 days ago
On Thu, 27 Aug 2026 at 20:40, Om Barkare <ombarkare123@gmail.com> wrote:
>
> From: OmBarkare <ombarkare123@gmail.com>
>
> Device did not have migration support, which would result in its
> internal state being lost during migration or saves.
>
> Add VMStateDescription to serialize state and set memory regions
> romd_mode to rom_mode field in post load hook
>
> total_sectors was changed from uint32_t to int32_t to satisfy the
> VMSTATE_BITMAP macro's _field_size argument, but that is OK because
> it's a value is calculated using the size of the flash and it will
> never be large enough to overflow int32_t
>
> The only boards using pflash_cfi02 are the sh4 r2d and
> the arm canon-a1100, musicpal and xilinx-zynq-a9
>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4157
>
> Suggested-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Om Barkare <ombarkare123@gmail.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM