vhost: fix vring addresses not translated
[dpdk.git] / lib / librte_vhost / vhost.c
index 65606f6..4f8b73a 100644 (file)
@@ -55,6 +55,7 @@
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
+/* Called with iotlb_lock read-locked */
 uint64_t
 __vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
                    uint64_t iova, uint64_t size, uint8_t perm)
@@ -71,8 +72,19 @@ __vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
                return vva;
 
        if (!vhost_user_iotlb_pending_miss(vq, iova + tmp_size, perm)) {
+               /*
+                * iotlb_lock is read-locked for a full burst,
+                * but it only protects the iotlb cache.
+                * In case of IOTLB miss, we might block on the socket,
+                * which could cause a deadlock with QEMU if an IOTLB update
+                * is being handled. We can safely unlock here to avoid it.
+                */
+               vhost_user_iotlb_rd_unlock(vq);
+
                vhost_user_iotlb_pending_insert(vq, iova + tmp_size, perm);
                vhost_user_iotlb_miss(dev, iova + tmp_size, perm);
+
+               vhost_user_iotlb_rd_lock(vq);
        }
 
        return 0;
@@ -173,6 +185,21 @@ out:
        return 0;
 }
 
+void
+vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq)
+{
+       if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
+               vhost_user_iotlb_wr_lock(vq);
+
+       vq->access_ok = 0;
+       vq->desc = NULL;
+       vq->avail = NULL;
+       vq->used = NULL;
+
+       if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
+               vhost_user_iotlb_wr_unlock(vq);
+}
+
 static void
 init_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {