migration/ram.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ qapi/migration.json | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+)
Introduce two new QMP commands to manage RAMBlock migratable state:
1. ram-block-set-migratable: Dynamically set a RAMBlock's migratable state
2. ram-block-get-migratable: Query a RAMBlock's migratable state
Signed-off-by: luzhipeng <luzhipeng@cestc.cn>
---
migration/ram.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
qapi/migration.json | 39 ++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/migration/ram.c b/migration/ram.c
index 979751f61b..8b4fd8226d 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -234,6 +234,54 @@ bool migrate_ram_is_ignored(RAMBlock *block)
&& qemu_ram_is_named_file(block));
}
+void qmp_ram_block_set_migratable(const char *name,
+ bool migratable, Error **errp)
+{
+ RAMBlock *rb = qemu_ram_block_by_name(name);
+ if (!rb) {
+ error_setg(errp, "RAMBlock '%s' not found", name);
+ return;
+ }
+
+ if (migration_is_running()) {
+ error_setg(errp, "Cannot modify RAMBlock migratable state
+ during migration");
+ return;
+ }
+
+ if (migratable) {
+ qemu_ram_set_migratable(rb);
+ info_report("RAMBlock '%s' marked as migratable", name);
+ } else {
+ qemu_ram_unset_migratable(rb);
+ info_report("RAMBlock '%s' marked as non-migratable", name);
+ }
+}
+
+/**
+ * qmp_ram_block_get_migratable:
+ * @name: Name of RAMBlock to query
+ * @errp: Error object
+ *
+ * Return: RamBlockMigratableInfo
+ */
+RamBlockMigratableInfo *qmp_ram_block_get_migratable(const char *name,
+ Error **errp)
+{
+ RAMBlock *rb;
+ RamBlockMigratableInfo *info = g_new0(RamBlockMigratableInfo, 1);
+ rb = qemu_ram_block_by_name(name);
+ if (!rb) {
+ g_free(info);
+ error_setg(errp, "RAMBlock '%s' not found", name);
+ return NULL;
+ }
+ info->migratable = qemu_ram_is_migratable(rb);
+ info_report("RAMBlock '%s' migratable state: %s", name,
+ info->migratable ? "true" : "false");
+ return info;
+}
+
#undef RAMBLOCK_FOREACH
int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque)
diff --git a/qapi/migration.json b/qapi/migration.json
index 7134d4ce47..483116db49 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -2233,3 +2233,42 @@
'data': { 'job-id': 'str',
'tag': 'str',
'devices': ['str'] } }
+
+##
+# @ram-block-set-migratable:
+#
+# Set the migratable state of a specific RAMBlock.
+#
+# @name: Name of the RAMBlock to modify
+# @migratable: true to enable migration for the RAMBlock,
+# false to disable
+#
+# Since: 11.1
+##
+{ 'command': 'ram-block-set-migratable',
+ 'data': { 'name': 'str', 'migratable': 'bool' } }
+
+##
+# @RamBlockMigratableInfo:
+#
+# Information about a RAMBlock's migratable state
+#
+# @migratable: true if the RAMBlock is migratable, false otherwise
+#
+# Since: 11.1
+##
+{ 'struct': 'RamBlockMigratableInfo', 'data': { 'migratable': 'bool' } }
+
+##
+# @ram-block-get-migratable:
+#
+# Get the migratable state of a specific RAMBlock.
+#
+# @name: Name of the RAMBlock to query
+#
+# Returns: RamBlockMigratableInfo containing the migratable state
+#
+# Since: 11.1
+##
+{ 'command': 'ram-block-get-migratable', 'data': { 'name': 'str' },
+ 'returns': 'RamBlockMigratableInfo' }
--
2.31.1
luzhipeng <luzhipeng@cestc.cn> writes:
> Introduce two new QMP commands to manage RAMBlock migratable state:
> 1. ram-block-set-migratable: Dynamically set a RAMBlock's migratable state
> 2. ram-block-get-migratable: Query a RAMBlock's migratable state
>
Hi! Could you provide more information on what are the use-cases for the
new commands?
In particular, what is the condition that can cause a ramblock to become
migratable/unmigratable at runtime that cannot be detected by QEMU
itself?
> Signed-off-by: luzhipeng <luzhipeng@cestc.cn>
> ---
> migration/ram.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
> qapi/migration.json | 39 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 87 insertions(+)
>
> diff --git a/migration/ram.c b/migration/ram.c
> index 979751f61b..8b4fd8226d 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -234,6 +234,54 @@ bool migrate_ram_is_ignored(RAMBlock *block)
> && qemu_ram_is_named_file(block));
> }
>
> +void qmp_ram_block_set_migratable(const char *name,
> + bool migratable, Error **errp)
> +{
> + RAMBlock *rb = qemu_ram_block_by_name(name);
> + if (!rb) {
> + error_setg(errp, "RAMBlock '%s' not found", name);
> + return;
> + }
> +
> + if (migration_is_running()) {
> + error_setg(errp, "Cannot modify RAMBlock migratable state
> + during migration");
> + return;
> + }
> +
> + if (migratable) {
> + qemu_ram_set_migratable(rb);
> + info_report("RAMBlock '%s' marked as migratable", name);
> + } else {
> + qemu_ram_unset_migratable(rb);
> + info_report("RAMBlock '%s' marked as non-migratable", name);
> + }
> +}
> +
> +/**
> + * qmp_ram_block_get_migratable:
> + * @name: Name of RAMBlock to query
> + * @errp: Error object
> + *
> + * Return: RamBlockMigratableInfo
> + */
> +RamBlockMigratableInfo *qmp_ram_block_get_migratable(const char *name,
> + Error **errp)
> +{
> + RAMBlock *rb;
> + RamBlockMigratableInfo *info = g_new0(RamBlockMigratableInfo, 1);
> + rb = qemu_ram_block_by_name(name);
> + if (!rb) {
> + g_free(info);
> + error_setg(errp, "RAMBlock '%s' not found", name);
> + return NULL;
> + }
> + info->migratable = qemu_ram_is_migratable(rb);
> + info_report("RAMBlock '%s' migratable state: %s", name,
> + info->migratable ? "true" : "false");
> + return info;
> +}
> +
> #undef RAMBLOCK_FOREACH
>
> int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque)
> diff --git a/qapi/migration.json b/qapi/migration.json
> index 7134d4ce47..483116db49 100644
> --- a/qapi/migration.json
> +++ b/qapi/migration.json
> @@ -2233,3 +2233,42 @@
> 'data': { 'job-id': 'str',
> 'tag': 'str',
> 'devices': ['str'] } }
> +
> +##
> +# @ram-block-set-migratable:
> +#
> +# Set the migratable state of a specific RAMBlock.
> +#
> +# @name: Name of the RAMBlock to modify
> +# @migratable: true to enable migration for the RAMBlock,
> +# false to disable
> +#
> +# Since: 11.1
> +##
> +{ 'command': 'ram-block-set-migratable',
> + 'data': { 'name': 'str', 'migratable': 'bool' } }
> +
> +##
> +# @RamBlockMigratableInfo:
> +#
> +# Information about a RAMBlock's migratable state
> +#
> +# @migratable: true if the RAMBlock is migratable, false otherwise
> +#
> +# Since: 11.1
> +##
> +{ 'struct': 'RamBlockMigratableInfo', 'data': { 'migratable': 'bool' } }
> +
> +##
> +# @ram-block-get-migratable:
> +#
> +# Get the migratable state of a specific RAMBlock.
> +#
> +# @name: Name of the RAMBlock to query
> +#
> +# Returns: RamBlockMigratableInfo containing the migratable state
> +#
> +# Since: 11.1
> +##
> +{ 'command': 'ram-block-get-migratable', 'data': { 'name': 'str' },
> + 'returns': 'RamBlockMigratableInfo' }
On Wed, Mar 11, 2026 at 09:47:29AM -0300, Fabiano Rosas wrote: > luzhipeng <luzhipeng@cestc.cn> writes: > > > Introduce two new QMP commands to manage RAMBlock migratable state: > > 1. ram-block-set-migratable: Dynamically set a RAMBlock's migratable state > > 2. ram-block-get-migratable: Query a RAMBlock's migratable state > > > > Hi! Could you provide more information on what are the use-cases for the > new commands? > > In particular, what is the condition that can cause a ramblock to become > migratable/unmigratable at runtime that cannot be detected by QEMU > itself? Or instead of saying "detected" maybe it's "decided" by QEMU. The QEMU cmdline and rest (e.g. a set of QMP commands to create the devices that needs to happen on both sides, or migration caps/params like x-ignore-shared) normally decides whether a ramblock should be migrated, and AFAIU that's part of the guest ABI. I think it may make more sense if we want to avoid migrating some ramblocks then we provide some similar way (e.g. a object property of the memory backend) rather than allowing it to be flipped anytime, causing more unpredictable guest ABI. Thanks, -- Peter Xu
© 2016 - 2026 Red Hat, Inc.