Signed-off-by: Eugenio Pérez <eperezma@xxxxxxxxxx> --- hw/virtio/vhost-sw-lm-ring.h | 4 ++++ hw/virtio/vhost-sw-lm-ring.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index 29d21feaf4..c537500d9e 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -19,6 +19,10 @@ typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; bool vhost_vring_kick(VhostShadowVirtqueue *vq); int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); + +/* Called within rcu_read_lock(). */ +void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable); + void vhost_vring_write_addr(const VhostShadowVirtqueue *vq, struct vhost_vring_addr *addr); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index aed005c2d9..c3244c550e 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -34,6 +34,9 @@ typedef struct VhostShadowVirtqueue { /* Next free descriptor */ uint16_t free_head; + /* Cache for exposed notification flag */ + bool notification; + vring_desc_t descs[]; } VhostShadowVirtqueue; @@ -60,6 +63,26 @@ bool vhost_vring_kick(VhostShadowVirtqueue *vq) : true; } +void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable) +{ + uint16_t notification_flag; + + if (vq->notification == enable) { + return; + } + + notification_flag = virtio_tswap16(vq->vdev, VRING_AVAIL_F_NO_INTERRUPT); + + vq->notification = enable; + if (enable) { + vq->vring.avail->flags &= ~notification_flag; + } else { + vq->vring.avail->flags |= notification_flag; + } + + smp_mb(); +} + static void vhost_vring_write_descs(VhostShadowVirtqueue *vq, const struct iovec *iovec, size_t num, bool more_descs, bool write) -- 2.18.4