aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
authorEugenio Pérez <eperezma@redhat.com>2022-05-12 19:57:43 +0200
committerMichael S. Tsirkin <mst@redhat.com>2022-05-13 07:57:26 -0400
commit81abfa5724c9a6502d7a1d3a67c55f2a303a1170 (patch)
tree7ca89f5f6b71dc4ff2a5f9326796d1a682e21c67 /hw/virtio
parent495fe3a78749c39c0e772c4e1a55d6cb8a7e5292 (diff)
downloadqemu-81abfa5724c9a6502d7a1d3a67c55f2a303a1170.zip
qemu-81abfa5724c9a6502d7a1d3a67c55f2a303a1170.tar.gz
qemu-81abfa5724c9a6502d7a1d3a67c55f2a303a1170.tar.bz2
vhost: Fix device's used descriptor dequeue
Only the first one of them were properly enqueued back. Fixes: 100890f7ca ("vhost: Shadow virtqueue buffers forwarding") Signed-off-by: Eugenio Pérez <eperezma@redhat.com> Message-Id: <20220512175747.142058-3-eperezma@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/vhost-shadow-virtqueue.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 1d6552b..a8376ef 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -334,12 +334,22 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
svq->vring.avail->flags |= cpu_to_le16(VRING_AVAIL_F_NO_INTERRUPT);
}
+static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
+ uint16_t num, uint16_t i)
+{
+ for (uint16_t j = 0; j < (num - 1); ++j) {
+ i = le16_to_cpu(svq->desc_next[i]);
+ }
+
+ return i;
+}
+
static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
uint32_t *len)
{
const vring_used_t *used = svq->vring.used;
vring_used_elem_t used_elem;
- uint16_t last_used;
+ uint16_t last_used, last_used_chain, num;
if (!vhost_svq_more_used(svq)) {
return NULL;
@@ -365,7 +375,10 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
return NULL;
}
- svq->desc_next[used_elem.id] = svq->free_head;
+ num = svq->ring_id_maps[used_elem.id]->in_num +
+ svq->ring_id_maps[used_elem.id]->out_num;
+ last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
+ svq->desc_next[last_used_chain] = svq->free_head;
svq->free_head = used_elem.id;
*len = used_elem.len;