From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981566016702.6613047628249; Wed, 29 Nov 2017 10:52:46 -0800 (PST) Received: from localhost ([::1]:44710 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7TL-00029w-9K for importer@patchew.org; Wed, 29 Nov 2017 13:52:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49045) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7RS-00010l-Q8 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7RR-0001RG-Ul for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:42 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56362) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7RR-0001Qn-O6 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:41 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 64AED8765D for ; Wed, 29 Nov 2017 18:50:40 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id C64BF60605; Wed, 29 Nov 2017 18:50:36 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:20 +0000 Message-Id: <20171129185026.23632-2-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 29 Nov 2017 18:50:40 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 1/7] memory: address_space_iterate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Iterate through an address space calling a function for each section. The iteration is done in order. Signed-off-by: Dr. David Alan Gilbert --- include/exec/memory.h | 23 +++++++++++++++++++++++ memory.c | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index 5ed4042f87..f5a9df642e 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1987,6 +1987,29 @@ address_space_write_cached(MemoryRegionCache *cache,= hwaddr addr, address_space_write(cache->as, cache->xlat + addr, MEMTXATTRS_UNSPECIF= IED, buf, len); } =20 +/** + * ASIterateCallback: Function type called by address_space_iterate + * + * Return 0 on success or a negative error code. + * + * @mrs: Memory region section for this range + * @opaque: The opaque value passed in to the iterator. + */ +typedef int (*ASIterateCallback)(MemoryRegionSection *mrs, void *opaque); + +/** + * address_space_iterate: Call the function for each address range in the + * AddressSpace, in sorted order. + * + * Return 0 on success or a negative error code. + * + * @as: Address space to iterate over + * @cb: Function to call. If the function returns none-0 the iteration wi= ll + * stop. + * @opaque: Value to pass to the function + */ +int +address_space_iterate(AddressSpace *as, ASIterateCallback cb, void *opaque= ); #endif =20 #endif diff --git a/memory.c b/memory.c index e26e5a3b1d..f45137f25e 100644 --- a/memory.c +++ b/memory.c @@ -2810,6 +2810,28 @@ void address_space_destroy(AddressSpace *as) call_rcu(as, do_address_space_destroy, rcu); } =20 +int address_space_iterate(AddressSpace *as, ASIterateCallback cb, + void *opaque) +{ + int res =3D 0; + FlatView *fv =3D address_space_to_flatview(as); + FlatRange *range; + + flatview_ref(fv); + + FOR_EACH_FLAT_RANGE(range, fv) { + MemoryRegionSection mrs =3D section_from_flat_range(range, fv); + res =3D cb(&mrs, opaque); + if (res) { + break; + } + } + + flatview_unref(fv); + + return res; +} + static const char *memory_region_type(MemoryRegion *mr) { if (memory_region_is_ram_device(mr)) { --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981717546890.9736856911703; Wed, 29 Nov 2017 10:55:17 -0800 (PST) Received: from localhost ([::1]:44723 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Vs-0004NB-Oa for importer@patchew.org; Wed, 29 Nov 2017 13:55:16 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49056) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7RU-00010o-51 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7RT-0001Rh-DJ for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:44 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34886) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7RT-0001RR-69 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:43 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3FE496146F for ; Wed, 29 Nov 2017 18:50:42 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id ADCFD60605; Wed, 29 Nov 2017 18:50:40 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:21 +0000 Message-Id: <20171129185026.23632-3-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 29 Nov 2017 18:50:42 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 2/7] vhost: Move log_dirty check X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Move the log_dirty check into vhost_section. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/trace-events | 3 +++ hw/virtio/vhost.c | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 775461ae98..4a493bcd46 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -1,5 +1,8 @@ # See docs/devel/tracing.txt for syntax documentation. =20 +# hw/virtio/vhost.c +vhost_section(const char *name, int r) "%s:%d" + # hw/virtio/virtio.c virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned o= ut_num) "elem %p size %zd in_num %u out_num %u" virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int = idx) "vq %p elem %p len %u idx %u" diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index ddc42f0f93..938253d1e8 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -27,6 +27,7 @@ #include "hw/virtio/virtio-access.h" #include "migration/blocker.h" #include "sysemu/dma.h" +#include "trace.h" =20 /* enabled until disconnected backend stabilizes */ #define _VHOST_DEBUG 1 @@ -567,18 +568,12 @@ static void vhost_set_memory(MemoryListener *listener, memory_listener); hwaddr start_addr =3D section->offset_within_address_space; ram_addr_t size =3D int128_get64(section->size); - bool log_dirty =3D - memory_region_get_dirty_log_mask(section->mr) & ~(1 << DIRTY_MEMOR= Y_MIGRATION); int s =3D offsetof(struct vhost_memory, regions) + (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; void *ram; =20 dev->mem =3D g_realloc(dev->mem, s); =20 - if (log_dirty) { - add =3D false; - } - assert(size); =20 /* Optimize no-change case. At least cirrus_vga does this a lot at thi= s time. */ @@ -611,8 +606,19 @@ static void vhost_set_memory(MemoryListener *listener, =20 static bool vhost_section(MemoryRegionSection *section) { - return memory_region_is_ram(section->mr) && + bool result; + bool log_dirty =3D memory_region_get_dirty_log_mask(section->mr) & + ~(1 << DIRTY_MEMORY_MIGRATION); + result =3D memory_region_is_ram(section->mr) && !memory_region_is_rom(section->mr); + + /* Vhost doesn't handle any block which is doing dirty-tracking other + * than migration; this typically fires on VGA areas. + */ + result &=3D !log_dirty; + + trace_vhost_section(section->mr->name, result); + return result; } =20 static void vhost_begin(MemoryListener *listener) --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981716330209.489253903679; Wed, 29 Nov 2017 10:55:16 -0800 (PST) Received: from localhost ([::1]:44721 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Vp-0004JK-JI for importer@patchew.org; Wed, 29 Nov 2017 13:55:13 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49071) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7RV-00011S-PT for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7RV-0001SD-1Q for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:45 -0500 Received: from mx1.redhat.com ([209.132.183.28]:62398) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7RU-0001Rt-Rg for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:44 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E5F4B85547 for ; Wed, 29 Nov 2017 18:50:43 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8958A60605; Wed, 29 Nov 2017 18:50:42 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:22 +0000 Message-Id: <20171129185026.23632-4-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 29 Nov 2017 18:50:43 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 3/7] vhost: New memory update functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" vhost_update_mem will replace the existing update mechanism. They make use of the Flatview we have now to make the update simpler. This commit just adds the basic structure. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/vhost.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 938253d1e8..c959a59fb3 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -629,6 +629,43 @@ static void vhost_begin(MemoryListener *listener) dev->mem_changed_start_addr =3D -1; } =20 +struct vhost_update_mem_tmp { + struct vhost_dev *dev; + uint32_t nregions; + struct vhost_memory_region *regions; +}; + +/* Called for each MRS from vhost_update_mem */ +static int vhost_update_mem_cb(MemoryRegionSection *mrs, void *opaque) +{ + if (!vhost_section(mrs)) { + return 0; + } + + /* TODO */ + return 0; +} + +static int vhost_update_mem(struct vhost_dev *dev) +{ + int res; + struct vhost_update_mem_tmp vtmp; + vtmp.regions =3D 0; + vtmp.nregions =3D 0; + vtmp.dev =3D dev; + + res =3D address_space_iterate(&address_space_memory, + vhost_update_mem_cb, &vtmp); + if (res) { + goto out; + } + + /* TODO */ +out: + g_free(vtmp.regions); + return res; +} + static void vhost_commit(MemoryListener *listener) { struct vhost_dev *dev =3D container_of(listener, struct vhost_dev, @@ -648,6 +685,10 @@ static void vhost_commit(MemoryListener *listener) return; } =20 + if (vhost_update_mem(dev)) { + return; + } + if (dev->started) { start_addr =3D dev->mem_changed_start_addr; size =3D dev->mem_changed_end_addr - dev->mem_changed_start_addr += 1; @@ -1523,6 +1564,9 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODev= ice *vdev) goto fail_features; } =20 + if (vhost_update_mem(hdev)) { + goto fail_mem; + } if (vhost_dev_has_iommu(hdev)) { memory_listener_register(&hdev->iommu_listener, vdev->dma_as); } --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981957244257.4362131016144; Wed, 29 Nov 2017 10:59:17 -0800 (PST) Received: from localhost ([::1]:44750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7ZN-0007l7-On for importer@patchew.org; Wed, 29 Nov 2017 13:58:53 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49107) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Rb-00016B-Ak for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7RY-0001T3-7g for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34608) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7RX-0001St-VB for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:48 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0DB4E3C34 for ; Wed, 29 Nov 2017 18:50:47 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3BF936062D; Wed, 29 Nov 2017 18:50:44 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:23 +0000 Message-Id: <20171129185026.23632-5-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 29 Nov 2017 18:50:47 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 4/7] vhost: update_mem_cb implementation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Add the meat of update_mem_cb; this is called for each region, to add a region to our temporary list. Our temporary list is in order we look to see if this region can be merged with the current head of list. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/trace-events | 2 ++ hw/virtio/vhost.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++= +++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 4a493bcd46..92fadec192 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -2,6 +2,8 @@ =20 # hw/virtio/vhost.c vhost_section(const char *name, int r) "%s:%d" +vhost_update_mem_cb(const char *name, uint64_t gpa, uint64_t size, uint64_= t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 +vhost_update_mem_cb_abut(const char *name, uint64_t new_size) "%s: 0x%"PRI= x64 =20 # hw/virtio/virtio.c virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned o= ut_num) "elem %p size %zd in_num %u out_num %u" diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index c959a59fb3..7e3c6ae032 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -638,11 +638,64 @@ struct vhost_update_mem_tmp { /* Called for each MRS from vhost_update_mem */ static int vhost_update_mem_cb(MemoryRegionSection *mrs, void *opaque) { + struct vhost_update_mem_tmp *vtmp =3D opaque; + struct vhost_memory_region *cur_vmr; + bool need_add =3D true; + uint64_t mrs_size; + uint64_t mrs_gpa; + uintptr_t mrs_host; + if (!vhost_section(mrs)) { return 0; } + mrs_size =3D int128_get64(mrs->size); + mrs_gpa =3D mrs->offset_within_address_space; + mrs_host =3D (uintptr_t)memory_region_get_ram_ptr(mrs->mr) + + mrs->offset_within_region; + + trace_vhost_update_mem_cb(mrs->mr->name, mrs_gpa, mrs_size, + (uint64_t)mrs_host); + + if (vtmp->nregions) { + /* Since we already have at least one region, lets see if + * this extends it; since we're scanning in order, we only + * have to look at the last one, and the FlatView that calls + * us shouldn't have overlaps. + */ + struct vhost_memory_region *prev_vmr =3D vtmp->regions + + (vtmp->nregions - 1); + uint64_t prev_gpa_start =3D prev_vmr->guest_phys_addr; + uint64_t prev_gpa_end =3D range_get_last(prev_gpa_start, + prev_vmr->memory_size); + uint64_t prev_host_start =3D prev_vmr->userspace_addr; + uint64_t prev_host_end =3D range_get_last(prev_host_start, + prev_vmr->memory_size); + + if (prev_gpa_end + 1 =3D=3D mrs_gpa && + prev_host_end + 1 =3D=3D mrs_host && + (!vtmp->dev->vhost_ops->vhost_backend_can_merge || + vtmp->dev->vhost_ops->vhost_backend_can_merge(vtmp->dev, + mrs_host, mrs_size, + prev_host_start, prev_vmr->memory_size))) { + /* The two regions abut */ + need_add =3D false; + mrs_size =3D mrs_size + prev_vmr->memory_size; + prev_vmr->memory_size =3D mrs_size; + trace_vhost_update_mem_cb_abut(mrs->mr->name, mrs_size); + } + } + + if (need_add) { + vtmp->nregions++; + vtmp->regions =3D g_realloc_n(vtmp->regions, vtmp->nregions, + sizeof(vtmp->regions[0])); + cur_vmr =3D &vtmp->regions[vtmp->nregions - 1]; + cur_vmr->guest_phys_addr =3D mrs_gpa; + cur_vmr->memory_size =3D mrs_size; + cur_vmr->userspace_addr =3D mrs_host; + cur_vmr->flags_padding =3D 0; + } =20 - /* TODO */ return 0; } =20 --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981855705770.0158256444818; Wed, 29 Nov 2017 10:57:35 -0800 (PST) Received: from localhost ([::1]:44740 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Xi-0005yf-Pa for importer@patchew.org; Wed, 29 Nov 2017 13:57:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49108) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Rb-00016D-BA for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7Ra-0001Tl-25 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51880) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7RZ-0001TQ-Os for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:49 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C75FC80476 for ; Wed, 29 Nov 2017 18:50:48 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 576C260600; Wed, 29 Nov 2017 18:50:47 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:24 +0000 Message-Id: <20171129185026.23632-6-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 29 Nov 2017 18:50:48 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 5/7] vhost: Compare new and old memory lists X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_6 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Compare the memory section list we've just built with the old one and produce an upper/lower bound of addresses changed. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/trace-events | 3 ++ hw/virtio/vhost.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 77 insertions(+) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 92fadec192..ba85a1855b 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -2,6 +2,9 @@ =20 # hw/virtio/vhost.c vhost_section(const char *name, int r) "%s:%d" +vhost_update_compare_list_loopn(int newi, int oldi, uint64_t gpa, uint64_t= size) "%d/%d: (new) 0x%"PRIx64"+0x%"PRIx64 +vhost_update_compare_list_loopo(int newi, int oldi, uint64_t gpa, uint64_t= size) "%d/%d: (old) 0x%"PRIx64"+0x%"PRIx64 +vhost_update_mem_comparison(bool update, uint64_t start, uint64_t end) "up= date: %d 0x%"PRIx64" - 0x%"PRIx64 vhost_update_mem_cb(const char *name, uint64_t gpa, uint64_t size, uint64_= t host) "%s: 0x%"PRIx64"+0x%"PRIx64" @ 0x%"PRIx64 vhost_update_mem_cb_abut(const char *name, uint64_t new_size) "%s: 0x%"PRI= x64 =20 diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 7e3c6ae032..ae3d57df1d 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -699,10 +699,79 @@ static int vhost_update_mem_cb(MemoryRegionSection *m= rs, void *opaque) return 0; } =20 +static bool vhost_update_compare_list(struct vhost_dev *dev, + struct vhost_update_mem_tmp *vtmp, + hwaddr *change_start, hwaddr *change= _end) +{ + uint32_t oldi, newi; + *change_start =3D 0; + *change_end =3D 0; + + for (newi =3D 0, oldi =3D 0; newi < vtmp->nregions; newi++) { + struct vhost_memory_region *newr =3D &vtmp->regions[newi]; + hwaddr newr_last =3D range_get_last(newr->guest_phys_addr, + newr->memory_size); + trace_vhost_update_compare_list_loopn(newi, oldi, + newr->guest_phys_addr, + newr->memory_size); + bool whole_change =3D true; + while (oldi < dev->mem->nregions) { + struct vhost_memory_region *oldr =3D &dev->mem->regions[oldi]; + hwaddr oldr_last =3D range_get_last(oldr->guest_phys_addr, + oldr->memory_size); + trace_vhost_update_compare_list_loopo(newi, oldi, + oldr->guest_phys_addr, + oldr->memory_size); + if (newr->guest_phys_addr =3D=3D oldr->guest_phys_addr && + newr->memory_size =3D=3D oldr->memory_size) { + /* Match in GPA and size, but it could be different + * in host address or flags + */ + whole_change =3D newr->userspace_addr !=3D oldr->userspace= _addr || + newr->flags_padding !=3D oldr->flags_paddin= g; + oldi++; + break; /* inner old loop */ + } + /* There's a difference - need to figure out what */ + if (oldr_last < newr->guest_phys_addr) { + /* There used to be a region before us that's gone */ + *change_start =3D MIN(*change_start, oldr->guest_phys_addr= ); + *change_end =3D MAX(*change_end, oldr_last); + oldi++; + continue; /* inner old loop */ + } + if (oldr->guest_phys_addr > newr_last) { + /* We've passed all the old mappings that could have overl= apped + * this one + */ + break; /* Inner old loop */ + } + /* Overlap case */ + *change_start =3D MIN(*change_start, + MIN(oldr->guest_phys_addr, + newr->guest_phys_addr)); + *change_end =3D MAX(*change_end, + MAX(oldr_last, newr_last)); + whole_change =3D false; + /* There might be more old mappings that overlap */ + oldi++; + } + if (whole_change) { + /* No old region to compare against, this must be a change */ + *change_start =3D MIN(*change_start, newr->guest_phys_addr); + *change_end =3D MAX(*change_end, newr_last); + } + } + + return *change_start || *change_end; +} + static int vhost_update_mem(struct vhost_dev *dev) { int res; struct vhost_update_mem_tmp vtmp; + hwaddr change_start, change_end; + bool need_update; vtmp.regions =3D 0; vtmp.nregions =3D 0; vtmp.dev =3D dev; @@ -713,6 +782,11 @@ static int vhost_update_mem(struct vhost_dev *dev) goto out; } =20 + need_update =3D vhost_update_compare_list(dev, &vtmp, + &change_start, &change_end); + trace_vhost_update_mem_comparison(need_update, + (uint64_t)change_start, + (uint64_t)change_end); /* TODO */ out: g_free(vtmp.regions); --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981738846912.5354398144253; Wed, 29 Nov 2017 10:55:38 -0800 (PST) Received: from localhost ([::1]:44726 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7W9-0004cx-3L for importer@patchew.org; Wed, 29 Nov 2017 13:55:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49172) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Rk-0001BW-Or for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:51:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7Rh-0001X8-O0 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:51:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39416) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7Rh-0001Wj-HX for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:57 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9AB99C01B3F9 for ; Wed, 29 Nov 2017 18:50:56 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1DB2860600; Wed, 29 Nov 2017 18:50:48 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:25 +0000 Message-Id: <20171129185026.23632-7-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 29 Nov 2017 18:50:56 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 6/7] vhost: Copy updated region data into device state X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Copy the temporary region data we calculated into the device state. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/vhost.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index ae3d57df1d..34011f9acb 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -787,7 +787,21 @@ static int vhost_update_mem(struct vhost_dev *dev) trace_vhost_update_mem_comparison(need_update, (uint64_t)change_start, (uint64_t)change_end); - /* TODO */ + if (need_update) { + /* Update the main regions list from our tmp */ + size_t mem_size =3D offsetof(struct vhost_memory, regions) + + (vtmp.nregions + 1) * sizeof dev->mem->regions[0]; + + dev->mem =3D g_realloc(dev->mem, mem_size); + dev->mem->nregions =3D vtmp.nregions; + memcpy(dev->mem->regions, vtmp.regions, + vtmp.nregions * sizeof dev->mem->regions[0]); + used_memslots =3D vtmp.nregions; + + dev->mem_changed_start_addr =3D change_start; + dev->mem_changed_end_addr =3D change_end; + } + out: g_free(vtmp.regions); return res; --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511981590463856.1337459194713; Wed, 29 Nov 2017 10:53:10 -0800 (PST) Received: from localhost ([::1]:44711 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Tk-0002Pf-Mf for importer@patchew.org; Wed, 29 Nov 2017 13:53:04 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49173) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eK7Rk-0001BX-P9 for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:51:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eK7Rj-0001Xr-6x for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:51:00 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40916) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eK7Ri-0001XL-TT for qemu-devel@nongnu.org; Wed, 29 Nov 2017 13:50:59 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0B91D1555A for ; Wed, 29 Nov 2017 18:50:58 +0000 (UTC) Received: from dgilbert-t530.redhat.com (unknown [10.36.118.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id DEF5D60600; Wed, 29 Nov 2017 18:50:56 +0000 (UTC) From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, imammedo@redhat.com Date: Wed, 29 Nov 2017 18:50:26 +0000 Message-Id: <20171129185026.23632-8-dgilbert@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 29 Nov 2017 18:50:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 7/7] vhost: Remove vhost_set_memory and children X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: maxime.coquelin@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Remove the old update mechanism, vhost_set_memory, and the functions it uses. Signed-off-by: Dr. David Alan Gilbert --- hw/virtio/vhost.c | 239 --------------------------------------------------= ---- 1 file changed, 239 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 34011f9acb..5b9a7d7107 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -156,160 +156,6 @@ static void vhost_log_sync_range(struct vhost_dev *de= v, } } =20 -/* Assign/unassign. Keep an unsorted array of non-overlapping - * memory regions in dev->mem. */ -static void vhost_dev_unassign_memory(struct vhost_dev *dev, - uint64_t start_addr, - uint64_t size) -{ - int from, to, n =3D dev->mem->nregions; - /* Track overlapping/split regions for sanity checking. */ - int overlap_start =3D 0, overlap_end =3D 0, overlap_middle =3D 0, spli= t =3D 0; - - for (from =3D 0, to =3D 0; from < n; ++from, ++to) { - struct vhost_memory_region *reg =3D dev->mem->regions + to; - uint64_t reglast; - uint64_t memlast; - uint64_t change; - - /* clone old region */ - if (to !=3D from) { - memcpy(reg, dev->mem->regions + from, sizeof *reg); - } - - /* No overlap is simple */ - if (!ranges_overlap(reg->guest_phys_addr, reg->memory_size, - start_addr, size)) { - continue; - } - - /* Split only happens if supplied region - * is in the middle of an existing one. Thus it can not - * overlap with any other existing region. */ - assert(!split); - - reglast =3D range_get_last(reg->guest_phys_addr, reg->memory_size); - memlast =3D range_get_last(start_addr, size); - - /* Remove whole region */ - if (start_addr <=3D reg->guest_phys_addr && memlast >=3D reglast) { - --dev->mem->nregions; - --to; - ++overlap_middle; - continue; - } - - /* Shrink region */ - if (memlast >=3D reglast) { - reg->memory_size =3D start_addr - reg->guest_phys_addr; - assert(reg->memory_size); - assert(!overlap_end); - ++overlap_end; - continue; - } - - /* Shift region */ - if (start_addr <=3D reg->guest_phys_addr) { - change =3D memlast + 1 - reg->guest_phys_addr; - reg->memory_size -=3D change; - reg->guest_phys_addr +=3D change; - reg->userspace_addr +=3D change; - assert(reg->memory_size); - assert(!overlap_start); - ++overlap_start; - continue; - } - - /* This only happens if supplied region - * is in the middle of an existing one. Thus it can not - * overlap with any other existing region. */ - assert(!overlap_start); - assert(!overlap_end); - assert(!overlap_middle); - /* Split region: shrink first part, shift second part. */ - memcpy(dev->mem->regions + n, reg, sizeof *reg); - reg->memory_size =3D start_addr - reg->guest_phys_addr; - assert(reg->memory_size); - change =3D memlast + 1 - reg->guest_phys_addr; - reg =3D dev->mem->regions + n; - reg->memory_size -=3D change; - assert(reg->memory_size); - reg->guest_phys_addr +=3D change; - reg->userspace_addr +=3D change; - /* Never add more than 1 region */ - assert(dev->mem->nregions =3D=3D n); - ++dev->mem->nregions; - ++split; - } -} - -/* Called after unassign, so no regions overlap the given range. */ -static void vhost_dev_assign_memory(struct vhost_dev *dev, - uint64_t start_addr, - uint64_t size, - uint64_t uaddr) -{ - int from, to; - struct vhost_memory_region *merged =3D NULL; - for (from =3D 0, to =3D 0; from < dev->mem->nregions; ++from, ++to) { - struct vhost_memory_region *reg =3D dev->mem->regions + to; - uint64_t prlast, urlast; - uint64_t pmlast, umlast; - uint64_t s, e, u; - - /* clone old region */ - if (to !=3D from) { - memcpy(reg, dev->mem->regions + from, sizeof *reg); - } - prlast =3D range_get_last(reg->guest_phys_addr, reg->memory_size); - pmlast =3D range_get_last(start_addr, size); - urlast =3D range_get_last(reg->userspace_addr, reg->memory_size); - umlast =3D range_get_last(uaddr, size); - - /* check for overlapping regions: should never happen. */ - assert(prlast < start_addr || pmlast < reg->guest_phys_addr); - /* Not an adjacent or overlapping region - do not merge. */ - if ((prlast + 1 !=3D start_addr || urlast + 1 !=3D uaddr) && - (pmlast + 1 !=3D reg->guest_phys_addr || - umlast + 1 !=3D reg->userspace_addr)) { - continue; - } - - if (dev->vhost_ops->vhost_backend_can_merge && - !dev->vhost_ops->vhost_backend_can_merge(dev, uaddr, size, - reg->userspace_addr, - reg->memory_size)) { - continue; - } - - if (merged) { - --to; - assert(to >=3D 0); - } else { - merged =3D reg; - } - u =3D MIN(uaddr, reg->userspace_addr); - s =3D MIN(start_addr, reg->guest_phys_addr); - e =3D MAX(pmlast, prlast); - uaddr =3D merged->userspace_addr =3D u; - start_addr =3D merged->guest_phys_addr =3D s; - size =3D merged->memory_size =3D e - s + 1; - assert(merged->memory_size); - } - - if (!merged) { - struct vhost_memory_region *reg =3D dev->mem->regions + to; - memset(reg, 0, sizeof *reg); - reg->memory_size =3D size; - assert(reg->memory_size); - reg->guest_phys_addr =3D start_addr; - reg->userspace_addr =3D uaddr; - ++to; - } - assert(to <=3D dev->mem->nregions + 1); - dev->mem->nregions =3D to; -} - static uint64_t vhost_get_log_size(struct vhost_dev *dev) { uint64_t log_size =3D 0; @@ -521,89 +367,6 @@ static int vhost_verify_ring_mappings(struct vhost_dev= *dev, return r; } =20 -static struct vhost_memory_region *vhost_dev_find_reg(struct vhost_dev *de= v, - uint64_t start_addr, - uint64_t size) -{ - int i, n =3D dev->mem->nregions; - for (i =3D 0; i < n; ++i) { - struct vhost_memory_region *reg =3D dev->mem->regions + i; - if (ranges_overlap(reg->guest_phys_addr, reg->memory_size, - start_addr, size)) { - return reg; - } - } - return NULL; -} - -static bool vhost_dev_cmp_memory(struct vhost_dev *dev, - uint64_t start_addr, - uint64_t size, - uint64_t uaddr) -{ - struct vhost_memory_region *reg =3D vhost_dev_find_reg(dev, start_addr= , size); - uint64_t reglast; - uint64_t memlast; - - if (!reg) { - return true; - } - - reglast =3D range_get_last(reg->guest_phys_addr, reg->memory_size); - memlast =3D range_get_last(start_addr, size); - - /* Need to extend region? */ - if (start_addr < reg->guest_phys_addr || memlast > reglast) { - return true; - } - /* userspace_addr changed? */ - return uaddr !=3D reg->userspace_addr + start_addr - reg->guest_phys_a= ddr; -} - -static void vhost_set_memory(MemoryListener *listener, - MemoryRegionSection *section, - bool add) -{ - struct vhost_dev *dev =3D container_of(listener, struct vhost_dev, - memory_listener); - hwaddr start_addr =3D section->offset_within_address_space; - ram_addr_t size =3D int128_get64(section->size); - int s =3D offsetof(struct vhost_memory, regions) + - (dev->mem->nregions + 1) * sizeof dev->mem->regions[0]; - void *ram; - - dev->mem =3D g_realloc(dev->mem, s); - - assert(size); - - /* Optimize no-change case. At least cirrus_vga does this a lot at thi= s time. */ - ram =3D memory_region_get_ram_ptr(section->mr) + section->offset_withi= n_region; - if (add) { - if (!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)) { - /* Removing region that we don't access. Nothing to do. */ - return; - } - } - - vhost_dev_unassign_memory(dev, start_addr, size); - if (add) { - /* Add given mapping, merging adjacent regions if any */ - vhost_dev_assign_memory(dev, start_addr, size, (uintptr_t)ram); - } else { - /* Remove old mapping for this memory, if any. */ - vhost_dev_unassign_memory(dev, start_addr, size); - } - dev->mem_changed_start_addr =3D MIN(dev->mem_changed_start_addr, start= _addr); - dev->mem_changed_end_addr =3D MAX(dev->mem_changed_end_addr, start_add= r + size - 1); - dev->memory_changed =3D true; - used_memslots =3D dev->mem->nregions; -} - static bool vhost_section(MemoryRegionSection *section) { bool result; @@ -880,7 +643,6 @@ static void vhost_region_add(MemoryListener *listener, dev->n_mem_sections); dev->mem_sections[dev->n_mem_sections - 1] =3D *section; memory_region_ref(section->mr); - vhost_set_memory(listener, section, true); } =20 static void vhost_region_del(MemoryListener *listener, @@ -894,7 +656,6 @@ static void vhost_region_del(MemoryListener *listener, return; } =20 - vhost_set_memory(listener, section, false); memory_region_unref(section->mr); for (i =3D 0; i < dev->n_mem_sections; ++i) { if (dev->mem_sections[i].offset_within_address_space --=20 2.14.3 From nobody Fri May 3 23:22:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15121435484511007.8427037068072; Fri, 1 Dec 2017 07:52:28 -0800 (PST) Received: from localhost ([::1]:58230 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eKnbr-0004Y8-H4 for importer@patchew.org; Fri, 01 Dec 2017 10:52:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38302) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eKnSG-0004Q4-Ko for qemu-devel@nongnu.org; Fri, 01 Dec 2017 10:43:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eKnRc-0000XU-1e for qemu-devel@nongnu.org; Fri, 01 Dec 2017 10:42:20 -0500 Received: from mx1.redhat.com ([209.132.183.28]:38922) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eKnRb-0000TV-1Z for qemu-devel@nongnu.org; Fri, 01 Dec 2017 10:41:39 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ECCD161E51; Fri, 1 Dec 2017 14:23:32 +0000 (UTC) Received: from dell-r430-03.lab.eng.brq.redhat.com (dell-r430-03.lab.eng.brq.redhat.com [10.37.153.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id BE67B5D9CA; Fri, 1 Dec 2017 14:23:28 +0000 (UTC) From: Igor Mammedov To: qemu-devel@nongnu.org Date: Fri, 1 Dec 2017 15:22:55 +0100 Message-Id: <1512138175-185428-1-git-send-email-imammedo@redhat.com> In-Reply-To: <20171129185026.23632-1-dgilbert@redhat.com> References: <20171129185026.23632-1-dgilbert@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 01 Dec 2017 14:23:33 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC] vhost: check if ring mapping is still valid when building memmap X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: stefanha@gmail.com, groug@kaod.org, dgilbert@redhat.com, mst@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" vhost_verify_ring_mappings() were used to verify that rings are still accessible and related memory hasn't been moved after flatview is updated. It were doing checks by mapping ring's GPA+len and checking that HVA hasn't changed with new memory map. To avoid maybe expensive mapping call, we were identifying address range that changed and were doing mapping only if ring were in changed range. However it's no neccessary to perform ringi's GPA mapping as we already have it's current HVA and all we need is to verify that ring's GPA translates to the same HVA in updated flatview. That could be done during time when we are building vhost memmap where vhost_update_mem_cb() already maps every RAM MemoryRegionSection to get section HVA. This fact can be used to check that ring belongs to the same MemoryRegion in the same place, like this: hva_ring_offset =3D GPA(ring) - GPA(MemoryRegionSection) ring_hva =3D=3D HVA(MemoryRegionSection) + hva_ring_offset Doing this would allow us to drop ~100LOC of code which figures out changed memory range and avoid calling not needed reverse vhost_memory_map(is_write=3Dtrue) which is overkill for the task at hand. Signed-off-by: Igor Mammedov --- PS: should be applied on top of David's series --- include/hw/virtio/vhost.h | 2 - hw/virtio/vhost.c | 195 ++++++++++++++----------------------------= ---- 2 files changed, 57 insertions(+), 140 deletions(-) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 467dc77..fc4af5c 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -68,8 +68,6 @@ struct vhost_dev { uint64_t log_size; Error *migration_blocker; bool memory_changed; - hwaddr mem_changed_start_addr; - hwaddr mem_changed_end_addr; const VhostOps *vhost_ops; void *opaque; struct vhost_log *log; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 5b9a7d7..026bac3 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -296,35 +296,43 @@ static void vhost_memory_unmap(struct vhost_dev *dev,= void *buffer, } } =20 -static int vhost_verify_ring_part_mapping(struct vhost_dev *dev, - void *part, - uint64_t part_addr, - uint64_t part_size, - uint64_t start_addr, - uint64_t size) +static int vhost_verify_ring_part_mapping(void *ring_hva, + uint64_t ring_gpa, + uint64_t ring_size, + void *reg_hva, + uint64_t reg_gpa, + uint64_t reg_size) { - hwaddr l; - void *p; - int r =3D 0; + uint64_t hva_ring_offset; + uint64_t ring_last =3D range_get_last(ring_gpa, ring_size); + uint64_t reg_last =3D range_get_last(reg_gpa, reg_size); =20 - if (!ranges_overlap(start_addr, size, part_addr, part_size)) { + /* start check from the end so that the rest of checks + * are done when whole ring is in merged sections range + */ + if (ring_last < reg_last || ring_gpa > reg_last) { return 0; } - l =3D part_size; - p =3D vhost_memory_map(dev, part_addr, &l, 1); - if (!p || l !=3D part_size) { - r =3D -ENOMEM; + + /* check that whole ring's is mapped */ + if (range_get_last(ring_gpa, ring_size) > + range_get_last(reg_gpa, reg_size)) { + return -EBUSY; } - if (p !=3D part) { - r =3D -EBUSY; + + /* check that ring's MemoryRegion wasn't replaced */ + hva_ring_offset =3D ring_gpa - reg_gpa; + if (ring_hva !=3D reg_hva + hva_ring_offset) { + return -ENOMEM; } - vhost_memory_unmap(dev, p, l, 0, 0); - return r; + + return 0; } =20 static int vhost_verify_ring_mappings(struct vhost_dev *dev, - uint64_t start_addr, - uint64_t size) + void *reg_hva, + uint64_t reg_gpa, + uint64_t reg_size) { int i, j; int r =3D 0; @@ -338,23 +346,26 @@ static int vhost_verify_ring_mappings(struct vhost_de= v *dev, struct vhost_virtqueue *vq =3D dev->vqs + i; =20 j =3D 0; - r =3D vhost_verify_ring_part_mapping(dev, vq->desc, vq->desc_phys, - vq->desc_size, start_addr, size= ); - if (!r) { + r =3D vhost_verify_ring_part_mapping( + vq->desc, vq->desc_phys, vq->desc_size, + reg_hva, reg_gpa, reg_size); + if (r) { break; } =20 j++; - r =3D vhost_verify_ring_part_mapping(dev, vq->avail, vq->avail_phy= s, - vq->avail_size, start_addr, siz= e); - if (!r) { + r =3D vhost_verify_ring_part_mapping( + vq->desc, vq->desc_phys, vq->desc_size, + reg_hva, reg_gpa, reg_size); + if (r) { break; } =20 j++; - r =3D vhost_verify_ring_part_mapping(dev, vq->used, vq->used_phys, - vq->used_size, start_addr, size= ); - if (!r) { + r =3D vhost_verify_ring_part_mapping( + vq->desc, vq->desc_phys, vq->desc_size, + reg_hva, reg_gpa, reg_size); + if (r) { break; } } @@ -384,24 +395,18 @@ static bool vhost_section(MemoryRegionSection *sectio= n) return result; } =20 -static void vhost_begin(MemoryListener *listener) -{ - struct vhost_dev *dev =3D container_of(listener, struct vhost_dev, - memory_listener); - dev->mem_changed_end_addr =3D 0; - dev->mem_changed_start_addr =3D -1; -} - struct vhost_update_mem_tmp { struct vhost_dev *dev; uint32_t nregions; struct vhost_memory_region *regions; }; =20 + /* Called for each MRS from vhost_update_mem */ static int vhost_update_mem_cb(MemoryRegionSection *mrs, void *opaque) { struct vhost_update_mem_tmp *vtmp =3D opaque; + struct vhost_dev *dev =3D vtmp->dev; struct vhost_memory_region *cur_vmr; bool need_add =3D true; uint64_t mrs_size; @@ -416,8 +421,7 @@ static int vhost_update_mem_cb(MemoryRegionSection *mrs= , void *opaque) mrs_host =3D (uintptr_t)memory_region_get_ram_ptr(mrs->mr) + mrs->offset_within_region; =20 - trace_vhost_update_mem_cb(mrs->mr->name, mrs_gpa, mrs_size, - (uint64_t)mrs_host); + trace_vhost_update_mem_cb(mrs->mr->name, mrs_gpa, mrs_size, mrs_host); =20 if (vtmp->nregions) { /* Since we already have at least one region, lets see if @@ -459,85 +463,19 @@ static int vhost_update_mem_cb(MemoryRegionSection *m= rs, void *opaque) cur_vmr->flags_padding =3D 0; } =20 - return 0; -} - -static bool vhost_update_compare_list(struct vhost_dev *dev, - struct vhost_update_mem_tmp *vtmp, - hwaddr *change_start, hwaddr *change= _end) -{ - uint32_t oldi, newi; - *change_start =3D 0; - *change_end =3D 0; - - for (newi =3D 0, oldi =3D 0; newi < vtmp->nregions; newi++) { - struct vhost_memory_region *newr =3D &vtmp->regions[newi]; - hwaddr newr_last =3D range_get_last(newr->guest_phys_addr, - newr->memory_size); - trace_vhost_update_compare_list_loopn(newi, oldi, - newr->guest_phys_addr, - newr->memory_size); - bool whole_change =3D true; - while (oldi < dev->mem->nregions) { - struct vhost_memory_region *oldr =3D &dev->mem->regions[oldi]; - hwaddr oldr_last =3D range_get_last(oldr->guest_phys_addr, - oldr->memory_size); - trace_vhost_update_compare_list_loopo(newi, oldi, - oldr->guest_phys_addr, - oldr->memory_size); - if (newr->guest_phys_addr =3D=3D oldr->guest_phys_addr && - newr->memory_size =3D=3D oldr->memory_size) { - /* Match in GPA and size, but it could be different - * in host address or flags - */ - whole_change =3D newr->userspace_addr !=3D oldr->userspace= _addr || - newr->flags_padding !=3D oldr->flags_paddin= g; - oldi++; - break; /* inner old loop */ - } - /* There's a difference - need to figure out what */ - if (oldr_last < newr->guest_phys_addr) { - /* There used to be a region before us that's gone */ - *change_start =3D MIN(*change_start, oldr->guest_phys_addr= ); - *change_end =3D MAX(*change_end, oldr_last); - oldi++; - continue; /* inner old loop */ - } - if (oldr->guest_phys_addr > newr_last) { - /* We've passed all the old mappings that could have overl= apped - * this one - */ - break; /* Inner old loop */ - } - /* Overlap case */ - *change_start =3D MIN(*change_start, - MIN(oldr->guest_phys_addr, - newr->guest_phys_addr)); - *change_end =3D MAX(*change_end, - MAX(oldr_last, newr_last)); - whole_change =3D false; - /* There might be more old mappings that overlap */ - oldi++; - } - if (whole_change) { - /* No old region to compare against, this must be a change */ - *change_start =3D MIN(*change_start, newr->guest_phys_addr); - *change_end =3D MAX(*change_end, newr_last); - } + if (dev->started && + vhost_verify_ring_mappings(dev, (void *)mrs_host, mrs_gpa, mrs_siz= e)) { + abort(); } =20 - return *change_start || *change_end; + return 0; } =20 static int vhost_update_mem(struct vhost_dev *dev) { int res; - struct vhost_update_mem_tmp vtmp; - hwaddr change_start, change_end; - bool need_update; - vtmp.regions =3D 0; - vtmp.nregions =3D 0; - vtmp.dev =3D dev; + size_t mem_size; + struct vhost_update_mem_tmp vtmp =3D {.dev =3D dev}; =20 res =3D address_space_iterate(&address_space_memory, vhost_update_mem_cb, &vtmp); @@ -545,24 +483,17 @@ static int vhost_update_mem(struct vhost_dev *dev) goto out; } =20 - need_update =3D vhost_update_compare_list(dev, &vtmp, - &change_start, &change_end); - trace_vhost_update_mem_comparison(need_update, - (uint64_t)change_start, - (uint64_t)change_end); - if (need_update) { - /* Update the main regions list from our tmp */ - size_t mem_size =3D offsetof(struct vhost_memory, regions) + - (vtmp.nregions + 1) * sizeof dev->mem->regions[0]; + mem_size =3D offsetof(struct vhost_memory, regions) + + (vtmp.nregions + 1) * sizeof dev->mem->regions[0]; =20 + if(vtmp.nregions !=3D dev->mem->nregions || + memcmp(vtmp.regions, dev->mem->regions, mem_size)) { + /* Update the main regions list from our tmp */ dev->mem =3D g_realloc(dev->mem, mem_size); dev->mem->nregions =3D vtmp.nregions; memcpy(dev->mem->regions, vtmp.regions, vtmp.nregions * sizeof dev->mem->regions[0]); used_memslots =3D vtmp.nregions; - - dev->mem_changed_start_addr =3D change_start; - dev->mem_changed_end_addr =3D change_end; } =20 out: @@ -574,8 +505,6 @@ static void vhost_commit(MemoryListener *listener) { struct vhost_dev *dev =3D container_of(listener, struct vhost_dev, memory_listener); - hwaddr start_addr =3D 0; - ram_addr_t size =3D 0; uint64_t log_size; int r; =20 @@ -585,22 +514,11 @@ static void vhost_commit(MemoryListener *listener) if (!dev->started) { return; } - if (dev->mem_changed_start_addr > dev->mem_changed_end_addr) { - return; - } =20 if (vhost_update_mem(dev)) { return; } =20 - if (dev->started) { - start_addr =3D dev->mem_changed_start_addr; - size =3D dev->mem_changed_end_addr - dev->mem_changed_start_addr += 1; - - r =3D vhost_verify_ring_mappings(dev, start_addr, size); - assert(r >=3D 0); - } - if (!dev->log_enabled) { r =3D dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); if (r < 0) { @@ -1235,7 +1153,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaq= ue, hdev->features =3D features; =20 hdev->memory_listener =3D (MemoryListener) { - .begin =3D vhost_begin, .commit =3D vhost_commit, .region_add =3D vhost_region_add, .region_del =3D vhost_region_del, @@ -1458,7 +1375,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODev= ice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); =20 - hdev->started =3D true; hdev->vdev =3D vdev; =20 r =3D vhost_dev_set_features(hdev, hdev->log_enabled); @@ -1469,6 +1385,9 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODev= ice *vdev) if (vhost_update_mem(hdev)) { goto fail_mem; } + + hdev->started =3D true; + if (vhost_dev_has_iommu(hdev)) { memory_listener_register(&hdev->iommu_listener, vdev->dma_as); } --=20 2.7.4