On 24.07.26 00:30, Connor Kite wrote:
Adds shadow virtqueues that will eventually be used to transfer data
between device and host via bounce buffers when isolation mode is
active.  The svqs are initalized, and eventfd assignments are
intercepted so that notifications come to svqs first before
the guest or backend receive them.

Signed-off-by: Connor Kite <[email protected]>
---
  hw/virtio/vhost-user.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
  1 file changed, 54 insertions(+)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index acabfb7f1c..75858289a2 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -18,6 +18,7 @@
  #include "hw/virtio/vhost-backend.h"
  #include "hw/virtio/virtio.h"
  #include "hw/virtio/virtio-net.h"
+#include "hw/virtio/vhost-shadow-virtqueue.h"
  #include "hw/virtio/vhost-iova-tree.h"
  #include "chardev/char-fe.h"
  #include "io/channel-socket.h"
@@ -365,7 +366,9 @@ struct vhost_user {
/* Isolated memory data*/
      struct IsolationRegion iso_memory;
+    GPtrArray *shadow_vqs;
      VhostIOVATree *iso_iova_tree;
+    bool svqs_allocated;
  };
struct scrub_regions {
@@ -1693,6 +1696,24 @@ static int vhost_set_vring_file(struct vhost_dev *dev,
  static int vhost_user_set_vring_kick(struct vhost_dev *dev,
                                       struct vhost_vring_file *file)
  {
+    struct vhost_user *u = dev->opaque;
+    int svq_idx = file->index - dev->vq_index;
+    if (u->user->memory_isolation) {
+        VhostShadowVirtqueue *svq = g_ptr_array_index(u->shadow_vqs,
+                                                      svq_idx);

Bounds checking via `vhost_user_get_vq_index()` would be nice. (Same below.)

+        vhost_svq_set_svq_kick_fd(svq, file->fd);
+
+        if (svq->hdev_kick.initialized == false) {
+            int r = event_notifier_init(&svq->hdev_kick, 0);
+            if (r) {
+                error_report("Failed to create kick event notifier");
+                return r;
+            }
+        }
+
+        file->fd = event_notifier_get_fd(&svq->hdev_kick);

What if `file->fd` was -1, i.e. `VHOST_FILE_UNBIND`? Should we put a real FD here then or just continue with -1?

+    }
+
      int ret = vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
      if (ret < 0) {
          return ret;
@@ -1721,6 +1742,24 @@ static int vhost_user_set_vring_kick(struct vhost_dev 
*dev,
  static int vhost_user_set_vring_call(struct vhost_dev *dev,
                                       struct vhost_vring_file *file)
  {
+    struct vhost_user *u = dev->opaque;
+    int svq_idx = file->index - dev->vq_index;
+    if (u->user->memory_isolation) {
+        VhostShadowVirtqueue *svq = g_ptr_array_index(u->shadow_vqs,
+                                                      svq_idx);
+        vhost_svq_set_svq_call_fd(svq, file->fd);
+
+        if (svq->hdev_call.initialized == false) {
+            int r = event_notifier_init(&svq->hdev_call, 0);

Do we need to check if the call event FD is already active?

+            if (r) {
+                error_report("Failed to create call event notifier");
+                return r;
+            }
+        }
+
+        file->fd = event_notifier_get_fd(&svq->hdev_call);
+    }
+
      return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
  }
@@ -2715,6 +2754,17 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
      return 0;
  }
+static void vhost_user_init_svq(struct vhost_dev *dev, struct vhost_user *u)
+{
+    /*Modified from vhost-vdpa*/
+    u->shadow_vqs = g_ptr_array_new_full(dev->nvqs, vhost_svq_free);
+    for (int i = 0; i < dev->nvqs; i++) {
+        VhostShadowVirtqueue *svq;
+        svq = vhost_svq_new(NULL, NULL);

Patch 15 adds clean-up for this; I would squash it into here, as far as possible. Ideally, a patch series can be stopped at any step and not break anything, so if an allocation is added, the accompanying freeing should come with it.

Hanna

+        g_ptr_array_add(u->shadow_vqs, svq);
+    }
+}
+
  static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
                                     Error **errp)
  {
@@ -2859,6 +2909,10 @@ static int vhost_user_backend_init(struct vhost_dev 
*dev, void *opaque,
      u->postcopy_notifier.notify = vhost_user_postcopy_notifier;
      postcopy_add_notifier(&u->postcopy_notifier);
+ if (vus->memory_isolation) {
+        vhost_user_init_svq(dev, u);
+    }
+
      return 0;
  }


Reply via email to