@@ -119,8 +119,12 @@ static inline uint16_t vring_avail_flags(VirtQueue *vq)
static inline uint16_t vring_avail_idx(VirtQueue *vq)
{
target_phys_addr_t pa;
+ uint16_t idx;
pa = vq->vring.avail + offsetof(VRingAvail, idx);
- return lduw_phys(pa);
+ idx = lduw_phys(pa);
+ /* Make sure data read happens after index read */
+ rmb();
+ return idx;
}
static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
@@ -588,6 +592,8 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
+ /* Make sure used ring is updated before we check NO_INTERRUPT. */
+ mb();
/* Always notify when queue is empty (when feature acknowledge) */
if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) &&
(!(vdev->features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
Add missing memory barriers in virtio: - before checking interrupt enabled bit, make sure data has been written to memory - make sure ring index has been read before reading ring data Signed-off-by: Michael S. Tsirkin <mst@redhat.com> --- hw/virtio.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-)