[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v2 3/5] virtio: In-order support for packed VQs
From: |
Jonah Palmer |
Subject: |
[RFC v2 3/5] virtio: In-order support for packed VQs |
Date: |
Thu, 28 Mar 2024 12:22:01 -0400 |
Implements VIRTIO_F_IN_ORDER feature support for virtio devices using
the packed virtqueue layout.
For a virtio device that has negotiated the VIRTIO_F_IN_ORDER feature
whose virtqueues use a packed virtqueue layout, it's essential that used
VirtQueueElements are written to the descriptor ring in-order.
In the packed virtqueue case, since we already write to the virtqueue's
used_elems array at the start of virtqueue_fill, we don't need to call
virtqueue_packed_fill. Furthermore, due to change in behavior of the
used_elems array and not knowing how many unused in-order elements
exist, separate logic is required for the flushing operation of packed
virtqueues.
Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
---
hw/virtio/virtio.c | 50 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 43 insertions(+), 7 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 19d3d43816..dc2eabd18b 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -960,7 +960,8 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement
*elem,
vq->used_elems[seq_idx].out_num = elem->out_num;
}
- if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
+ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED) &&
+ !virtio_vdev_has_feature(vq->vdev, VIRTIO_F_IN_ORDER)) {
virtqueue_packed_fill(vq, elem, len, idx);
} else {
virtqueue_split_fill(vq, elem, len, idx);
@@ -997,18 +998,53 @@ static void virtqueue_split_flush(VirtQueue *vq, unsigned
int count)
static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count)
{
- unsigned int i, ndescs = 0;
+ unsigned int i, j, uelem_idx, ndescs = 0;
if (unlikely(!vq->vring.desc)) {
return;
}
- for (i = 1; i < count; i++) {
- virtqueue_packed_fill_desc(vq, &vq->used_elems[i], i, false);
- ndescs += vq->used_elems[i].ndescs;
+ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_IN_ORDER)) {
+ /* First expected element is used, nothing to do */
+ if (vq->used_elems[vq->used_idx].in_num +
+ vq->used_elems[vq->used_idx].out_num <= 0) {
+ return;
+ }
+
+ j = vq->used_idx;
+
+ for (i = j + 1; ; i++) {
+ uelem_idx = i % vq->vring.num;
+
+ /* Stop if element has been used */
+ if (vq->used_elems[uelem_idx].in_num +
+ vq->used_elems[uelem_idx].out_num <= 0) {
+ break;
+ }
+
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[uelem_idx],
+ uelem_idx, false);
+ ndescs += vq->used_elems[uelem_idx].ndescs;
+
+ /* Mark this element as used */
+ vq->used_elems[uelem_idx].in_num = 0;
+ vq->used_elems[uelem_idx].out_num = 0;
+ }
+
+ /* Mark first expected element as used */
+ vq->used_elems[vq->used_idx].in_num = 0;
+ vq->used_elems[vq->used_idx].out_num = 0;
+ } else {
+ j = 0;
+
+ for (i = 1; i < count; i++) {
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[i], i, false);
+ ndescs += vq->used_elems[i].ndescs;
+ }
}
- virtqueue_packed_fill_desc(vq, &vq->used_elems[0], 0, true);
- ndescs += vq->used_elems[0].ndescs;
+
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[j], j, true);
+ ndescs += vq->used_elems[j].ndescs;
vq->inuse -= ndescs;
vq->used_idx += ndescs;
--
2.39.3
- [RFC v2 0/5] virtio,vhost: Add VIRTIO_F_IN_ORDER support, Jonah Palmer, 2024/03/28
- [RFC v2 5/5] virtio: Add VIRTIO_F_IN_ORDER property definition, Jonah Palmer, 2024/03/28
- [RFC v2 3/5] virtio: In-order support for packed VQs,
Jonah Palmer <=
- [RFC v2 2/5] virtio: In-order support for split VQs, Jonah Palmer, 2024/03/28
- [RFC v2 4/5] vhost, vhost-user: Add VIRTIO_F_IN_ORDER to vhost feature bits, Jonah Palmer, 2024/03/28
- [RFC v2 1/5] virtio: Initialize sequence variables, Jonah Palmer, 2024/03/28