untrusted comment: signature from openbsd 5.5 base secret key RWRGy8gxk9N93xob/rIni4484cw6hOLhQpR5MP30JzQo6ETZ6S1po5tqNYDOLThyCBGwWQxEPKEG8fQdkD9JfD7KHwbDq8J7uQk= OpenBSD 5.5 errata 18, Dec 10, 2014: Several bugs in virtio(4) can lead to hangs with virtio devices, like vio(4) and vioblk(4). Apply patch using: signify -Vep /etc/signify/openbsd-55-base.pub -x 018_virtio.patch.sig -m - | \ (cd /usr/src && patch -p0) Then build and install a new kernel: cd /usr/src/sys/arch/`machine`/conf KK=`sysctl -n kern.osversion | cut -d# -f1` config $KK cd ../compile/$KK make make install Index: sys/dev/pci/virtio.c =================================================================== RCS file: /cvs/src/sys/dev/pci/virtio.c,v retrieving revision 1.5 retrieving revision 1.5.6.2 diff -u -p -r1.5 -r1.5.6.2 --- sys/dev/pci/virtio.c 10 Mar 2013 21:58:02 -0000 1.5 +++ sys/dev/pci/virtio.c 9 Dec 2014 13:03:54 -0000 1.5.6.2 @@ -277,7 +277,6 @@ virtio_init_vq(struct virtio_softc *sc, /* enqueue/dequeue status */ vq->vq_avail_idx = 0; - vq->vq_avail_signalled = 0xffff; vq->vq_used_idx = 0; vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq_sync_uring(sc, vq, BUS_DMASYNC_PREREAD); @@ -658,6 +657,8 @@ publish_avail_idx(struct virtio_softc *s { 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; @@ -684,17 +685,19 @@ virtio_enqueue_commit(struct virtio_soft notify: if (notifynow) { if (vq->vq_owner->sc_features & VIRTIO_F_RING_EVENT_IDX) { - uint16_t o = vq->vq_avail_signalled; + uint16_t o = vq->vq_avail->idx; uint16_t n = vq->vq_avail_idx; - uint16_t t = VQ_AVAIL_EVENT(vq) + 1; + uint16_t t; publish_avail_idx(sc, vq); - if ((o < n && o < t && t <= n) - || (o > n && (o < t || t <= n))) { + + 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); - vq->vq_avail_signalled = n; - } } 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); } @@ -747,6 +750,8 @@ virtio_dequeue(struct virtio_softc *sc, 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]; @@ -797,6 +802,7 @@ virtio_postpone_intr(struct virtqueue *v /* 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++; @@ -870,6 +876,8 @@ virtio_start_vq_intr(struct virtio_softc VQ_USED_EVENT(vq) = vq->vq_used_idx; else vq->vq_avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + + virtio_membar_sync(); vq_sync_aring(sc, vq, BUS_DMASYNC_PREWRITE); vq->vq_queued++; Index: sys/arch/i386/include/atomic.h =================================================================== RCS file: /cvs/src/sys/arch/i386/include/atomic.h,v retrieving revision 1.11 retrieving revision 1.11.8.1 diff -u -p -r1.11 -r1.11.8.1 --- sys/arch/i386/include/atomic.h 19 Nov 2012 15:18:06 -0000 1.11 +++ sys/arch/i386/include/atomic.h 9 Dec 2014 13:03:17 -0000 1.11.8.1 @@ -49,6 +49,13 @@ #else #define LOCK #endif + +#define __membar(_f) do { __asm __volatile(_f ::: "memory"); } while (0) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("lock; addl $0,0(%%esp)") static __inline u_int64_t i386_atomic_testset_uq(volatile u_int64_t *ptr, u_int64_t val) Index: sys/arch/amd64/include/atomic.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/atomic.h,v retrieving revision 1.10 retrieving revision 1.10.4.1 diff -u -p -r1.10 -r1.10.4.1 --- sys/arch/amd64/include/atomic.h 17 Feb 2014 10:01:32 -0000 1.10 +++ sys/arch/amd64/include/atomic.h 9 Dec 2014 13:03:17 -0000 1.10.4.1 @@ -54,6 +54,13 @@ #else #define LOCK #endif + +#define __membar(_f) do { __asm __volatile(_f ::: "memory"); } while (0) + +/* virtio needs MP membars even on SP kernels */ +#define virtio_membar_producer() __membar("") +#define virtio_membar_consumer() __membar("") +#define virtio_membar_sync() __membar("mfence") static __inline u_int64_t x86_atomic_testset_u64(volatile u_int64_t *ptr, u_int64_t val)