Commit 18269069c310 ("migration: Introduce ignore-shared capability") addes a ignore-shared capability to bypass the shared ramblock (e,g, membackend + numa node). It does good to live migration.
This commit expected that QEMU doesn't write to guest RAM until VM starts, but it does on aarch64 qemu: Backtrace: 1 0x000055f4a296dd84 in address_space_write_rom_internal () at exec.c:3458 2 0x000055f4a296de3a in address_space_write_rom () at exec.c:3479 3 0x000055f4a2d519ff in rom_reset () at hw/core/loader.c:1101 4 0x000055f4a2d475ec in qemu_devices_reset () at hw/core/reset.c:69 5 0x000055f4a2c90a28 in qemu_system_reset () at vl.c:1675 6 0x000055f4a2c9851d in main () at vl.c:4552 In address_space_write_rom_internal, if the ramblock is RAM of ramblock_is_ignored(), memcpy this ramblock will cause the memory-backend file corruption. But in normal case (!in_incoming_migration), this logic should be reserved. Fixes: commit 18269069c310 ("migration: Introduce ignore-shared capability") Signed-off-by: Catherine Ho <catherine.h...@gmail.com> Suggested-by: Yury Kotov <yury-ko...@yandex-team.ru> --- exec.c | 4 ++++ include/exec/cpu-common.h | 1 + include/qemu/option.h | 1 + migration/ram.c | 2 +- vl.c | 2 ++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 86a38d3b3b..f08321fb7a 100644 --- a/exec.c +++ b/exec.c @@ -47,6 +47,7 @@ #include "exec/address-spaces.h" #include "sysemu/xen-mapcache.h" #include "trace-root.h" +#include "qemu/option.h" #ifdef CONFIG_FALLOCATE_PUNCH_HOLE #include <linux/falloc.h> @@ -3455,6 +3456,9 @@ static inline MemTxResult address_space_write_rom_internal(AddressSpace *as, l = memory_access_size(mr, l, addr1); } else { /* ROM/RAM case */ + if (in_incoming_migration && ramblock_is_ignored(mr->ram_block)) { + break; + } ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (type) { case WRITE_DATA: diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index cef8b88a2a..c80b7248a6 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -76,6 +76,7 @@ void *qemu_ram_get_host_addr(RAMBlock *rb); ram_addr_t qemu_ram_get_offset(RAMBlock *rb); ram_addr_t qemu_ram_get_used_length(RAMBlock *rb); bool qemu_ram_is_shared(RAMBlock *rb); +bool ramblock_is_ignored(RAMBlock *block); bool qemu_ram_is_uf_zeroable(RAMBlock *rb); void qemu_ram_set_uf_zeroable(RAMBlock *rb); bool qemu_ram_is_migratable(RAMBlock *rb); diff --git a/include/qemu/option.h b/include/qemu/option.h index 844587cab3..7509435164 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -139,4 +139,5 @@ QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); QDict *keyval_parse(const char *params, const char *implied_key, Error **errp); +extern bool in_incoming_migration; #endif diff --git a/migration/ram.c b/migration/ram.c index 35bd6213e9..d6de9d335d 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -159,7 +159,7 @@ out: return ret; } -static bool ramblock_is_ignored(RAMBlock *block) +bool ramblock_is_ignored(RAMBlock *block) { return !qemu_ram_is_migratable(block) || (migrate_ignore_shared() && qemu_ram_is_shared(block)); diff --git a/vl.c b/vl.c index c1d5484e12..b79aec9ac3 100644 --- a/vl.c +++ b/vl.c @@ -145,6 +145,7 @@ bool enable_cpu_pm = false; int nb_nics; NICInfo nd_table[MAX_NICS]; int autostart; +bool in_incoming_migration; static enum { RTC_BASE_UTC, RTC_BASE_LOCALTIME, @@ -3797,6 +3798,7 @@ int main(int argc, char **argv, char **envp) runstate_set(RUN_STATE_INMIGRATE); } incoming = optarg; + in_incoming_migration = true; break; case QEMU_OPTION_only_migratable: /* -- 2.17.1