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 <m...@redhat.com> --- hw/virtio.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/hw/virtio.c b/hw/virtio.c index 9f020cf..bbd7b51 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -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)) || -- 1.6.5.2.143.g8cc62