Signed-off-by: Eugenio Pérez <eperezma@xxxxxxxxxx> --- hw/virtio/vhost-sw-lm-ring.h | 2 ++ hw/virtio/vhost-sw-lm-ring.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index c537500d9e..03257d60c1 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -22,6 +22,8 @@ int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); /* Called within rcu_read_lock(). */ void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable); +/* Called within rcu_read_lock(). */ +bool vhost_vring_poll_rcu(VhostShadowVirtqueue *vq); 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 c3244c550e..3652889d8e 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -34,6 +34,12 @@ typedef struct VhostShadowVirtqueue { /* Next free descriptor */ uint16_t free_head; + /* Last seen used idx */ + uint16_t shadow_used_idx; + + /* Next head to consume from device */ + uint16_t used_idx; + /* Cache for exposed notification flag */ bool notification; @@ -83,6 +89,18 @@ void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable) smp_mb(); } +bool vhost_vring_poll_rcu(VhostShadowVirtqueue *vq) +{ + if (vq->used_idx != vq->shadow_used_idx) { + return true; + } + + smp_rmb(); + vq->shadow_used_idx = virtio_tswap16(vq->vdev, vq->vring.used->idx); + + return vq->used_idx != vq->shadow_used_idx; +} + static void vhost_vring_write_descs(VhostShadowVirtqueue *vq, const struct iovec *iovec, size_t num, bool more_descs, bool write) -- 2.18.4