]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - drivers/vhost/vhost.c
vhost: add helper to check if a vq has been setup
[mirror_ubuntu-hirsute-kernel.git] / drivers / vhost / vhost.c
index b45519ca66a7e9a0d0ff5fe9ead216db6297fded..a262e12c6dc26f76810ac28a833ea5deb1e70d74 100644 (file)
@@ -302,9 +302,14 @@ static void vhost_vring_call_reset(struct vhost_vring_call *call_ctx)
 {
        call_ctx->ctx = NULL;
        memset(&call_ctx->producer, 0x0, sizeof(struct irq_bypass_producer));
-       spin_lock_init(&call_ctx->ctx_lock);
 }
 
+bool vhost_vq_is_setup(struct vhost_virtqueue *vq)
+{
+       return vq->avail && vq->desc && vq->used && vhost_vq_access_ok(vq);
+}
+EXPORT_SYMBOL_GPL(vhost_vq_is_setup);
+
 static void vhost_vq_reset(struct vhost_dev *dev,
                           struct vhost_virtqueue *vq)
 {
@@ -1290,6 +1295,11 @@ static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num,
                         vring_used_t __user *used)
 
 {
+       /* If an IOTLB device is present, the vring addresses are
+        * GIOVAs. Access validation occurs at prefetch time. */
+       if (vq->iotlb)
+               return true;
+
        return access_ok(desc, vhost_get_desc_size(vq, num)) &&
               access_ok(avail, vhost_get_avail_size(vq, num)) &&
               access_ok(used, vhost_get_used_size(vq, num));
@@ -1365,6 +1375,20 @@ bool vhost_log_access_ok(struct vhost_dev *dev)
 }
 EXPORT_SYMBOL_GPL(vhost_log_access_ok);
 
+static bool vq_log_used_access_ok(struct vhost_virtqueue *vq,
+                                 void __user *log_base,
+                                 bool log_used,
+                                 u64 log_addr)
+{
+       /* If an IOTLB device is present, log_addr is a GIOVA that
+        * will never be logged by log_used(). */
+       if (vq->iotlb)
+               return true;
+
+       return !log_used || log_access_ok(log_base, log_addr,
+                                         vhost_get_used_size(vq, vq->num));
+}
+
 /* Verify access for write logging. */
 /* Caller should have vq mutex and device mutex */
 static bool vq_log_access_ok(struct vhost_virtqueue *vq,
@@ -1372,8 +1396,7 @@ static bool vq_log_access_ok(struct vhost_virtqueue *vq,
 {
        return vq_memory_access_ok(log_base, vq->umem,
                                   vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
-               (!vq->log_used || log_access_ok(log_base, vq->log_addr,
-                                 vhost_get_used_size(vq, vq->num)));
+               vq_log_used_access_ok(vq, log_base, vq->log_used, vq->log_addr);
 }
 
 /* Can we start vq? */
@@ -1383,10 +1406,6 @@ bool vhost_vq_access_ok(struct vhost_virtqueue *vq)
        if (!vq_log_access_ok(vq, vq->log_base))
                return false;
 
-       /* Access validation occurs at prefetch time with IOTLB */
-       if (vq->iotlb)
-               return true;
-
        return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used);
 }
 EXPORT_SYMBOL_GPL(vhost_vq_access_ok);
@@ -1516,10 +1535,9 @@ static long vhost_vring_set_addr(struct vhost_dev *d,
                        return -EINVAL;
 
                /* Also validate log access for used ring if enabled. */
-               if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
-                       !log_access_ok(vq->log_base, a.log_guest_addr,
-                               sizeof *vq->used +
-                               vq->num * sizeof *vq->used->ring))
+               if (!vq_log_used_access_ok(vq, vq->log_base,
+                               a.flags & (0x1 << VHOST_VRING_F_LOG),
+                               a.log_guest_addr))
                        return -EINVAL;
        }
 
@@ -1637,9 +1655,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
                        break;
                }
 
-               spin_lock(&vq->call_ctx.ctx_lock);
                swap(ctx, vq->call_ctx.ctx);
-               spin_unlock(&vq->call_ctx.ctx_lock);
                break;
        case VHOST_SET_VRING_ERR:
                if (copy_from_user(&f, argp, sizeof f)) {
@@ -1884,7 +1900,7 @@ static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
 
 static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
 {
-       struct iovec iov[64];
+       struct iovec *iov = vq->log_iov;
        int i, ret;
 
        if (!vq->iotlb)