On Thu, Jul 23, 2026 at 03:30:12PM -0700, 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); > + vhost_svq_set_svq_kick_fd(svq, file->fd); > + > + if (svq->hdev_kick.initialized == false) { > + int r = event_notifier_init(&svq->hdev_kick, 0);
Where is event_notifier_cleanup() called?
> + if (r) {
> + error_report("Failed to create kick event notifier");
> + return r;
> + }
> + }
> +
> + file->fd = event_notifier_get_fd(&svq->hdev_kick);
Modifying the function argument is probably not expected but
vhost_virtqueue_start() doesn't use it after this call, so there is no
immediate problem. It would be safer to have a local struct
vhost_vring_file that can be modified without affecting the caller's
copy.
> + }
> +
> 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);
Where is event_notifier_cleanup() called?
> + if (r) {
> + error_report("Failed to create call event notifier");
> + return r;
> + }
> + }
> +
> + file->fd = event_notifier_get_fd(&svq->hdev_call);
Same as above.
> + }
> +
> 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);
> + 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;
> }
>
>
> --
> 2.43.0
>
signature.asc
Description: PGP signature
