Skip to content

Commit df9ace7

Browse files
Gavin Shanmstsirkin
authored andcommitted
vhost: Add smp_rmb() in vhost_enable_notify()
A smp_rmb() has been missed in vhost_enable_notify(), inspired by Will. Otherwise, it's not ensured the available ring entries pushed by guest can be observed by vhost in time, leading to stale available ring entries fetched by vhost in vhost_get_vq_desc(), as reported by Yihuang Yu on NVidia's grace-hopper (ARM64) platform. /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \ -accel kvm -machine virt,gic-version=host -cpu host \ -smp maxcpus=1,cpus=1,sockets=1,clusters=1,cores=1,threads=1 \ -m 4096M,slots=16,maxmem=64G \ -object memory-backend-ram,id=mem0,size=4096M \ : \ -netdev tap,id=vnet0,vhost=true \ -device virtio-net-pci,bus=pcie.8,netdev=vnet0,mac=52:54:00:f1:26:b0 : guest# netperf -H 10.26.1.81 -l 60 -C -c -t UDP_STREAM virtio_net virtio0: output.0:id 100 is not a head! Add the missed smp_rmb() in vhost_enable_notify(). When it returns true, it means there's still pending tx buffers. Since it might read indices, so it still can bypass the smp_rmb() in vhost_get_vq_desc(). Note that it should be safe until vq->avail_idx is changed by commit d3bb267 ("vhost: cache avail index in vhost_enable_notify()"). Fixes: d3bb267 ("vhost: cache avail index in vhost_enable_notify()") Cc: <[email protected]> # v5.18+ Reported-by: Yihuang Yu <[email protected]> Suggested-by: Will Deacon <[email protected]> Signed-off-by: Gavin Shan <[email protected]> Acked-by: Jason Wang <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Reviewed-by: Stefano Garzarella <[email protected]>
1 parent 22e1992 commit df9ace7

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

drivers/vhost/vhost.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2848,9 +2848,19 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
28482848
&vq->avail->idx, r);
28492849
return false;
28502850
}
2851+
28512852
vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
2853+
if (vq->avail_idx != vq->last_avail_idx) {
2854+
/* Since we have updated avail_idx, the following
2855+
* call to vhost_get_vq_desc() will read available
2856+
* ring entries. Make sure that read happens after
2857+
* the avail_idx read.
2858+
*/
2859+
smp_rmb();
2860+
return true;
2861+
}
28522862

2853-
return vq->avail_idx != vq->last_avail_idx;
2863+
return false;
28542864
}
28552865
EXPORT_SYMBOL_GPL(vhost_enable_notify);
28562866

0 commit comments

Comments
 (0)