diff options
author | 2014-10-08 19:59:53 +0000 | |
---|---|---|
committer | 2014-10-08 19:59:53 +0000 | |
commit | 602da0fb86a6a23af63853970454337758eed172 (patch) | |
tree | 0812d89154c8f0f8a55abbfde9419d11307a84d1 | |
parent | Add virtio_membar_* macros (diff) | |
download | wireguard-openbsd-602da0fb86a6a23af63853970454337758eed172.tar.xz wireguard-openbsd-602da0fb86a6a23af63853970454337758eed172.zip |
Add missing memory barriers to virtio.
The virtio_membar_sync() calls are required even on x86. The *_producer()
and *_consumer() calls are only relevant on architectures with less strict
memory ordering.
-rw-r--r-- | sys/dev/pci/virtio.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/dev/pci/virtio.c b/sys/dev/pci/virtio.c index 553a6a7ee66..b6c74cf251f 100644 --- a/sys/dev/pci/virtio.c +++ b/sys/dev/pci/virtio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtio.c,v 1.9 2014/07/13 23:10:23 deraadt Exp $ */ +/* $OpenBSD: virtio.c,v 1.10 2014/10/08 19:59:53 sf Exp $ */ /* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */ /* @@ -657,6 +657,8 @@ publish_avail_idx(struct virtio_softc *sc, struct virtqueue *vq) { vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); + + virtio_membar_producer(); vq->vq_avail->idx = vq->vq_avail_idx; vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE); vq->vq_queued = 1; @@ -687,11 +689,15 @@ notify: uint16_t n = vq->vq_avail_idx; uint16_t t; publish_avail_idx(sc, vq); + + virtio_membar_sync(); t = VQ_AVAIL_EVENT(vq) + 1; if ((uint16_t)(n - t) < (uint16_t)(n - o)) sc->sc_ops->kick(sc, vq->vq_index); } else { publish_avail_idx(sc, vq); + + virtio_membar_sync(); if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY)) sc->sc_ops->kick(sc, vq->vq_index); } @@ -744,6 +750,8 @@ virtio_dequeue(struct virtio_softc *sc, struct virtqueue *vq, return ENOENT; usedidx = vq->vq_used_idx++; usedidx &= vq->vq_mask; + + virtio_membar_consumer(); slot = vq->vq_used->ring[usedidx].id; qe = &vq->vq_entries[slot]; @@ -794,6 +802,7 @@ virtio_postpone_intr(struct virtqueue *vq, uint16_t nslots) /* set the new event index: avail_ring->used_event = idx */ VQ_USED_EVENT(vq) = idx; + virtio_membar_sync(); vq_sync_aring(vq->vq_owner, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; @@ -868,6 +877,8 @@ virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) else vq->vq_avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + virtio_membar_sync(); + vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; |