All of lore.kernel.org
 help / color / mirror / Atom feed
From: Connor Kite <connorkite@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	"Stefano Garzarella" <sgarzare@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Viresh Kumar" <viresh.kumar@linaro.org>,
	"Gerd Hoffmann" <kraxel@redhat.com>,
	"Mathieu Poirier" <mathieu.poirier@linaro.org>,
	"Manos Pitsidianakis" <manos.pitsidianakis@linaro.org>,
	"Raphael Norwitz" <rnorwitz@nvidia.com>,
	"Kevin Wolf" <kwolf@redhat.com>,
	"Hanna Reitz" <hreitz@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Fam Zheng" <fam@euphon.net>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Milan Zamazal" <mzamazal@redhat.com>,
	"Akihiko Odaki" <odaki@rsg.ci.i.u-tokyo.ac.jp>,
	"Dmitry Osipenko" <dmitry.osipenko@collabora.com>,
	qemu-block@nongnu.org, virtio-fs@lists.linux.dev,
	"Gonglei (Arei)" <arei.gonglei@huawei.com>,
	"zhenwei pi" <zhenwei.pi@linux.dev>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Jason Wang" <jasowangio@gmail.com>,
	"Peter Xu" <peterx@redhat.com>,
	"Eugenio Pérez" <eperezma@redhat.com>,
	"Alyssa Ross" <hi@alyssa.is>,
	"Demi Marie Obenour" <demiobenour@gmail.com>,
	"Connor Kite" <connorkite@gmail.com>,
	20260817233147.2867623-1-connorkite@gmail.com
Subject: [PATCH RFC v2 09/13] hw/virtio/vhost-user: add shadow virtqueues and eventfd intercepts
Date: Mon, 17 Aug 2026 22:12:24 -0700	[thread overview]
Message-ID: <20260817-vhost-user-isolated-memory-v2-9-948aae960abb@gmail.com> (raw)
In-Reply-To: <20260817-vhost-user-isolated-memory-v2-0-948aae960abb@gmail.com>

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 <connorkite@gmail.com>
---
 hw/virtio/vhost-user.c | 136 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 119 insertions(+), 17 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index e1e5cba53d..ace328f5eb 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"
@@ -331,6 +332,7 @@ typedef struct {
     size_t size; /* size of the mapped shared memory */
     int fd; /* descriptor of anonymous file backing shared iso region */
     Int128 iso_iova_offset; /* translation from IOVA to hva of iso region */
+    GPtrArray *shadow_vqs; /* shadow vqs with vrings in iso region*/
 } IsolationModeCtx;
 
 struct vhost_user {
@@ -1128,15 +1130,38 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev,
     return 0;
 }
 
-static void cleanup_isolation_regions(struct vhost_dev *dev)
+static void vhost_user_svq_cleanup(struct vhost_user *u, bool reset)
+{
+    VhostShadowVirtqueue *svq;
+    for (int i = 0; i < u->iso_mem_ctx.shadow_vqs->len; i++) {
+        svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, i);
+        vhost_svq_stop(svq);
+        event_notifier_cleanup(&svq->hdev_call);
+        event_notifier_cleanup(&svq->hdev_kick);
+    }
+
+    if (!reset) {
+        g_ptr_array_free(u->iso_mem_ctx.shadow_vqs, true);
+    }
+}
+
+static void cleanup_isolation_regions(struct vhost_dev *dev, bool reset)
 {
     struct vhost_user *u = dev->opaque;
     if (u->iso_mem_ctx.shared_mem_addr) {
+        vhost_user_svq_cleanup(u, reset);
         vhost_iova_tree_delete(u->iso_mem_ctx.tree);
         qemu_memfd_free(u->iso_mem_ctx.shared_mem_addr,
                         u->iso_mem_ctx.size,
                         u->iso_mem_ctx.fd);
+
+        GPtrArray *temp = u->iso_mem_ctx.shadow_vqs;
         memset(&u->iso_mem_ctx, 0, sizeof(IsolationModeCtx));
+
+        if (!reset) {
+            u->iso_mem_ctx.shadow_vqs = temp;
+        }
+
     }
 }
 
@@ -1234,7 +1259,7 @@ static int init_isolation_regions(struct vhost_dev *dev,
     msg->hdr.request = VHOST_USER_SET_MEM_TABLE;
 
     /* In case of reset, clear old regions */
-    cleanup_isolation_regions(dev);
+    cleanup_isolation_regions(dev, true);
 
     /* Gather information for bounce buffers to be mapped */
     for (u_int32_t i = 0; i < nregions; i++) {
@@ -1267,7 +1292,7 @@ static int init_isolation_regions(struct vhost_dev *dev,
 
     if (err) {
         error_report_err(err);
-        cleanup_isolation_regions(dev);
+        cleanup_isolation_regions(dev, false);
         return -1;
     }
 
@@ -1295,7 +1320,7 @@ static int init_isolation_regions(struct vhost_dev *dev,
                                   (hwaddr)u->iso_mem_ctx.shared_mem_addr);
 
     if (r != IOVA_OK) {
-        cleanup_isolation_regions(dev);
+        cleanup_isolation_regions(dev, false);
         return r;
     }
 
@@ -1310,7 +1335,7 @@ static int init_isolation_regions(struct vhost_dev *dev,
                                           dev->mem->regions[i].guest_phys_addr);
 
         if (r != IOVA_OK) {
-            cleanup_isolation_regions(dev);
+            cleanup_isolation_regions(dev, false);
             return r;
         }
     }
@@ -1738,11 +1763,49 @@ static int vhost_set_vring_file(struct vhost_dev *dev,
     return 0;
 }
 
+static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
+{
+    assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
+
+    return idx;
+}
+
 static int vhost_user_set_vring_kick(struct vhost_dev *dev,
                                      struct vhost_vring_file *file)
 {
-    int ret = vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file);
+    struct vhost_user *u = dev->opaque;
+    int svq_idx = file->index - dev->vq_index;
+    VhostShadowVirtqueue *svq = NULL;
+    struct vhost_vring_file vr_file = *file;
+    int ret;
+
+    vhost_user_get_vq_index(dev, file->index); /* bounds checking */
+
+    if (u->user->memory_isolation) {
+        svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, svq_idx);
+        vhost_svq_set_svq_kick_fd(svq, file->fd);
+
+        if (file->fd != -1) {
+            if (!svq->hdev_kick.initialized) {
+                ret = event_notifier_init(&svq->hdev_kick, 0);
+                if (ret < 0) {
+                    event_notifier_cleanup(&svq->hdev_kick);
+                    error_report("Failed to create kick event notifier");
+                    return ret;
+                }
+            }
+
+            vr_file.fd = event_notifier_get_fd(&svq->hdev_kick);
+        } else {
+            event_notifier_cleanup(&svq->hdev_kick);
+        }
+    }
+
+    ret = vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, &vr_file);
     if (ret < 0) {
+        if (svq != NULL) {
+            event_notifier_cleanup(&svq->hdev_kick);
+        }
         return ret;
     }
 
@@ -1750,15 +1813,18 @@ static int vhost_user_set_vring_kick(struct vhost_dev *dev,
      * Inject a kick in case the back-end only starts vring processing upon
      * receiving a kick. The spec suggests this to improve compatibility.
      */
-    if (file->fd != -1) {
+    if (vr_file.fd != -1) {
         uint64_t val = 1;
         ssize_t nwritten;
 
         do {
-            nwritten = write(file->fd, &val, sizeof(val));
+            nwritten = write(vr_file.fd, &val, sizeof(val));
         } while (nwritten < 0 && errno == EINTR);
 
         if (nwritten < 0 && errno != EAGAIN /* back-end can already read */) {
+            if (svq != NULL) {
+                event_notifier_cleanup(&svq->hdev_kick);
+            }
             return -errno;
         }
     }
@@ -1769,7 +1835,35 @@ 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)
 {
-    return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
+    struct vhost_user *u = dev->opaque;
+    int svq_idx = file->index - dev->vq_index;
+    VhostShadowVirtqueue *svq = NULL;
+    struct vhost_vring_file vr_file = *file;
+    int ret;
+
+    vhost_user_get_vq_index(dev, file->index); /* bounds checking */
+
+    if (u->user->memory_isolation) {
+        svq = g_ptr_array_index(u->iso_mem_ctx.shadow_vqs, svq_idx);
+        vhost_svq_set_svq_call_fd(svq, file->fd);
+
+        if (file->fd != -1) {
+            if (!svq->hdev_call.initialized) {
+                ret = event_notifier_init(&svq->hdev_call, 0);
+                if (ret < 0) {
+                    event_notifier_cleanup(&svq->hdev_call);
+                    error_report("Failed to create call event notifier");
+                    return ret;
+                }
+            }
+
+            vr_file.fd = event_notifier_get_fd(&svq->hdev_call);
+        } else {
+            event_notifier_cleanup(&svq->hdev_call);
+        }
+    }
+
+    return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, &vr_file);
 }
 
 static int vhost_user_set_vring_err(struct vhost_dev *dev,
@@ -2763,6 +2857,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->iso_mem_ctx.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);
+        g_ptr_array_add(u->iso_mem_ctx.shadow_vqs, svq);
+    }
+}
+
 static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque,
                                    Error **errp)
 {
@@ -2907,6 +3012,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;
 }
 
@@ -2935,20 +3044,13 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev)
     g_free(u->region_rb_offset);
     u->region_rb_offset = NULL;
     u->region_rb_len = 0;
-    cleanup_isolation_regions(dev);
+    cleanup_isolation_regions(dev, false);
     g_free(u);
     dev->opaque = 0;
 
     return 0;
 }
 
-static int vhost_user_get_vq_index(struct vhost_dev *dev, int idx)
-{
-    assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
-
-    return idx;
-}
-
 static int vhost_user_memslots_limit(struct vhost_dev *dev)
 {
     struct vhost_user *u = dev->opaque;

-- 
2.43.0


  parent reply	other threads:[~2026-08-18  5:12 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-18  5:12 [PATCH RFC v2 00/13] vhost-user: isolated memory Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 01/13] vhost-user: Consolidate chardev property definitions Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 02/13] util/iova-tree: g_tree_foreach wrapper Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 03/13] hw/virtio: iova_tree_foreach wrapper Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 04/13] hw/virtio/vhost-shadow-virtqueue: used callback Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 05/13] hw/virtio/vhost-shadow-virtqueue: specified vring placement Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 06/13] vhost-user: add memory_isolation to VhostUserState Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 07/13] hw/virtio/vhost-user: create isolation region Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 08/13] hw/virtio/vhost-user: send isolation regions to device Connor Kite
2026-08-18  5:12 ` Connor Kite [this message]
2026-08-18  5:12 ` [PATCH RFC v2 10/13] hw/virtio/vhost-user: handle data movement with shadow vqs Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 11/13] vhost-user: Add memory-isolation qdev property to vhost-user devices Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 12/13] backends/cryptodev-vhost-user: add memory isolation bool Connor Kite
2026-08-18  5:12 ` [PATCH RFC v2 13/13] net/vhost-user: add memory isolation Connor Kite

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260817-vhost-user-isolated-memory-v2-9-948aae960abb@gmail.com \
    --to=connorkite@gmail.com \
    --cc=20260817233147.2867623-1-connorkite@gmail.com \
    --cc=alex.bennee@linaro.org \
    --cc=arei.gonglei@huawei.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=demiobenour@gmail.com \
    --cc=dmitry.osipenko@collabora.com \
    --cc=eblake@redhat.com \
    --cc=eperezma@redhat.com \
    --cc=fam@euphon.net \
    --cc=hi@alyssa.is \
    --cc=hreitz@redhat.com \
    --cc=jasowangio@gmail.com \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=manos.pitsidianakis@linaro.org \
    --cc=marcandre.lureau@redhat.com \
    --cc=mathieu.poirier@linaro.org \
    --cc=mst@redhat.com \
    --cc=mzamazal@redhat.com \
    --cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rnorwitz@nvidia.com \
    --cc=sgarzare@redhat.com \
    --cc=stefanha@redhat.com \
    --cc=viresh.kumar@linaro.org \
    --cc=virtio-fs@lists.linux.dev \
    --cc=zhenwei.pi@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.