Skip to content

Commit 6f482b8

Browse files
conghuic23wenlingz
authored andcommitted
dm: virtio: add memory barrier before notify FE
Without memory barrier, the change of used ring index could not immediately detected by FE, this would bring some problems. For virtio-blk FE driver, when it receives an interrupt, and confirms the used ring index has changed, it will first set ring flags with VRING_AVAIL_F_NO_INTERRUPT, then get buffer from virtqueue, after process this request, it will mask VRING_AVAIL_F_NO_INTERRUPT, and get used ring index again before return. If used ring changes, it will process it. At the same time, BE will read this flags before each notify, if VRING_AVAIL_F_NO_INTERRUPT was set, BE will not inject interrupt. Without memory barrier, before FE mask VRING_AVAIL_F_NO_INTERRUPT, BE has finished notify without interrupt, then FE mask VRING_AVAIL_F_NO_INTERRUPT, and get used ring index but failed (index has changed from BE side). FE will return from interrupt handler function, and wait for next interrupt which was not injected by BE. Thus, this will cause kernel hung. Tracked-On: #2732 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Wang Yu <yu1.wang@intel.com>
1 parent 7ab6e7e commit 6f482b8

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

devicemodel/hw/pci/virtio/virtio.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "pci_core.h"
3636
#include "virtio.h"
3737
#include "timer.h"
38+
#include <atomic.h>
3839

3940
/*
4041
* Functions for dealing with generalized "virtual devices" as
@@ -611,6 +612,9 @@ vq_endchains(struct virtio_vq_info *vq, int used_all_avail)
611612
* In any case, though, if NOTIFY_ON_EMPTY is set and the
612613
* entire avail was processed, we need to interrupt always.
613614
*/
615+
616+
atomic_thread_fence();
617+
614618
base = vq->base;
615619
old_idx = vq->save_used;
616620
vq->save_used = new_idx = vq->used->idx;

0 commit comments

Comments
 (0)