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 <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
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 1427949b72cd..e8ec6a152af4 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