29b115
From c33bc0b7f2b5cfa330a6d89d60ee94de129c65c1 Mon Sep 17 00:00:00 2001
29b115
From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= <eperezma@redhat.com>
29b115
Date: Thu, 21 Jul 2022 16:05:38 +0200
29b115
Subject: [PATCH 23/32] vdpa: manual forward CVQ buffers
29b115
MIME-Version: 1.0
29b115
Content-Type: text/plain; charset=UTF-8
29b115
Content-Transfer-Encoding: 8bit
29b115
29b115
RH-Author: Eugenio Pérez <eperezma@redhat.com>
29b115
RH-MergeRequest: 108: Net Control Virtqueue shadow Support
29b115
RH-Commit: [23/27] ce128d5152be7eebf87e186eb8b58c2ed95aff6d (eperezmartin/qemu-kvm)
29b115
RH-Bugzilla: 1939363
29b115
RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
29b115
RH-Acked-by: Cindy Lu <lulu@redhat.com>
29b115
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
29b115
29b115
Bugzilla: https://bugzilla.redhat.com/1939363
29b115
29b115
Upstream Status: git://git.qemu.org/qemu.git
29b115
29b115
commit bd907ae4b00ebedad5e586af05ea3d6490318d45
29b115
Author: Eugenio Pérez <eperezma@redhat.com>
29b115
Date:   Wed Jul 20 08:59:42 2022 +0200
29b115
29b115
    vdpa: manual forward CVQ buffers
29b115
29b115
    Do a simple forwarding of CVQ buffers, the same work SVQ could do but
29b115
    through callbacks. No functional change intended.
29b115
29b115
    Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
29b115
    Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
29b115
    Signed-off-by: Jason Wang <jasowang@redhat.com>
29b115
29b115
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
29b115
---
29b115
 hw/virtio/vhost-vdpa.c         |  3 +-
29b115
 include/hw/virtio/vhost-vdpa.h |  3 ++
29b115
 net/vhost-vdpa.c               | 58 ++++++++++++++++++++++++++++++++++
29b115
 3 files changed, 63 insertions(+), 1 deletion(-)
29b115
29b115
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
29b115
index 14b02fe079..49effe5462 100644
29b115
--- a/hw/virtio/vhost-vdpa.c
29b115
+++ b/hw/virtio/vhost-vdpa.c
29b115
@@ -417,7 +417,8 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v,
29b115
     for (unsigned n = 0; n < hdev->nvqs; ++n) {
29b115
         g_autoptr(VhostShadowVirtqueue) svq;
29b115
 
29b115
-        svq = vhost_svq_new(v->iova_tree, NULL, NULL);
29b115
+        svq = vhost_svq_new(v->iova_tree, v->shadow_vq_ops,
29b115
+                            v->shadow_vq_ops_opaque);
29b115
         if (unlikely(!svq)) {
29b115
             error_setg(errp, "Cannot create svq %u", n);
29b115
             return -1;
29b115
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
29b115
index 7214eb47dc..1111d85643 100644
29b115
--- a/include/hw/virtio/vhost-vdpa.h
29b115
+++ b/include/hw/virtio/vhost-vdpa.h
29b115
@@ -15,6 +15,7 @@
29b115
 #include <gmodule.h>
29b115
 
29b115
 #include "hw/virtio/vhost-iova-tree.h"
29b115
+#include "hw/virtio/vhost-shadow-virtqueue.h"
29b115
 #include "hw/virtio/virtio.h"
29b115
 #include "standard-headers/linux/vhost_types.h"
29b115
 
29b115
@@ -35,6 +36,8 @@ typedef struct vhost_vdpa {
29b115
     /* IOVA mapping used by the Shadow Virtqueue */
29b115
     VhostIOVATree *iova_tree;
29b115
     GPtrArray *shadow_vqs;
29b115
+    const VhostShadowVirtqueueOps *shadow_vq_ops;
29b115
+    void *shadow_vq_ops_opaque;
29b115
     struct vhost_dev *dev;
29b115
     VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
29b115
 } VhostVDPA;
29b115
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
29b115
index df1e69ee72..2e3b6b10d8 100644
29b115
--- a/net/vhost-vdpa.c
29b115
+++ b/net/vhost-vdpa.c
29b115
@@ -11,11 +11,14 @@
29b115
 
29b115
 #include "qemu/osdep.h"
29b115
 #include "clients.h"
29b115
+#include "hw/virtio/virtio-net.h"
29b115
 #include "net/vhost_net.h"
29b115
 #include "net/vhost-vdpa.h"
29b115
 #include "hw/virtio/vhost-vdpa.h"
29b115
 #include "qemu/config-file.h"
29b115
 #include "qemu/error-report.h"
29b115
+#include "qemu/log.h"
29b115
+#include "qemu/memalign.h"
29b115
 #include "qemu/option.h"
29b115
 #include "qapi/error.h"
29b115
 #include <linux/vhost.h>
29b115
@@ -187,6 +190,57 @@ static NetClientInfo net_vhost_vdpa_info = {
29b115
         .check_peer_type = vhost_vdpa_check_peer_type,
29b115
 };
29b115
 
29b115
+/**
29b115
+ * Forward buffer for the moment.
29b115
+ */
29b115
+static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
29b115
+                                            VirtQueueElement *elem,
29b115
+                                            void *opaque)
29b115
+{
29b115
+    unsigned int n = elem->out_num + elem->in_num;
29b115
+    g_autofree struct iovec *dev_buffers = g_new(struct iovec, n);
29b115
+    size_t in_len, dev_written;
29b115
+    virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
29b115
+    int r;
29b115
+
29b115
+    memcpy(dev_buffers, elem->out_sg, elem->out_num);
29b115
+    memcpy(dev_buffers + elem->out_num, elem->in_sg, elem->in_num);
29b115
+
29b115
+    r = vhost_svq_add(svq, &dev_buffers[0], elem->out_num, &dev_buffers[1],
29b115
+                      elem->in_num, elem);
29b115
+    if (unlikely(r != 0)) {
29b115
+        if (unlikely(r == -ENOSPC)) {
29b115
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
29b115
+                          __func__);
29b115
+        }
29b115
+        goto out;
29b115
+    }
29b115
+
29b115
+    /*
29b115
+     * We can poll here since we've had BQL from the time we sent the
29b115
+     * descriptor. Also, we need to take the answer before SVQ pulls by itself,
29b115
+     * when BQL is released
29b115
+     */
29b115
+    dev_written = vhost_svq_poll(svq);
29b115
+    if (unlikely(dev_written < sizeof(status))) {
29b115
+        error_report("Insufficient written data (%zu)", dev_written);
29b115
+    }
29b115
+
29b115
+out:
29b115
+    in_len = iov_from_buf(elem->in_sg, elem->in_num, 0, &status,
29b115
+                          sizeof(status));
29b115
+    if (unlikely(in_len < sizeof(status))) {
29b115
+        error_report("Bad device CVQ written length");
29b115
+    }
29b115
+    vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
29b115
+    g_free(elem);
29b115
+    return r;
29b115
+}
29b115
+
29b115
+static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = {
29b115
+    .avail_handler = vhost_vdpa_net_handle_ctrl_avail,
29b115
+};
29b115
+
29b115
 static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
29b115
                                            const char *device,
29b115
                                            const char *name,
29b115
@@ -211,6 +265,10 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
29b115
 
29b115
     s->vhost_vdpa.device_fd = vdpa_device_fd;
29b115
     s->vhost_vdpa.index = queue_pair_index;
29b115
+    if (!is_datapath) {
29b115
+        s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops;
29b115
+        s->vhost_vdpa.shadow_vq_ops_opaque = s;
29b115
+    }
29b115
     ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
29b115
     if (ret) {
29b115
         qemu_del_net_client(nc);
29b115
-- 
29b115
2.31.1
29b115