Re: [PATCH RFC 13/15] hw/virtio/vhost-user: add shadow virtqueues and eventfd intercepts

Stefan Hajnoczi <[email protected]> Tue, 28 Jul 2026 15:41:46 -0400
Newsgroups dev.linux.lists.virtio-fs,org.nongnu.qemu-devel
Message-ID <20260728194145.GK371693@fedora>
--B6GEy+uFbHjCCumJ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

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.
>=20
> Signed-off-by: Connor Kite <[email protected]>
> ---
>  hw/virtio/vhost-user.c | 54 ++++++++++++++++++++++++++++++++++++++++++++=
++++++
>  1 file changed, 54 insertions(+)
>=20
> 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 {
> =20
>      /* Isolated memory data*/
>      struct IsolationRegion iso_memory;
> +    GPtrArray *shadow_vqs;
>      VhostIOVATree *iso_iova_tree;
> +    bool svqs_allocated;
>  };
> =20
>  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 =3D dev->opaque;
> +    int svq_idx =3D file->index - dev->vq_index;
> +    if (u->user->memory_isolation) {
> +        VhostShadowVirtqueue *svq =3D g_ptr_array_index(u->shadow_vqs,
> +                                                      svq_idx);
> +        vhost_svq_set_svq_kick_fd(svq, file->fd);
> +
> +        if (svq->hdev_kick.initialized =3D=3D false) {
> +            int r =3D 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 =3D 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 =3D vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, fil=
e);
>      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 =3D dev->opaque;
> +    int svq_idx =3D file->index - dev->vq_index;
> +    if (u->user->memory_isolation) {
> +        VhostShadowVirtqueue *svq =3D g_ptr_array_index(u->shadow_vqs,
> +                                                      svq_idx);
> +        vhost_svq_set_svq_call_fd(svq, file->fd);
> +
> +        if (svq->hdev_call.initialized =3D=3D false) {
> +            int r =3D 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 =3D event_notifier_get_fd(&svq->hdev_call);

Same as above.

> +    }
> +
>      return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
>  }
> =20
> @@ -2715,6 +2754,17 @@ static int vhost_user_postcopy_notifier(NotifierWi=
thReturn *notifier,
>      return 0;
>  }
> =20
> +static void vhost_user_init_svq(struct vhost_dev *dev, struct vhost_user=
 *u)
> +{
> +    /*Modified from vhost-vdpa*/
> +    u->shadow_vqs =3D g_ptr_array_new_full(dev->nvqs, vhost_svq_free);
> +    for (int i =3D 0; i < dev->nvqs; i++) {
> +        VhostShadowVirtqueue *svq;
> +        svq =3D 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_de=
v *dev, void *opaque,
>      u->postcopy_notifier.notify =3D vhost_user_postcopy_notifier;
>      postcopy_add_notifier(&u->postcopy_notifier);
> =20
> +    if (vus->memory_isolation) {
> +        vhost_user_init_svq(dev, u);
> +    }
> +
>      return 0;
>  }
> =20
>=20
> --=20
> 2.43.0
>=20

--B6GEy+uFbHjCCumJ
Content-Type: application/pgp-signature; name=signature.asc

-----BEGIN PGP SIGNATURE-----

iQEzBAEBCgAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAmppBfkACgkQnKSrs4Gr
c8incggAjXD8O74CX7ZbPEI9yeqAUza43JWOz78Ypa4LvWMaqWm0MK2nSmjunVjC
99wXDVM2Dz2DVphziIy7C6D/zyJBopg1K/N08Z1ZKB43TY3BtteU0tfEgJuAOooA
TKK5UJynp/mLbMG8IWEVB1Sg9bogNL8cckPMzVVzkQwCD+33CPBfwHChwmR4zuai
XNUeTUnU3D4mQycDXAlsWG+MwGQRh1GPd6i0Q8bIXM7Uv1w8qSSeZ4skNGEvH0SZ
Xq7Y0sXONrDVkRGyvKkHOb7claFGvm4KoCUTt8rVwe1BSM9+JMC+apsDBiLvTxlX
qAJCi8AzjycweYFAENIpHtQrM5h0uw==
=gN7E
-----END PGP SIGNATURE-----

--B6GEy+uFbHjCCumJ--