From nobody Mon Feb 9 02:27:35 2026 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.zoho.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 1487362495256806.9854803911383; Fri, 17 Feb 2017 12:14:55 -0800 (PST) Received: from localhost ([::1]:55644 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceovd-00058n-MD for importer@patchew.org; Fri, 17 Feb 2017 15:14:53 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44178) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceobt-00046x-9a for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ceobs-0005aD-0Z for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:29 -0500 Received: from mail.kernel.org ([198.145.29.136]:34388) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ceobr-0005ZC-MR for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:27 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7A9E4201FE; Fri, 17 Feb 2017 19:54:25 +0000 (UTC) Received: from redhat.com (pool-96-237-235-121.bstnma.fios.verizon.net [96.237.235.121]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id F3B762021F; Fri, 17 Feb 2017 19:54:23 +0000 (UTC) Date: Fri, 17 Feb 2017 21:54:23 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <1487361200-29966-10-git-send-email-mst@redhat.com> References: <1487361200-29966-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1487361200-29966-1-git-send-email-mst@redhat.com> X-Mailer: git-send-email 2.8.0.287.g0deeb61 X-Mutt-Fcc: =sent X-Virus-Scanned: ClamAV using ClamSMTP X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 198.145.29.136 Subject: [Qemu-devel] [PULL 09/23] virtio: add MemoryListener to cache ring translations 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: Peter Maydell , Stefan Hajnoczi , Paolo Bonzini 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 Content-Type: text/plain; charset="utf-8" From: Paolo Bonzini The cached translations are RCU-protected to allow efficient use when processing virtqueues. Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/virtio.h | 1 + hw/virtio/virtio.c | 105 +++++++++++++++++++++++++++++++++++++++++= ++-- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 0863a25..15efcf2 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -85,6 +85,7 @@ struct VirtIODevice uint32_t generation; int nvectors; VirtQueue *vq; + MemoryListener listener; uint16_t device_id; bool vm_running; bool broken; /* device in invalid state, needs reset */ diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 71e41f6..b75cb52 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -60,6 +60,13 @@ typedef struct VRingUsed VRingUsedElem ring[0]; } VRingUsed; =20 +typedef struct VRingMemoryRegionCaches { + struct rcu_head rcu; + MemoryRegionCache desc; + MemoryRegionCache avail; + MemoryRegionCache used; +} VRingMemoryRegionCaches; + typedef struct VRing { unsigned int num; @@ -68,6 +75,7 @@ typedef struct VRing hwaddr desc; hwaddr avail; hwaddr used; + VRingMemoryRegionCaches *caches; } VRing; =20 struct VirtQueue @@ -104,6 +112,51 @@ struct VirtQueue QLIST_ENTRY(VirtQueue) node; }; =20 +static void virtio_free_region_cache(VRingMemoryRegionCaches *caches) +{ + if (!caches) { + return; + } + + address_space_cache_destroy(&caches->desc); + address_space_cache_destroy(&caches->avail); + address_space_cache_destroy(&caches->used); + g_free(caches); +} + +static void virtio_init_region_cache(VirtIODevice *vdev, int n) +{ + VirtQueue *vq =3D &vdev->vq[n]; + VRingMemoryRegionCaches *old =3D vq->vring.caches; + VRingMemoryRegionCaches *new; + hwaddr addr, size; + int event_size; + + event_size =3D virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_I= DX) ? 2 : 0; + + addr =3D vq->vring.desc; + if (!addr) { + return; + } + new =3D g_new0(VRingMemoryRegionCaches, 1); + size =3D virtio_queue_get_desc_size(vdev, n); + address_space_cache_init(&new->desc, vdev->dma_as, + addr, size, false); + + size =3D virtio_queue_get_used_size(vdev, n) + event_size; + address_space_cache_init(&new->used, vdev->dma_as, + vq->vring.used, size, true); + + size =3D virtio_queue_get_avail_size(vdev, n) + event_size; + address_space_cache_init(&new->avail, vdev->dma_as, + vq->vring.avail, size, false); + + atomic_rcu_set(&vq->vring.caches, new); + if (old) { + call_rcu(old, virtio_free_region_cache, rcu); + } +} + /* virt queue functions */ void virtio_queue_update_rings(VirtIODevice *vdev, int n) { @@ -117,6 +170,7 @@ void virtio_queue_update_rings(VirtIODevice *vdev, int = n) vring->used =3D vring_align(vring->avail + offsetof(VRingAvail, ring[vring->num]), vring->align); + virtio_init_region_cache(vdev, n); } =20 static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc, @@ -1264,6 +1318,7 @@ void virtio_queue_set_rings(VirtIODevice *vdev, int n= , hwaddr desc, vdev->vq[n].vring.desc =3D desc; vdev->vq[n].vring.avail =3D avail; vdev->vq[n].vring.used =3D used; + virtio_init_region_cache(vdev, n); } =20 void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) @@ -1984,9 +2039,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int = version_id) void virtio_cleanup(VirtIODevice *vdev) { qemu_del_vm_change_state_handler(vdev->vmstate); - g_free(vdev->config); - g_free(vdev->vq); - g_free(vdev->vector_queues); } =20 static void virtio_vmstate_change(void *opaque, int running, RunState stat= e) @@ -2248,6 +2300,19 @@ void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *v= dev, const char *fmt, ...) } } =20 +static void virtio_memory_listener_commit(MemoryListener *listener) +{ + VirtIODevice *vdev =3D container_of(listener, VirtIODevice, listener); + int i; + + for (i =3D 0; i < VIRTIO_QUEUE_MAX; i++) { + if (vdev->vq[i].vring.num =3D=3D 0) { + break; + } + virtio_init_region_cache(vdev, i); + } +} + static void virtio_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); @@ -2270,6 +2335,9 @@ static void virtio_device_realize(DeviceState *dev, E= rror **errp) error_propagate(errp, err); return; } + + vdev->listener.commit =3D virtio_memory_listener_commit; + memory_listener_register(&vdev->listener, vdev->dma_as); } =20 static void virtio_device_unrealize(DeviceState *dev, Error **errp) @@ -2292,6 +2360,36 @@ static void virtio_device_unrealize(DeviceState *dev= , Error **errp) vdev->bus_name =3D NULL; } =20 +static void virtio_device_free_virtqueues(VirtIODevice *vdev) +{ + int i; + if (!vdev->vq) { + return; + } + + for (i =3D 0; i < VIRTIO_QUEUE_MAX; i++) { + VRingMemoryRegionCaches *caches; + if (vdev->vq[i].vring.num =3D=3D 0) { + break; + } + caches =3D atomic_read(&vdev->vq[i].vring.caches); + atomic_set(&vdev->vq[i].vring.caches, NULL); + virtio_free_region_cache(caches); + } + g_free(vdev->vq); +} + +static void virtio_device_instance_finalize(Object *obj) +{ + VirtIODevice *vdev =3D VIRTIO_DEVICE(obj); + + memory_listener_unregister(&vdev->listener); + virtio_device_free_virtqueues(vdev); + + g_free(vdev->config); + g_free(vdev->vector_queues); +} + static Property virtio_properties[] =3D { DEFINE_VIRTIO_COMMON_FEATURES(VirtIODevice, host_features), DEFINE_PROP_END_OF_LIST(), @@ -2418,6 +2516,7 @@ static const TypeInfo virtio_device_info =3D { .parent =3D TYPE_DEVICE, .instance_size =3D sizeof(VirtIODevice), .class_init =3D virtio_device_class_init, + .instance_finalize =3D virtio_device_instance_finalize, .abstract =3D true, .class_size =3D sizeof(VirtioDeviceClass), }; --=20 MST