From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50126) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z07h4-0004Gx-NB for qemu-devel@nongnu.org; Wed, 03 Jun 2015 08:22:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z07gy-0002qO-5Q for qemu-devel@nongnu.org; Wed, 03 Jun 2015 08:22:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48109) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z07gy-0002qK-0u for qemu-devel@nongnu.org; Wed, 03 Jun 2015 08:22:44 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id B24A2B8BD0 for ; Wed, 3 Jun 2015 12:22:43 +0000 (UTC) From: Igor Mammedov Date: Wed, 3 Jun 2015 14:22:37 +0200 Message-Id: <1433334157-37665-3-git-send-email-imammedo@redhat.com> In-Reply-To: <1433334157-37665-1-git-send-email-imammedo@redhat.com> References: <1433334157-37665-1-git-send-email-imammedo@redhat.com> Subject: [Qemu-devel] [RFC 2/2] pc: fix QEMU crashing when more than ~50 memory hotplugged List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, mst@redhat.com QEMU assert in vhost due to hitting vhost bachend limit on number of supported memory regions. Instead of increasing limit in backends, describe all hotlugged memory as one continuos range to vhost that implements 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 datastructure. The same applies to vhost user which has even lower limit. Signed-off-by: Igor Mammedov --- hw/i386/pc.c | 4 ++-- hw/virtio/vhost.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1eb1db0..c722339 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1306,8 +1306,8 @@ FWCfgState *pc_memory_init(MachineState *machine, exit(EXIT_FAILURE); } - memory_region_init(&pcms->hotplug_memory, OBJECT(pcms), - "hotplug-memory", hotplug_mem_size); + memory_region_init_rsvd_hva(&pcms->hotplug_memory, OBJECT(pcms), + "hotplug-memory", hotplug_mem_size); memory_region_add_subregion(system_memory, pcms->hotplug_memory_base, &pcms->hotplug_memory); } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 54851b7..44cfaab 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -380,6 +380,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); @@ -388,17 +389,25 @@ static void vhost_set_memory(MemoryListener *listener, add = false; } + rsvd_hva = memory_region_find_rsvd_hva(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