OSDN Git Service

vringh: add 'iotlb_lock' to synchronize iotlb accesses
authorStefano Garzarella <sgarzare@redhat.com>
Mon, 15 Mar 2021 16:34:38 +0000 (17:34 +0100)
committerMichael S. Tsirkin <mst@redhat.com>
Mon, 3 May 2021 08:55:52 +0000 (04:55 -0400)
Usually iotlb accesses are synchronized with a spinlock.
Let's request it as a new parameter in vringh_set_iotlb() and
hold it when we navigate the iotlb in iotlb_translate() to avoid
race conditions with any new additions/deletions of ranges from
the ioltb.

Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Link: https://lore.kernel.org/r/20210315163450.254396-3-sgarzare@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vhost/vringh.c
include/linux/vringh.h

index fc2ec95..a92c088 100644 (file)
@@ -284,7 +284,8 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
                goto err_iommu;
 
        for (i = 0; i < dev_attr->nvqs; i++)
-               vringh_set_iotlb(&vdpasim->vqs[i].vring, vdpasim->iommu);
+               vringh_set_iotlb(&vdpasim->vqs[i].vring, vdpasim->iommu,
+                                &vdpasim->iommu_lock);
 
        ret = iova_cache_get();
        if (ret)
index 85d85fa..f681227 100644 (file)
@@ -1074,6 +1074,8 @@ static int iotlb_translate(const struct vringh *vrh,
        int ret = 0;
        u64 s = 0;
 
+       spin_lock(vrh->iotlb_lock);
+
        while (len > s) {
                u64 size, pa, pfn;
 
@@ -1103,6 +1105,8 @@ static int iotlb_translate(const struct vringh *vrh,
                ++ret;
        }
 
+       spin_unlock(vrh->iotlb_lock);
+
        return ret;
 }
 
@@ -1262,10 +1266,13 @@ EXPORT_SYMBOL(vringh_init_iotlb);
  * vringh_set_iotlb - initialize a vringh for a ring with IOTLB.
  * @vrh: the vring
  * @iotlb: iotlb associated with this vring
+ * @iotlb_lock: spinlock to synchronize the iotlb accesses
  */
-void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb)
+void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
+                     spinlock_t *iotlb_lock)
 {
        vrh->iotlb = iotlb;
+       vrh->iotlb_lock = iotlb_lock;
 }
 EXPORT_SYMBOL(vringh_set_iotlb);
 
index 59bd50f..9c07786 100644 (file)
@@ -46,6 +46,9 @@ struct vringh {
        /* IOTLB for this vring */
        struct vhost_iotlb *iotlb;
 
+       /* spinlock to synchronize IOTLB accesses */
+       spinlock_t *iotlb_lock;
+
        /* The function to call to notify the guest about added buffers */
        void (*notify)(struct vringh *);
 };
@@ -258,7 +261,8 @@ static inline __virtio64 cpu_to_vringh64(const struct vringh *vrh, u64 val)
 
 #if IS_REACHABLE(CONFIG_VHOST_IOTLB)
 
-void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb);
+void vringh_set_iotlb(struct vringh *vrh, struct vhost_iotlb *iotlb,
+                     spinlock_t *iotlb_lock);
 
 int vringh_init_iotlb(struct vringh *vrh, u64 features,
                      unsigned int num, bool weak_barriers,