QEMU asserts in vhost due to hitting vhost backend limit on number of supported memory regions.
Instead of increasing limit in backends, describe all hotplugged memory as one continuos range to vhost with linear 1:1 HVA->GPA mapping in backend. It allows to avoid increasing VHOST_MEMORY_MAX_NREGIONS limit in kernel and refactoring current region lookup algorithm to a faster/scalable data structure. The same applies to vhost user which has even lower limit. Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- hw/virtio/vhost.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 01f1e04..49a7b2e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -419,6 +419,7 @@ static void vhost_set_memory(MemoryListener *listener, bool log_dirty = memory_region_is_logging(section->mr); int s = offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; + MemoryRegionSection rsvd_hva; void *ram; dev->mem = g_realloc(dev->mem, s); @@ -427,17 +428,25 @@ static void vhost_set_memory(MemoryListener *listener, add = false; } + rsvd_hva = memory_region_find_hva_range(section->mr); + if (rsvd_hva.mr) { + start_addr = rsvd_hva.offset_within_address_space; + size = int128_get64(rsvd_hva.size); + ram = memory_region_get_ram_ptr(rsvd_hva.mr); + } else { + ram = memory_region_get_ram_ptr(section->mr) + section->offset_within_region; + } + assert(size); /* Optimize no-change case. At least cirrus_vga does this a lot at this time. */ - ram = memory_region_get_ram_ptr(section->mr) + section->offset_within_region; if (add) { - if (!vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) { + if (!rsvd_hva.mr && !vhost_dev_cmp_memory(dev, start_addr, size, (uintptr_t)ram)) { /* Region exists with same address. Nothing to do. */ return; } } else { - if (!vhost_dev_find_reg(dev, start_addr, size)) { + if (!rsvd_hva.mr && !vhost_dev_find_reg(dev, start_addr, size)) { /* Removing region that we don't access. Nothing to do. */ return; } -- 1.8.3.1