@samitouri / QOSamiQemu / commits / 90369a1165

vhost: factor out the get of last used desc in SVQ

This code path is modified to handle in order devices. Abstract here so we can generalize on the caller. Signed-off-by: Eugenio Pérez <eperezma@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260304173535.2702587-5-eperezma@redhat.com>

Eugenio Pérez committed Mar 4, 2026 at 18:35 UTC 90369a1165c4ffc5a22c9e0fb1743bc0ff896861
1 file changed +29 -16
hw/virtio/vhost-shadow-virtqueue.c
+29 -16
@@ -444,6 +444,25 @@ static void vhost_svq_disable_notification(VhostShadowVirtqueue *svq)
444 }
445 }
446
447 +/*
448 + * Gets the next buffer id and moves forward the used idx, so the next time
449 + * SVQ calls this function will get the next one.
450 + *
451 + * @svq: Shadow VirtQueue
452 + * @len: Consumed length by the device.
453 + *
454 + * Return the next descriptor consumed by the device.
455 + */
456 +static uint16_t vhost_svq_get_last_used_split(VhostShadowVirtqueue *svq,
457 + uint32_t *len)
458 +{
459 + const vring_used_t *used = svq->vring.used;
460 + uint16_t last_used = svq->last_used_idx++ & (svq->vring.num - 1);
461 +
462 + *len = le32_to_cpu(used->ring[last_used].len);
463 + return le32_to_cpu(used->ring[last_used].id);
464 +}
465 +
466 static uint16_t vhost_svq_last_desc_of_chain(const VhostShadowVirtqueue *svq,
467 uint16_t num, uint16_t i)
468 {
@@ -458,8 +477,6 @@ G_GNUC_WARN_UNUSED_RESULT
477 static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
478 uint32_t *len)
479 {
461 - const vring_used_t *used = svq->vring.used;
462 - vring_used_elem_t used_elem;
480 uint16_t last_used, last_used_chain, num;
481
482 if (!vhost_svq_more_used(svq)) {
@@ -468,33 +485,29 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
485
486 /* Only get used array entries after they have been exposed by dev */
487 smp_rmb();
471 - last_used = svq->last_used_idx & (svq->vring.num - 1);
472 - used_elem.id = le32_to_cpu(used->ring[last_used].id);
473 - used_elem.len = le32_to_cpu(used->ring[last_used].len);
488 + last_used = vhost_svq_get_last_used_split(svq, len);
489
475 - svq->last_used_idx++;
476 - if (unlikely(used_elem.id >= svq->vring.num)) {
490 + if (unlikely(last_used >= svq->vring.num)) {
491 qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used",
478 - svq->vdev->name, used_elem.id);
492 + svq->vdev->name, last_used);
493 return NULL;
494 }
495
482 - if (unlikely(!svq->desc_state[used_elem.id].ndescs)) {
496 + if (unlikely(!svq->desc_state[last_used].ndescs)) {
497 qemu_log_mask(LOG_GUEST_ERROR,
498 "Device %s says index %u is used, but it was not available",
485 - svq->vdev->name, used_elem.id);
499 + svq->vdev->name, last_used);
500 return NULL;
501 }
502
489 - num = svq->desc_state[used_elem.id].ndescs;
490 - svq->desc_state[used_elem.id].ndescs = 0;
491 - last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
503 + num = svq->desc_state[last_used].ndescs;
504 + svq->desc_state[last_used].ndescs = 0;
505 + last_used_chain = vhost_svq_last_desc_of_chain(svq, num, last_used);
506 svq->desc_state[last_used_chain].next = svq->free_head;
493 - svq->free_head = used_elem.id;
507 + svq->free_head = last_used;
508 svq->num_free += num;
509
496 - *len = used_elem.len;
497 - return g_steal_pointer(&svq->desc_state[used_elem.id].elem);
510 + return g_steal_pointer(&svq->desc_state[last_used].elem);
511 }
512
513 /**