The RAM migration code assumes that the set of migratable RAMBlocks and their idstr values do not change while migration is running. Add RAMBlockNotifier callbacks for RAM_MIGRATABLE flag and idstr changes so migration can detect attempts to make such changes at runtime and abort with a clear error.
Signed-off-by: Akihiko Odaki <[email protected]> --- include/system/ramlist.h | 6 ++++++ hw/core/numa.c | 36 ++++++++++++++++++++++++++++++++++++ system/physmem.c | 9 +++++++++ 3 files changed, 51 insertions(+) diff --git a/include/system/ramlist.h b/include/system/ramlist.h index 32157cc84305..e96de5573eed 100644 --- a/include/system/ramlist.h +++ b/include/system/ramlist.h @@ -66,6 +66,9 @@ struct RAMBlockNotifier { void *host, size_t size, size_t max_size); void (*ram_block_removed)(RAMBlockNotifier *n, const RAMBlock *rb, void *host, size_t size, size_t max_size); + void (*ram_block_set_migratable)(RAMBlockNotifier *n, const RAMBlock *rb); + void (*ram_block_unset_migratable)(RAMBlockNotifier *n, const RAMBlock *rb); + void (*ram_block_set_idstr)(RAMBlockNotifier *n, const RAMBlock *rb); void (*ram_block_resized)(RAMBlockNotifier *n, RAMBlock *rb, size_t new_size); QLIST_ENTRY(RAMBlockNotifier) next; @@ -81,6 +84,9 @@ void ram_block_notify_add(const RAMBlock *rb, void *host, size_t size, size_t max_size); void ram_block_notify_remove(const RAMBlock *rb, void *host, size_t size, size_t max_size); +void ram_block_notify_set_migratable(const RAMBlock *rb); +void ram_block_notify_unset_migratable(const RAMBlock *rb); +void ram_block_notify_set_idstr(const RAMBlock *rb); void ram_block_notify_resize(RAMBlock *rb, size_t new_size); GString *ram_block_format(void); diff --git a/hw/core/numa.c b/hw/core/numa.c index 40acb98bdd0b..0685cd1c6ccc 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -887,6 +887,42 @@ void ram_block_notify_remove(const RAMBlock *rb, } } +void ram_block_notify_set_migratable(const RAMBlock *rb) +{ + RAMBlockNotifier *notifier; + RAMBlockNotifier *next; + + QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) { + if (notifier->ram_block_set_migratable) { + notifier->ram_block_set_migratable(notifier, rb); + } + } +} + +void ram_block_notify_unset_migratable(const RAMBlock *rb) +{ + RAMBlockNotifier *notifier; + RAMBlockNotifier *next; + + QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) { + if (notifier->ram_block_unset_migratable) { + notifier->ram_block_unset_migratable(notifier, rb); + } + } +} + +void ram_block_notify_set_idstr(const RAMBlock *rb) +{ + RAMBlockNotifier *notifier; + RAMBlockNotifier *next; + + QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) { + if (notifier->ram_block_set_idstr) { + notifier->ram_block_set_idstr(notifier, rb); + } + } +} + void ram_block_notify_resize(RAMBlock *rb, size_t new_size) { RAMBlockNotifier *notifier; diff --git a/system/physmem.c b/system/physmem.c index 6d00e99270c7..83c9243236a5 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1911,11 +1911,17 @@ bool qemu_ram_is_migratable(const RAMBlock *rb) void qemu_ram_set_migratable(RAMBlock *rb) { + /* Notify before modifying the ram block. */ + ram_block_notify_set_migratable(rb); + rb->flags |= RAM_MIGRATABLE; } void qemu_ram_unset_migratable(RAMBlock *rb) { + /* Notify before modifying the ram block. */ + ram_block_notify_unset_migratable(rb); + rb->flags &= ~RAM_MIGRATABLE; } @@ -1937,6 +1943,9 @@ void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) assert(new_block); assert(!new_block->idstr[0]); + /* Notify before modifying the ram block. */ + ram_block_notify_set_idstr(new_block); + if (dev) { char *id = qdev_get_dev_path(dev); if (id) { -- 2.54.0
