[PATCH] hw/block: Add migration support for pflash_cfi02.c
Om Barkare <[email protected]>
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
From: OmBarkare <[email protected]> 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 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4157 Signed-off-by: Om Barkare <[email protected]> --- hw/block/pflash_cfi02.c | 73 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 6f952fe7de..82965e6cdc 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,50 @@ struct PFlashCFI02 { unsigned long *sector_erase_map; char *name; void *storage; + VMChangeStateEntry *vmstate; +}; + +static int pflash_post_load(void *opaque, int version_id); + +static bool pflash_sector_erase_needed(void *opaque) +{ + PFlashCFI02 *pfl = opaque; + + return (pfl->sectors_to_erase > 0); +} + +static const VMStateDescription vmstate_pflash_sector_erase = { + .name = "pflash_cfi02_erase_sector", + .version_id = 1, + .minimum_version_id = 1, + .needed = pflash_sector_erase_needed, + .fields = (const VMStateField[]) { + 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() + } + +}; + +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_UINT8(cmd, PFlashCFI02), + VMSTATE_UINT8(status, PFlashCFI02), + VMSTATE_INT32(read_counter, PFlashCFI02), + VMSTATE_BOOL(rom_mode, PFlashCFI02), + VMSTATE_TIMER(timer, PFlashCFI02), + VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * const []) { + &vmstate_pflash_sector_erase, + NULL + } }; /* @@ -976,6 +1021,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 +1074,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