aboutsummaryrefslogtreecommitdiff
path: root/hw/cxl
diff options
context:
space:
mode:
authorHawkins Jiawei <yin31149@gmail.com>2023-05-09 16:48:17 +0800
committerMichael S. Tsirkin <mst@redhat.com>2023-05-19 01:36:09 -0400
commit5d410557dea452f6231a7c66155e29a37e168528 (patch)
treeecfbc4fb797af061c21b50c594e5f0a065c3d7df /hw/cxl
parent297e8182194e634baa0cbbfd96d2e09e2a0bcd40 (diff)
downloadqemu-5d410557dea452f6231a7c66155e29a37e168528.zip
qemu-5d410557dea452f6231a7c66155e29a37e168528.tar.gz
qemu-5d410557dea452f6231a7c66155e29a37e168528.tar.bz2
vhost: fix possible wrap in SVQ descriptor ring
QEMU invokes vhost_svq_add() when adding a guest's element into SVQ. In vhost_svq_add(), it uses vhost_svq_available_slots() to check whether QEMU can add the element into SVQ. If there is enough space, then QEMU combines some out descriptors and some in descriptors into one descriptor chain, and adds it into `svq->vring.desc` by vhost_svq_vring_write_descs(). Yet the problem is that, `svq->shadow_avail_idx - svq->shadow_used_idx` in vhost_svq_available_slots() returns the number of occupied elements, or the number of descriptor chains, instead of the number of occupied descriptors, which may cause wrapping in SVQ descriptor ring. Here is an example. In vhost_handle_guest_kick(), QEMU forwards as many available buffers to device by virtqueue_pop() and vhost_svq_add_element(). virtqueue_pop() returns a guest's element, and then this element is added into SVQ by vhost_svq_add_element(), a wrapper to vhost_svq_add(). If QEMU invokes virtqueue_pop() and vhost_svq_add_element() `svq->vring.num` times, vhost_svq_available_slots() thinks QEMU just ran out of slots and everything should work fine. But in fact, virtqueue_pop() returns `svq->vring.num` elements or descriptor chains, more than `svq->vring.num` descriptors due to guest memory fragmentation, and this causes wrapping in SVQ descriptor ring. This bug is valid even before marking the descriptors used. If the guest memory is fragmented, SVQ must add chains so it can try to add more descriptors than possible. This patch solves it by adding `num_free` field in VhostShadowVirtqueue structure and updating this field in vhost_svq_add() and vhost_svq_get_buf(), to record the number of free descriptors. Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding") Signed-off-by: Hawkins Jiawei <yin31149@gmail.com> Acked-by: Eugenio PĂ©rez <eperezma@redhat.com> Message-Id: <20230509084817.3973-1-yin31149@gmail.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Lei Yang <leiyang@redhat.com>
Diffstat (limited to 'hw/cxl')
0 files changed, 0 insertions, 0 deletions