hw/block/pflash_cfi02.c | 52 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-)
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
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!
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
© 2016 - 2026 Red Hat, Inc.