76daa3
From 252e1d70fd15578a8ed365ee2c0face8f12bc149 Mon Sep 17 00:00:00 2001
76daa3
From: Maxime Coquelin <maxime.coquelin@redhat.com>
76daa3
Date: Tue, 6 Jun 2017 12:05:21 +0200
76daa3
Subject: [PATCH 10/17] vhost: rework IOTLB messaging
76daa3
76daa3
RH-Author: Maxime Coquelin <maxime.coquelin@redhat.com>
76daa3
Message-id: <20170606120524.3050-3-maxime.coquelin@redhat.com>
76daa3
Patchwork-id: 75497
76daa3
O-Subject: [RHV-7.4 qemu-kvm-rhev PATCH 2/5] vhost: rework IOTLB messaging
76daa3
Bugzilla: 1451862
76daa3
RH-Acked-by: Peter Xu <peterx@redhat.com>
76daa3
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
76daa3
RH-Acked-by: Jens Freimann <jfreiman@redhat.com>
76daa3
76daa3
This patch reworks IOTLB messaging to prepare for vhost-user
76daa3
device IOTLB support.
76daa3
76daa3
IOTLB messages handling is extracted from vhost-kernel backend,
76daa3
so that only the messages transport remains backend specifics.
76daa3
76daa3
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
76daa3
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
76daa3
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
76daa3
(cherry picked from commit 020e571b8bf90e022bbb78346e189f0f26e4675f)
76daa3
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
76daa3
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
---
76daa3
 hw/virtio/vhost-backend.c         | 130 +++++++++++++++++++++-----------------
76daa3
 hw/virtio/vhost.c                 |   8 +--
76daa3
 include/hw/virtio/vhost-backend.h |  23 ++++---
76daa3
 3 files changed, 92 insertions(+), 69 deletions(-)
76daa3
76daa3
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
76daa3
index be927b8..4e31de1 100644
76daa3
--- a/hw/virtio/vhost-backend.c
76daa3
+++ b/hw/virtio/vhost-backend.c
76daa3
@@ -192,7 +192,6 @@ static void vhost_kernel_iotlb_read(void *opaque)
76daa3
     ssize_t len;
76daa3
 
76daa3
     while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
76daa3
-        struct vhost_iotlb_msg *imsg = &msg.iotlb;
76daa3
         if (len < sizeof msg) {
76daa3
             error_report("Wrong vhost message len: %d", (int)len);
76daa3
             break;
76daa3
@@ -201,70 +200,21 @@ static void vhost_kernel_iotlb_read(void *opaque)
76daa3
             error_report("Unknown vhost iotlb message type");
76daa3
             break;
76daa3
         }
76daa3
-        switch (imsg->type) {
76daa3
-        case VHOST_IOTLB_MISS:
76daa3
-            vhost_device_iotlb_miss(dev, imsg->iova,
76daa3
-                                    imsg->perm != VHOST_ACCESS_RO);
76daa3
-            break;
76daa3
-        case VHOST_IOTLB_UPDATE:
76daa3
-        case VHOST_IOTLB_INVALIDATE:
76daa3
-            error_report("Unexpected IOTLB message type");
76daa3
-            break;
76daa3
-        case VHOST_IOTLB_ACCESS_FAIL:
76daa3
-            /* FIXME: report device iotlb error */
76daa3
-            break;
76daa3
-        default:
76daa3
-            break;
76daa3
-        }
76daa3
-    }
76daa3
-}
76daa3
 
76daa3
-static int vhost_kernel_update_device_iotlb(struct vhost_dev *dev,
76daa3
-                                            uint64_t iova, uint64_t uaddr,
76daa3
-                                            uint64_t len,
76daa3
-                                            IOMMUAccessFlags perm)
76daa3
-{
76daa3
-    struct vhost_msg msg;
76daa3
-    msg.type = VHOST_IOTLB_MSG;
76daa3
-    msg.iotlb.iova =  iova;
76daa3
-    msg.iotlb.uaddr = uaddr;
76daa3
-    msg.iotlb.size = len;
76daa3
-    msg.iotlb.type = VHOST_IOTLB_UPDATE;
76daa3
-
76daa3
-    switch (perm) {
76daa3
-    case IOMMU_RO:
76daa3
-        msg.iotlb.perm = VHOST_ACCESS_RO;
76daa3
-        break;
76daa3
-    case IOMMU_WO:
76daa3
-        msg.iotlb.perm = VHOST_ACCESS_WO;
76daa3
-        break;
76daa3
-    case IOMMU_RW:
76daa3
-        msg.iotlb.perm = VHOST_ACCESS_RW;
76daa3
-        break;
76daa3
-    default:
76daa3
-        g_assert_not_reached();
76daa3
-    }
76daa3
-
76daa3
-    if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
76daa3
-        error_report("Fail to update device iotlb");
76daa3
-        return -EFAULT;
76daa3
+        vhost_backend_handle_iotlb_msg(dev, &msg.iotlb);
76daa3
     }
76daa3
-
76daa3
-    return 0;
76daa3
 }
76daa3
 
76daa3
-static int vhost_kernel_invalidate_device_iotlb(struct vhost_dev *dev,
76daa3
-                                                uint64_t iova, uint64_t len)
76daa3
+static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev,
76daa3
+                                              struct vhost_iotlb_msg *imsg)
76daa3
 {
76daa3
     struct vhost_msg msg;
76daa3
 
76daa3
     msg.type = VHOST_IOTLB_MSG;
76daa3
-    msg.iotlb.iova = iova;
76daa3
-    msg.iotlb.size = len;
76daa3
-    msg.iotlb.type = VHOST_IOTLB_INVALIDATE;
76daa3
+    msg.iotlb = *imsg;
76daa3
 
76daa3
     if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
76daa3
-        error_report("Fail to invalidate device iotlb");
76daa3
+        error_report("Fail to update device iotlb");
76daa3
         return -EFAULT;
76daa3
     }
76daa3
 
76daa3
@@ -311,8 +261,7 @@ static const VhostOps kernel_ops = {
76daa3
         .vhost_vsock_set_running = vhost_kernel_vsock_set_running,
76daa3
 #endif /* CONFIG_VHOST_VSOCK */
76daa3
         .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
76daa3
-        .vhost_update_device_iotlb = vhost_kernel_update_device_iotlb,
76daa3
-        .vhost_invalidate_device_iotlb = vhost_kernel_invalidate_device_iotlb,
76daa3
+        .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
76daa3
 };
76daa3
 
76daa3
 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
76daa3
@@ -333,3 +282,70 @@ int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
76daa3
 
76daa3
     return r;
76daa3
 }
76daa3
+
76daa3
+int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
76daa3
+                                             uint64_t iova, uint64_t uaddr,
76daa3
+                                             uint64_t len,
76daa3
+                                             IOMMUAccessFlags perm)
76daa3
+{
76daa3
+    struct vhost_iotlb_msg imsg;
76daa3
+
76daa3
+    imsg.iova =  iova;
76daa3
+    imsg.uaddr = uaddr;
76daa3
+    imsg.size = len;
76daa3
+    imsg.type = VHOST_IOTLB_UPDATE;
76daa3
+
76daa3
+    switch (perm) {
76daa3
+    case IOMMU_RO:
76daa3
+        imsg.perm = VHOST_ACCESS_RO;
76daa3
+        break;
76daa3
+    case IOMMU_WO:
76daa3
+        imsg.perm = VHOST_ACCESS_WO;
76daa3
+        break;
76daa3
+    case IOMMU_RW:
76daa3
+        imsg.perm = VHOST_ACCESS_RW;
76daa3
+        break;
76daa3
+    default:
76daa3
+        return -EINVAL;
76daa3
+    }
76daa3
+
76daa3
+    return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
76daa3
+}
76daa3
+
76daa3
+int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
76daa3
+                                                 uint64_t iova, uint64_t len)
76daa3
+{
76daa3
+    struct vhost_iotlb_msg imsg;
76daa3
+
76daa3
+    imsg.iova = iova;
76daa3
+    imsg.size = len;
76daa3
+    imsg.type = VHOST_IOTLB_INVALIDATE;
76daa3
+
76daa3
+    return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg);
76daa3
+}
76daa3
+
76daa3
+int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
76daa3
+                                          struct vhost_iotlb_msg *imsg)
76daa3
+{
76daa3
+    int ret = 0;
76daa3
+
76daa3
+    switch (imsg->type) {
76daa3
+    case VHOST_IOTLB_MISS:
76daa3
+        ret = vhost_device_iotlb_miss(dev, imsg->iova,
76daa3
+                                      imsg->perm != VHOST_ACCESS_RO);
76daa3
+        break;
76daa3
+    case VHOST_IOTLB_ACCESS_FAIL:
76daa3
+        /* FIXME: report device iotlb error */
76daa3
+        error_report("Access failure IOTLB message type not supported");
76daa3
+        ret = -ENOTSUP;
76daa3
+        break;
76daa3
+    case VHOST_IOTLB_UPDATE:
76daa3
+    case VHOST_IOTLB_INVALIDATE:
76daa3
+    default:
76daa3
+        error_report("Unexpected IOTLB message type");
76daa3
+        ret = -EINVAL;
76daa3
+        break;
76daa3
+    }
76daa3
+
76daa3
+    return ret;
76daa3
+}
76daa3
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
76daa3
index 369373a..748e331 100644
76daa3
--- a/hw/virtio/vhost.c
76daa3
+++ b/hw/virtio/vhost.c
76daa3
@@ -724,8 +724,8 @@ static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
76daa3
     struct vhost_dev *hdev = iommu->hdev;
76daa3
     hwaddr iova = iotlb->iova + iommu->iommu_offset;
76daa3
 
76daa3
-    if (hdev->vhost_ops->vhost_invalidate_device_iotlb(hdev, iova,
76daa3
-                                                       iotlb->addr_mask + 1)) {
76daa3
+    if (vhost_backend_invalidate_device_iotlb(hdev, iova,
76daa3
+                                              iotlb->addr_mask + 1)) {
76daa3
         error_report("Fail to invalidate device iotlb");
76daa3
     }
76daa3
 }
76daa3
@@ -993,8 +993,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
76daa3
         len = MIN(iotlb.addr_mask + 1, len);
76daa3
         iova = iova & ~iotlb.addr_mask;
76daa3
 
76daa3
-        ret = dev->vhost_ops->vhost_update_device_iotlb(dev, iova, uaddr,
76daa3
-                                                      len, iotlb.perm);
76daa3
+        ret = vhost_backend_update_device_iotlb(dev, iova, uaddr,
76daa3
+                                                len, iotlb.perm);
76daa3
         if (ret) {
76daa3
             error_report("Fail to update device iotlb");
76daa3
             goto out;
76daa3
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
76daa3
index c3cf4a7..a7a5f22 100644
76daa3
--- a/include/hw/virtio/vhost-backend.h
76daa3
+++ b/include/hw/virtio/vhost-backend.h
76daa3
@@ -27,6 +27,7 @@ struct vhost_vring_file;
76daa3
 struct vhost_vring_state;
76daa3
 struct vhost_vring_addr;
76daa3
 struct vhost_scsi_target;
76daa3
+struct vhost_iotlb_msg;
76daa3
 
76daa3
 typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
76daa3
 typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
76daa3
@@ -81,12 +82,8 @@ typedef int (*vhost_vsock_set_guest_cid_op)(struct vhost_dev *dev,
76daa3
 typedef int (*vhost_vsock_set_running_op)(struct vhost_dev *dev, int start);
76daa3
 typedef void (*vhost_set_iotlb_callback_op)(struct vhost_dev *dev,
76daa3
                                            int enabled);
76daa3
-typedef int (*vhost_update_device_iotlb_op)(struct vhost_dev *dev,
76daa3
-                                            uint64_t iova, uint64_t uaddr,
76daa3
-                                            uint64_t len,
76daa3
-                                            IOMMUAccessFlags perm);
76daa3
-typedef int (*vhost_invalidate_device_iotlb_op)(struct vhost_dev *dev,
76daa3
-                                                uint64_t iova, uint64_t len);
76daa3
+typedef int (*vhost_send_device_iotlb_msg_op)(struct vhost_dev *dev,
76daa3
+                                              struct vhost_iotlb_msg *imsg);
76daa3
 
76daa3
 typedef struct VhostOps {
76daa3
     VhostBackendType backend_type;
76daa3
@@ -120,8 +117,7 @@ typedef struct VhostOps {
76daa3
     vhost_vsock_set_guest_cid_op vhost_vsock_set_guest_cid;
76daa3
     vhost_vsock_set_running_op vhost_vsock_set_running;
76daa3
     vhost_set_iotlb_callback_op vhost_set_iotlb_callback;
76daa3
-    vhost_update_device_iotlb_op vhost_update_device_iotlb;
76daa3
-    vhost_invalidate_device_iotlb_op vhost_invalidate_device_iotlb;
76daa3
+    vhost_send_device_iotlb_msg_op vhost_send_device_iotlb_msg;
76daa3
 } VhostOps;
76daa3
 
76daa3
 extern const VhostOps user_ops;
76daa3
@@ -129,4 +125,15 @@ extern const VhostOps user_ops;
76daa3
 int vhost_set_backend_type(struct vhost_dev *dev,
76daa3
                            VhostBackendType backend_type);
76daa3
 
76daa3
+int vhost_backend_update_device_iotlb(struct vhost_dev *dev,
76daa3
+                                             uint64_t iova, uint64_t uaddr,
76daa3
+                                             uint64_t len,
76daa3
+                                             IOMMUAccessFlags perm);
76daa3
+
76daa3
+int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev,
76daa3
+                                                 uint64_t iova, uint64_t len);
76daa3
+
76daa3
+int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev,
76daa3
+                                          struct vhost_iotlb_msg *imsg);
76daa3
+
76daa3
 #endif /* VHOST_BACKEND_H */
76daa3
-- 
76daa3
1.8.3.1
76daa3