Date: Sat, 18 May 2019 19:32:39 +0000 (UTC) From: "Rodney W. Grimes" <rgrimes@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r347960 - head/usr.sbin/bhyve Message-ID: <201905181932.x4IJWdMA000871@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905181932.x4IJWdMA000871>