From mboxrd@z Thu Jan 1 00:00:00 1970 From: Maxime Coquelin Subject: [RFC 18/19] vhost: iommu: Invalidate vring in case of matching IOTLB invalidate Date: Tue, 4 Jul 2017 11:49:21 +0200 Message-ID: <20170704094922.11405-19-maxime.coquelin@redhat.com> References: <20170704094922.11405-1-maxime.coquelin@redhat.com> Cc: mst@redhat.com, vkaplans@redhat.com, jasowang@redhat.com, jfreiman@redhat.com, Maxime Coquelin To: dev@dpdk.org, Yuanhan Liu Return-path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by dpdk.org (Postfix) with ESMTP id 77CC87CF0 for ; Tue, 4 Jul 2017 11:50:45 +0200 (CEST) In-Reply-To: <20170704094922.11405-1-maxime.coquelin@redhat.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" As soon as a page used by a ring is invalidated, the access_ok flag is cleared, so that processing threads try to map them again. Signed-off-by: Maxime Coquelin --- lib/librte_vhost/vhost.c | 17 +++++++++++++++++ lib/librte_vhost/vhost.h | 1 + lib/librte_vhost/vhost_user.c | 38 +++++++++++++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index 3f193bf..971ff51 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -274,6 +274,23 @@ vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) return 0; } +void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq) +{ + int vid = dev->vid; + + /* Ensure no thread is using the vrings */ + put_device(vid); + dev = get_device_wr(vid); + + vq->access_ok = 0; + vq->desc = NULL; + vq->avail = NULL; + vq->used = NULL; + + put_device_wr(vid); + get_device(vid); +} + static void init_vring_queue(struct virtio_net *dev, uint32_t vring_idx) { diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h index 4b03977..9aef00e 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -358,5 +358,6 @@ void notify_iotlb_event(struct virtio_net *dev); uint64_t vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, uint64_t iova, uint64_t size, uint8_t perm); int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); +void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq); #endif /* _VHOST_NET_CDEV_H_ */ diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 0ebaac7..1ff83ca 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -356,11 +356,7 @@ vhost_user_set_vring_addr(struct virtio_net *dev, VhostUserMsg *msg) */ memcpy(&vq->ring_addrs, addr, sizeof(*addr)); - vq->desc = NULL; - vq->avail = NULL; - vq->used = NULL; - - vq->access_ok = 0; + vring_invalidate(dev, vq); return 0; } @@ -979,6 +975,35 @@ is_vring_iotlb_update(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) } static int +is_vring_iotlb_invalidate(struct vhost_virtqueue *vq, + struct vhost_iotlb_msg *imsg) +{ + uint64_t istart, iend, vstart, vend; + + istart = imsg->iova; + iend = istart + imsg->size - 1; + + vstart = (uint64_t)vq->desc; + vend = vstart + sizeof(struct vring_desc) * vq->size - 1; + if (vstart <= iend && istart <= vend) + return 1; + + vstart = (uint64_t)vq->avail; + vend = vstart + sizeof(struct vring_avail); + vend += sizeof(uint16_t) * vq->size - 1; + if (vstart <= iend && istart <= vend) + return 1; + + vstart = (uint64_t)vq->used; + vend = vstart + sizeof(struct vring_used); + vend += sizeof(struct vring_used_elem) * vq->size - 1; + if (vstart <= iend && istart <= vend) + return 1; + + return 0; +} + +static int vhost_user_iotlb_msg(struct virtio_net **pdev, struct VhostUserMsg *msg) { struct virtio_net *dev = *pdev; @@ -1009,6 +1034,9 @@ vhost_user_iotlb_msg(struct virtio_net **pdev, struct VhostUserMsg *msg) struct vhost_virtqueue *vq = dev->virtqueue[i]; vhost_user_iotlb_remove(vq, imsg->iova, imsg->size); + + if (is_vring_iotlb_invalidate(vq, imsg)) + vring_invalidate(dev, vq); } break; default: -- 2.9.4