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
This commit is contained in:
parent
1935b8f92e
commit
efc25f65e2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=347960
@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2013 Chris Torek <torek @ torek net>
|
* Copyright (c) 2013 Chris Torek <torek @ torek net>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2019 Joyent, Inc.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -32,6 +33,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <machine/atomic.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -422,6 +425,12 @@ vq_relchain(struct vqueue_info *vq, uint16_t idx, uint32_t iolen)
|
|||||||
vue = &vuh->vu_ring[uidx++ & mask];
|
vue = &vuh->vu_ring[uidx++ & mask];
|
||||||
vue->vu_idx = idx;
|
vue->vu_idx = idx;
|
||||||
vue->vu_tlen = iolen;
|
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;
|
vuh->vu_idx = uidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,6 +468,13 @@ vq_endchains(struct vqueue_info *vq, int used_all_avail)
|
|||||||
vs = vq->vq_vs;
|
vs = vq->vq_vs;
|
||||||
old_idx = vq->vq_save_used;
|
old_idx = vq->vq_save_used;
|
||||||
vq->vq_save_used = new_idx = vq->vq_used->vu_idx;
|
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 &&
|
if (used_all_avail &&
|
||||||
(vs->vs_negotiated_caps & VIRTIO_F_NOTIFY_ON_EMPTY))
|
(vs->vs_negotiated_caps & VIRTIO_F_NOTIFY_ON_EMPTY))
|
||||||
intr = 1;
|
intr = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user