Re: [PATCH RFC 13/15] hw/virtio/vhost-user: add shadow virtqueues and eventfd intercepts
Hanna Czenczek <[email protected]> Mon, 3 Aug 2026 15:52:28 +0200
| Newsgroups | dev.linux.lists.virtio-fs,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
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; > } > >