7f1c5b
From d0e7f24a8d941ab142f2a1973ae18ed1bfdc074f Mon Sep 17 00:00:00 2001
7f1c5b
From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= <eperezma@redhat.com>
7f1c5b
Date: Thu, 15 Dec 2022 12:31:41 +0100
7f1c5b
Subject: [PATCH 09/14] vdpa: add asid parameter to vhost_vdpa_dma_map/unmap
7f1c5b
MIME-Version: 1.0
7f1c5b
Content-Type: text/plain; charset=UTF-8
7f1c5b
Content-Transfer-Encoding: 8bit
7f1c5b
7f1c5b
RH-Author: Eugenio Pérez <eperezma@redhat.com>
7f1c5b
RH-MergeRequest: 136: vDPA ASID support in Qemu
7f1c5b
RH-Bugzilla: 2104412
7f1c5b
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
7f1c5b
RH-Acked-by: Cindy Lu <lulu@redhat.com>
7f1c5b
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
7f1c5b
RH-Commit: [9/13] 3e7f89e57f73661017ccf0206f2ea77a72ca46bb (eperezmartin/qemu-kvm)
7f1c5b
7f1c5b
So the caller can choose which ASID is destined.
7f1c5b
7f1c5b
No need to update the batch functions as they will always be called from
7f1c5b
memory listener updates at the moment. Memory listener updates will
7f1c5b
always update ASID 0, as it's the passthrough ASID.
7f1c5b
7f1c5b
All vhost devices's ASID are 0 at this moment.
7f1c5b
7f1c5b
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
7f1c5b
Acked-by: Jason Wang <jasowang@redhat.com>
7f1c5b
Message-Id: <20221215113144.322011-10-eperezma@redhat.com>
7f1c5b
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
7f1c5b
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
7f1c5b
(cherry picked from commit cd831ed5c4add8ed6ee980c3645b241cbef5130f)
7f1c5b
---
7f1c5b
 hw/virtio/trace-events         |  4 ++--
7f1c5b
 hw/virtio/vhost-vdpa.c         | 36 +++++++++++++++++++++++-----------
7f1c5b
 include/hw/virtio/vhost-vdpa.h | 14 ++++++++++---
7f1c5b
 net/vhost-vdpa.c               |  6 +++---
7f1c5b
 4 files changed, 41 insertions(+), 19 deletions(-)
7f1c5b
7f1c5b
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
7f1c5b
index 46f2faf04e..a87c5f39a2 100644
7f1c5b
--- a/hw/virtio/trace-events
7f1c5b
+++ b/hw/virtio/trace-events
7f1c5b
@@ -30,8 +30,8 @@ vhost_user_write(uint32_t req, uint32_t flags) "req:%d flags:0x%"PRIx32""
7f1c5b
 vhost_user_create_notifier(int idx, void *n) "idx:%d n:%p"
7f1c5b
 
7f1c5b
 # vhost-vdpa.c
7f1c5b
-vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8
7f1c5b
-vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
7f1c5b
+vhost_vdpa_dma_map(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint64_t uaddr, uint8_t perm, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" uaddr: 0x%"PRIx64" perm: 0x%"PRIx8" type: %"PRIu8
7f1c5b
+vhost_vdpa_dma_unmap(void *vdpa, int fd, uint32_t msg_type, uint32_t asid, uint64_t iova, uint64_t size, uint8_t type) "vdpa:%p fd: %d msg_type: %"PRIu32" asid: %"PRIu32" iova: 0x%"PRIx64" size: 0x%"PRIx64" type: %"PRIu8
7f1c5b
 vhost_vdpa_listener_begin_batch(void *v, int fd, uint32_t msg_type, uint8_t type)  "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
7f1c5b
 vhost_vdpa_listener_commit(void *v, int fd, uint32_t msg_type, uint8_t type)  "vdpa:%p fd: %d msg_type: %"PRIu32" type: %"PRIu8
7f1c5b
 vhost_vdpa_listener_region_add(void *vdpa, uint64_t iova, uint64_t llend, void *vaddr, bool readonly) "vdpa: %p iova 0x%"PRIx64" llend 0x%"PRIx64" vaddr: %p read-only: %d"
7f1c5b
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
7f1c5b
index dd2768634b..0ecf2bbaa0 100644
7f1c5b
--- a/hw/virtio/vhost-vdpa.c
7f1c5b
+++ b/hw/virtio/vhost-vdpa.c
7f1c5b
@@ -72,22 +72,28 @@ static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section,
7f1c5b
     return false;
7f1c5b
 }
7f1c5b
 
7f1c5b
-int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
7f1c5b
-                       void *vaddr, bool readonly)
7f1c5b
+/*
7f1c5b
+ * The caller must set asid = 0 if the device does not support asid.
7f1c5b
+ * This is not an ABI break since it is set to 0 by the initializer anyway.
7f1c5b
+ */
7f1c5b
+int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
7f1c5b
+                       hwaddr size, void *vaddr, bool readonly)
7f1c5b
 {
7f1c5b
     struct vhost_msg_v2 msg = {};
7f1c5b
     int fd = v->device_fd;
7f1c5b
     int ret = 0;
7f1c5b
 
7f1c5b
     msg.type = v->msg_type;
7f1c5b
+    msg.asid = asid;
7f1c5b
     msg.iotlb.iova = iova;
7f1c5b
     msg.iotlb.size = size;
7f1c5b
     msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr;
7f1c5b
     msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW;
7f1c5b
     msg.iotlb.type = VHOST_IOTLB_UPDATE;
7f1c5b
 
7f1c5b
-   trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.iotlb.iova, msg.iotlb.size,
7f1c5b
-                            msg.iotlb.uaddr, msg.iotlb.perm, msg.iotlb.type);
7f1c5b
+    trace_vhost_vdpa_dma_map(v, fd, msg.type, msg.asid, msg.iotlb.iova,
7f1c5b
+                             msg.iotlb.size, msg.iotlb.uaddr, msg.iotlb.perm,
7f1c5b
+                             msg.iotlb.type);
7f1c5b
 
7f1c5b
     if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
7f1c5b
         error_report("failed to write, fd=%d, errno=%d (%s)",
7f1c5b
@@ -98,18 +104,24 @@ int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
7f1c5b
     return ret;
7f1c5b
 }
7f1c5b
 
7f1c5b
-int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size)
7f1c5b
+/*
7f1c5b
+ * The caller must set asid = 0 if the device does not support asid.
7f1c5b
+ * This is not an ABI break since it is set to 0 by the initializer anyway.
7f1c5b
+ */
7f1c5b
+int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
7f1c5b
+                         hwaddr size)
7f1c5b
 {
7f1c5b
     struct vhost_msg_v2 msg = {};
7f1c5b
     int fd = v->device_fd;
7f1c5b
     int ret = 0;
7f1c5b
 
7f1c5b
     msg.type = v->msg_type;
7f1c5b
+    msg.asid = asid;
7f1c5b
     msg.iotlb.iova = iova;
7f1c5b
     msg.iotlb.size = size;
7f1c5b
     msg.iotlb.type = VHOST_IOTLB_INVALIDATE;
7f1c5b
 
7f1c5b
-    trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.iotlb.iova,
7f1c5b
+    trace_vhost_vdpa_dma_unmap(v, fd, msg.type, msg.asid, msg.iotlb.iova,
7f1c5b
                                msg.iotlb.size, msg.iotlb.type);
7f1c5b
 
7f1c5b
     if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
7f1c5b
@@ -229,8 +241,8 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
7f1c5b
     }
7f1c5b
 
7f1c5b
     vhost_vdpa_iotlb_batch_begin_once(v);
7f1c5b
-    ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize),
7f1c5b
-                             vaddr, section->readonly);
7f1c5b
+    ret = vhost_vdpa_dma_map(v, VHOST_VDPA_GUEST_PA_ASID, iova,
7f1c5b
+                             int128_get64(llsize), vaddr, section->readonly);
7f1c5b
     if (ret) {
7f1c5b
         error_report("vhost vdpa map fail!");
7f1c5b
         goto fail_map;
7f1c5b
@@ -303,7 +315,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
7f1c5b
         vhost_iova_tree_remove(v->iova_tree, *result);
7f1c5b
     }
7f1c5b
     vhost_vdpa_iotlb_batch_begin_once(v);
7f1c5b
-    ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize));
7f1c5b
+    ret = vhost_vdpa_dma_unmap(v, VHOST_VDPA_GUEST_PA_ASID, iova,
7f1c5b
+                               int128_get64(llsize));
7f1c5b
     if (ret) {
7f1c5b
         error_report("vhost_vdpa dma unmap error!");
7f1c5b
     }
7f1c5b
@@ -876,7 +889,7 @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr)
7f1c5b
     }
7f1c5b
 
7f1c5b
     size = ROUND_UP(result->size, qemu_real_host_page_size());
7f1c5b
-    r = vhost_vdpa_dma_unmap(v, result->iova, size);
7f1c5b
+    r = vhost_vdpa_dma_unmap(v, v->address_space_id, result->iova, size);
7f1c5b
     if (unlikely(r < 0)) {
7f1c5b
         error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r);
7f1c5b
         return;
7f1c5b
@@ -916,7 +929,8 @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle,
7f1c5b
         return false;
7f1c5b
     }
7f1c5b
 
7f1c5b
-    r = vhost_vdpa_dma_map(v, needle->iova, needle->size + 1,
7f1c5b
+    r = vhost_vdpa_dma_map(v, v->address_space_id, needle->iova,
7f1c5b
+                           needle->size + 1,
7f1c5b
                            (void *)(uintptr_t)needle->translated_addr,
7f1c5b
                            needle->perm == IOMMU_RO);
7f1c5b
     if (unlikely(r != 0)) {
7f1c5b
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
7f1c5b
index 1111d85643..e57dfa1fd1 100644
7f1c5b
--- a/include/hw/virtio/vhost-vdpa.h
7f1c5b
+++ b/include/hw/virtio/vhost-vdpa.h
7f1c5b
@@ -19,6 +19,12 @@
7f1c5b
 #include "hw/virtio/virtio.h"
7f1c5b
 #include "standard-headers/linux/vhost_types.h"
7f1c5b
 
7f1c5b
+/*
7f1c5b
+ * ASID dedicated to map guest's addresses.  If SVQ is disabled it maps GPA to
7f1c5b
+ * qemu's IOVA.  If SVQ is enabled it maps also the SVQ vring here
7f1c5b
+ */
7f1c5b
+#define VHOST_VDPA_GUEST_PA_ASID 0
7f1c5b
+
7f1c5b
 typedef struct VhostVDPAHostNotifier {
7f1c5b
     MemoryRegion mr;
7f1c5b
     void *addr;
7f1c5b
@@ -29,6 +35,7 @@ typedef struct vhost_vdpa {
7f1c5b
     int index;
7f1c5b
     uint32_t msg_type;
7f1c5b
     bool iotlb_batch_begin_sent;
7f1c5b
+    uint32_t address_space_id;
7f1c5b
     MemoryListener listener;
7f1c5b
     struct vhost_vdpa_iova_range iova_range;
7f1c5b
     uint64_t acked_features;
7f1c5b
@@ -42,8 +49,9 @@ typedef struct vhost_vdpa {
7f1c5b
     VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
7f1c5b
 } VhostVDPA;
7f1c5b
 
7f1c5b
-int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size,
7f1c5b
-                       void *vaddr, bool readonly);
7f1c5b
-int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, hwaddr size);
7f1c5b
+int vhost_vdpa_dma_map(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
7f1c5b
+                       hwaddr size, void *vaddr, bool readonly);
7f1c5b
+int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, uint32_t asid, hwaddr iova,
7f1c5b
+                         hwaddr size);
7f1c5b
 
7f1c5b
 #endif
7f1c5b
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
7f1c5b
index 85aa0da39a..c2f319eb88 100644
7f1c5b
--- a/net/vhost-vdpa.c
7f1c5b
+++ b/net/vhost-vdpa.c
7f1c5b
@@ -258,7 +258,7 @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr)
7f1c5b
         return;
7f1c5b
     }
7f1c5b
 
7f1c5b
-    r = vhost_vdpa_dma_unmap(v, map->iova, map->size + 1);
7f1c5b
+    r = vhost_vdpa_dma_unmap(v, v->address_space_id, map->iova, map->size + 1);
7f1c5b
     if (unlikely(r != 0)) {
7f1c5b
         error_report("Device cannot unmap: %s(%d)", g_strerror(r), r);
7f1c5b
     }
7f1c5b
@@ -298,8 +298,8 @@ static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size,
7f1c5b
         return r;
7f1c5b
     }
7f1c5b
 
7f1c5b
-    r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf,
7f1c5b
-                           !write);
7f1c5b
+    r = vhost_vdpa_dma_map(v, v->address_space_id, map.iova,
7f1c5b
+                           vhost_vdpa_net_cvq_cmd_page_len(), buf, !write);
7f1c5b
     if (unlikely(r < 0)) {
7f1c5b
         goto dma_map_err;
7f1c5b
     }
7f1c5b
-- 
7f1c5b
2.31.1
7f1c5b