Steve Sistare <steven.sist...@oracle.com> writes: > For cpr-exec mode, ramblock_is_ignored is always true, and the address of > each migrated memory region must match the address of the statically > initialized region on the target. However, for a PCI rom block, the region > address is set when the guest writes to a BAR on the source, which does not > occur on the target, causing a "Mismatched GPAs" error during cpr-exec > migration. > > To fix, unconditionally set the target's address to the source's address > if the region does not have an address yet. > > Signed-off-by: Steve Sistare <steven.sist...@oracle.com>
Just a detail below. Reviewed-by: Fabiano Rosas <faro...@suse.de> > --- > include/exec/memory.h | 12 ++++++++++++ > migration/ram.c | 15 +++++++++------ > system/memory.c | 10 ++++++++-- > 3 files changed, 29 insertions(+), 8 deletions(-) > > diff --git a/include/exec/memory.h b/include/exec/memory.h > index d337737..4f654b0 100644 > --- a/include/exec/memory.h > +++ b/include/exec/memory.h > @@ -801,6 +801,7 @@ struct MemoryRegion { > bool unmergeable; > uint8_t dirty_log_mask; > bool is_iommu; > + bool has_addr; This field is not used during memory access, maybe move it down below to preserve the hole for future usage. > RAMBlock *ram_block; > Object *owner; > /* owner as TYPE_DEVICE. Used for re-entrancy checks in MR access > hotpath */ > @@ -2402,6 +2403,17 @@ void memory_region_set_enabled(MemoryRegion *mr, bool > enabled); > void memory_region_set_address(MemoryRegion *mr, hwaddr addr); > > /* > + * memory_region_set_address_only: set the address of a region. > + * > + * Same as memory_region_set_address, but without causing transaction side > + * effects. > + * > + * @mr: the region to be updated > + * @addr: new address, relative to container region > + */ > +void memory_region_set_address_only(MemoryRegion *mr, hwaddr addr); > + > +/* > * memory_region_set_size: dynamically update the size of a region. > * > * Dynamically updates the size of a region. > diff --git a/migration/ram.c b/migration/ram.c > index add285b..7b8d7f6 100644 > --- a/migration/ram.c > +++ b/migration/ram.c > @@ -4196,12 +4196,15 @@ static int parse_ramblock(QEMUFile *f, RAMBlock > *block, ram_addr_t length) > } > if (migrate_ignore_shared()) { > hwaddr addr = qemu_get_be64(f); > - if (migrate_ram_is_ignored(block) && > - block->mr->addr != addr) { > - error_report("Mismatched GPAs for block %s " > - "%" PRId64 "!= %" PRId64, block->idstr, > - (uint64_t)addr, (uint64_t)block->mr->addr); > - return -EINVAL; > + if (migrate_ram_is_ignored(block)) { > + if (!block->mr->has_addr) { > + memory_region_set_address_only(block->mr, addr); > + } else if (block->mr->addr != addr) { > + error_report("Mismatched GPAs for block %s " > + "%" PRId64 "!= %" PRId64, block->idstr, > + (uint64_t)addr, (uint64_t)block->mr->addr); > + return -EINVAL; > + } > } > } > ret = rdma_block_notification_handle(f, block->idstr); > diff --git a/system/memory.c b/system/memory.c > index ca04a0e..3c72504 100644 > --- a/system/memory.c > +++ b/system/memory.c > @@ -2665,7 +2665,7 @@ static void > memory_region_add_subregion_common(MemoryRegion *mr, > for (alias = subregion->alias; alias; alias = alias->alias) { > alias->mapped_via_alias++; > } > - subregion->addr = offset; > + memory_region_set_address_only(subregion, offset); > memory_region_update_container_subregions(subregion); > } > > @@ -2745,10 +2745,16 @@ static void > memory_region_readd_subregion(MemoryRegion *mr) > } > } > > +void memory_region_set_address_only(MemoryRegion *mr, hwaddr addr) > +{ > + mr->addr = addr; > + mr->has_addr = true; > +} > + > void memory_region_set_address(MemoryRegion *mr, hwaddr addr) > { > if (addr != mr->addr) { > - mr->addr = addr; > + memory_region_set_address_only(mr, addr); > memory_region_readd_subregion(mr); > } > }