Message ID | 20200403101827.30664-4-shameerali.kolothum.thodi@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | acpi: Fixes for inconsistency in ACPI MR size during migration | expand |
On 4/3/20 12:18 PM, Shameer Kolothum wrote: > From: David Hildenbrand <david@redhat.com> > > Summarizing the issue: > 1. Memory regions contain ram blocks with a different size, if the > size is not properly aligned. While memory regions can have an > unaligned size, ram blocks can't. This is true when creating > resizable memory region with an unaligned size. > 2. When resizing a ram block/memory region, the size of the memory > region is set to the aligned size. The callback is called with > the aligned size. The unaligned piece is lost. > > Because of the above, if ACPI blob length modifications happens > after the initial virt_acpi_build() call, and the changed blob > length is within the PAGE size boundary, then the revised size > is not seen by the firmware on Guest reboot. > > Hence make sure callback is called if memory region size is changed, > irrespective of aligned or not. > > Signed-off-by: David Hildenbrand <david@redhat.com> > [Shameer: added commit log] > Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> > Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> > --- > Please find previous discussion here, > https://patchwork.kernel.org/patch/11432375/#23216751 > --- > exec.c | 16 ++++++++++++++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/exec.c b/exec.c > index de9d949902..2874bb5088 100644 > --- a/exec.c > +++ b/exec.c > @@ -2074,11 +2074,23 @@ static int memory_try_enable_merging(void *addr, size_t len) > */ > int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) > { > + const ram_addr_t unaligned_size = newsize; > + > assert(block); > > newsize = HOST_PAGE_ALIGN(newsize); > > if (block->used_length == newsize) { > + /* > + * We don't have to resize the ram block (which only knows aligned > + * sizes), however, we have to notify if the unaligned size changed. > + */ > + if (unaligned_size != memory_region_size(block->mr)) { > + memory_region_set_size(block->mr, unaligned_size); > + if (block->resized) { > + block->resized(block->idstr, unaligned_size, block->host); > + } > + } > return 0; > } > > @@ -2102,9 +2114,9 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) > block->used_length = newsize; > cpu_physical_memory_set_dirty_range(block->offset, block->used_length, > DIRTY_CLIENTS_ALL); > - memory_region_set_size(block->mr, newsize); > + memory_region_set_size(block->mr, unaligned_size); > if (block->resized) { > - block->resized(block->idstr, newsize, block->host); > + block->resized(block->idstr, unaligned_size, block->host); > } > return 0; > } >
diff --git a/exec.c b/exec.c index de9d949902..2874bb5088 100644 --- a/exec.c +++ b/exec.c @@ -2074,11 +2074,23 @@ static int memory_try_enable_merging(void *addr, size_t len) */ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) { + const ram_addr_t unaligned_size = newsize; + assert(block); newsize = HOST_PAGE_ALIGN(newsize); if (block->used_length == newsize) { + /* + * We don't have to resize the ram block (which only knows aligned + * sizes), however, we have to notify if the unaligned size changed. + */ + if (unaligned_size != memory_region_size(block->mr)) { + memory_region_set_size(block->mr, unaligned_size); + if (block->resized) { + block->resized(block->idstr, unaligned_size, block->host); + } + } return 0; } @@ -2102,9 +2114,9 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) block->used_length = newsize; cpu_physical_memory_set_dirty_range(block->offset, block->used_length, DIRTY_CLIENTS_ALL); - memory_region_set_size(block->mr, newsize); + memory_region_set_size(block->mr, unaligned_size); if (block->resized) { - block->resized(block->idstr, newsize, block->host); + block->resized(block->idstr, unaligned_size, block->host); } return 0; }