Signed-off-by: Eugenio Pérez <[email protected]>
---
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