svn commit: r347960 - head/usr.sbin/bhyve
Rodney W. Grimes
rgrimes at FreeBSD.org
Sat May 18 19:32:40 UTC 2019
Author: rgrimes
Date: Sat May 18 19:32:38 2019
New Revision: 347960
URL: https://svnweb.freebsd.org/changeset/base/347960
Log:
bhyve virtio needs barriers
Under certain tight race conditions, we found that the lack of a memory
barrier in bhyve's virtio handling causes it to miss a NO_NOTIFY state
transition on block devices, resulting in guest stall. The investigation
is recorded in OS-7613. As part of the examination into bhyve's use of
barriers, one other section was found to be problematic, but only on
non-x86 ISAs with less strict memory ordering. That was addressed in
this patch as well, although it was not at all a problem on x86.
PR: 231117
Submitted by: Patrick Mooney <patrick.mooney at joyent.com>
Reviewed by: jhb, kib, rgrimes
Approved by: jhb
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D19501
Modified:
head/usr.sbin/bhyve/virtio.c
Modified: head/usr.sbin/bhyve/virtio.c
==============================================================================
--- head/usr.sbin/bhyve/virtio.c Sat May 18 17:30:03 2019 (r347959)
+++ head/usr.sbin/bhyve/virtio.c Sat May 18 19:32:38 2019 (r347960)
@@ -3,6 +3,7 @@
*
* Copyright (c) 2013 Chris Torek <torek @ torek net>
* All rights reserved.
+ * Copyright (c) 2019 Joyent, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +33,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/uio.h>
+#include <machine/atomic.h>
+
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
@@ -422,6 +425,12 @@ vq_relchain(struct vqueue_info *vq, uint16_t idx, uint
vue = &vuh->vu_ring[uidx++ & mask];
vue->vu_idx = idx;
vue->vu_tlen = iolen;
+
+ /*
+ * Ensure the used descriptor is visible before updating the index.
+ * This is necessary on ISAs with memory ordering less strict than x86.
+ */
+ atomic_thread_fence_rel();
vuh->vu_idx = uidx;
}
@@ -459,6 +468,13 @@ vq_endchains(struct vqueue_info *vq, int used_all_avai
vs = vq->vq_vs;
old_idx = vq->vq_save_used;
vq->vq_save_used = new_idx = vq->vq_used->vu_idx;
+
+ /*
+ * Use full memory barrier between vu_idx store from preceding
+ * vq_relchain() call and the loads from VQ_USED_EVENT_IDX() or
+ * va_flags below.
+ */
+ atomic_thread_fence_seq_cst();
if (used_all_avail &&
(vs->vs_negotiated_caps & VIRTIO_F_NOTIFY_ON_EMPTY))
intr = 1;
More information about the svn-src-all
mailing list