summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsf <sf@openbsd.org>2014-10-08 19:59:53 +0000
committersf <sf@openbsd.org>2014-10-08 19:59:53 +0000
commit602da0fb86a6a23af63853970454337758eed172 (patch)
tree0812d89154c8f0f8a55abbfde9419d11307a84d1
parentAdd virtio_membar_* macros (diff)
downloadwireguard-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.c13
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++;