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)