untrusted comment: signature from openbsd 5.6 base private key
RWR0EANmo9nqhm+ggK98I1rvCSdAAAuoh2w1cAW9PShdW52IqAaM+ogTfSbujjQHeJknhwld7EWu105QrmO3qtPlpSZCEpik9g4=

OpenBSD 5.6 errata 13, Dec 10, 2014:

Missing memory barriers in virtio(4) can lead to hangs with virtio devices,
like vio(4) and vioblk(4).

Apply patch using:

   signify -Vep /etc/signify/openbsd-56-base.pub -x 013_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.9
retrieving revision 1.9.4.1
diff -u -p -r1.9 -r1.9.4.1
--- sys/dev/pci/virtio.c        13 Jul 2014 23:10:23 -0000      1.9
+++ sys/dev/pci/virtio.c        9 Dec 2014 12:54:26 -0000       1.9.4.1
@@ -657,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;
@@ -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,
               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 *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++;
@@ -867,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.12
retrieving revision 1.12.4.1
diff -u -p -r1.12 -r1.12.4.1
--- sys/arch/i386/include/atomic.h      29 Mar 2014 18:09:29 -0000      1.12
+++ sys/arch/i386/include/atomic.h      9 Dec 2014 12:53:03 -0000       1.12.4.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.13
retrieving revision 1.13.4.1
diff -u -p -r1.13 -r1.13.4.1
--- sys/arch/amd64/include/atomic.h     18 Jul 2014 10:40:14 -0000      1.13
+++ sys/arch/amd64/include/atomic.h     9 Dec 2014 12:53:03 -0000       1.13.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 unsigned int
_atomic_cas_uint(volatile unsigned int *p, unsigned int e, unsigned int n)