[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL v2 25/61] virtio: virtqueue_ordered_flush - VIRTIO_F_IN_ORDER supp
From: |
Michael S. Tsirkin |
Subject: |
[PULL v2 25/61] virtio: virtqueue_ordered_flush - VIRTIO_F_IN_ORDER support |
Date: |
Tue, 23 Jul 2024 06:57:21 -0400 |
From: Jonah Palmer <jonah.palmer@oracle.com>
Add VIRTIO_F_IN_ORDER feature support for the virtqueue_flush operation.
The goal of the virtqueue_ordered_flush operation when the
VIRTIO_F_IN_ORDER feature has been negotiated is to write elements to
the used/descriptor ring in-order and then update used_idx.
The function iterates through the VirtQueueElement used_elems array
in-order starting at vq->used_idx. If the element is valid (filled), the
element is written to the used/descriptor ring. This process continues
until we find an invalid (not filled) element.
For packed VQs, the first entry (at vq->used_idx) is written to the
descriptor ring last so the guest doesn't see any invalid descriptors.
If any elements were written, the used_idx is updated.
Signed-off-by: Jonah Palmer <jonah.palmer@oracle.com>
Message-Id: <20240710125522.4168043-5-jonah.palmer@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Eugenio PĂ©rez <eperezma@redhat.com>
---
hw/virtio/virtio.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0000a7b41c..397c261c3c 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1023,6 +1023,73 @@ static void virtqueue_packed_flush(VirtQueue *vq,
unsigned int count)
}
}
+static void virtqueue_ordered_flush(VirtQueue *vq)
+{
+ unsigned int i = vq->used_idx % vq->vring.num;
+ unsigned int ndescs = 0;
+ uint16_t old = vq->used_idx;
+ uint16_t new;
+ bool packed;
+ VRingUsedElem uelem;
+
+ packed = virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED);
+
+ if (packed) {
+ if (unlikely(!vq->vring.desc)) {
+ return;
+ }
+ } else if (unlikely(!vq->vring.used)) {
+ return;
+ }
+
+ /* First expected in-order element isn't ready, nothing to do */
+ if (!vq->used_elems[i].in_order_filled) {
+ return;
+ }
+
+ /* Search for filled elements in-order */
+ while (vq->used_elems[i].in_order_filled) {
+ /*
+ * First entry for packed VQs is written last so the guest
+ * doesn't see invalid descriptors.
+ */
+ if (packed && i != vq->used_idx) {
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[i], ndescs, false);
+ } else if (!packed) {
+ uelem.id = vq->used_elems[i].index;
+ uelem.len = vq->used_elems[i].len;
+ vring_used_write(vq, &uelem, i);
+ }
+
+ vq->used_elems[i].in_order_filled = false;
+ ndescs += vq->used_elems[i].ndescs;
+ i += vq->used_elems[i].ndescs;
+ if (i >= vq->vring.num) {
+ i -= vq->vring.num;
+ }
+ }
+
+ if (packed) {
+ virtqueue_packed_fill_desc(vq, &vq->used_elems[vq->used_idx], 0, true);
+ vq->used_idx += ndescs;
+ if (vq->used_idx >= vq->vring.num) {
+ vq->used_idx -= vq->vring.num;
+ vq->used_wrap_counter ^= 1;
+ vq->signalled_used_valid = false;
+ }
+ } else {
+ /* Make sure buffer is written before we update index. */
+ smp_wmb();
+ new = old + ndescs;
+ vring_used_idx_set(vq, new);
+ if (unlikely((int16_t)(new - vq->signalled_used) <
+ (uint16_t)(new - old))) {
+ vq->signalled_used_valid = false;
+ }
+ }
+ vq->inuse -= ndescs;
+}
+
void virtqueue_flush(VirtQueue *vq, unsigned int count)
{
if (virtio_device_disabled(vq->vdev)) {
@@ -1030,7 +1097,9 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count)
return;
}
- if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
+ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_IN_ORDER)) {
+ virtqueue_ordered_flush(vq);
+ } else if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
virtqueue_packed_flush(vq, count);
} else {
virtqueue_split_flush(vq, count);
--
MST
- [PULL v2 15/61] MAINTAINERS: Add myself as a VT-d reviewer, (continued)
- [PULL v2 15/61] MAINTAINERS: Add myself as a VT-d reviewer, Michael S. Tsirkin, 2024/07/23
- [PULL v2 16/61] virtio-snd: add max size bounds check in input cb, Michael S. Tsirkin, 2024/07/23
- [PULL v2 17/61] virtio-snd: check for invalid param shift operands, Michael S. Tsirkin, 2024/07/23
- [PULL v2 18/61] intel_iommu: fix FRCD construction macro, Michael S. Tsirkin, 2024/07/23
- [PULL v2 19/61] intel_iommu: move VTD_FRCD_PV and VTD_FRCD_PP declarations, Michael S. Tsirkin, 2024/07/23
- [PULL v2 20/61] intel_iommu: fix type of the mask field in VTDIOTLBPageInvInfo, Michael S. Tsirkin, 2024/07/23
- [PULL v2 23/61] virtio: virtqueue_pop - VIRTIO_F_IN_ORDER support, Michael S. Tsirkin, 2024/07/23
- [PULL v2 21/61] intel_iommu: make type match, Michael S. Tsirkin, 2024/07/23
- [PULL v2 22/61] virtio: Add bool to VirtQueueElement, Michael S. Tsirkin, 2024/07/23
- [PULL v2 24/61] virtio: virtqueue_ordered_fill - VIRTIO_F_IN_ORDER support, Michael S. Tsirkin, 2024/07/23
- [PULL v2 25/61] virtio: virtqueue_ordered_flush - VIRTIO_F_IN_ORDER support,
Michael S. Tsirkin <=
- [PULL v2 26/61] vhost,vhost-user: Add VIRTIO_F_IN_ORDER to vhost feature bits, Michael S. Tsirkin, 2024/07/23
- [PULL v2 27/61] virtio: Add VIRTIO_F_IN_ORDER property definition, Michael S. Tsirkin, 2024/07/23
- [PULL v2 28/61] contrib/vhost-user-blk: fix overflowing expression, Michael S. Tsirkin, 2024/07/23
- [PULL v2 29/61] hw/pci: Fix SR-IOV VF number calculation, Michael S. Tsirkin, 2024/07/23
- [PULL v2 30/61] pcie_sriov: Ensure PF and VF are mutually exclusive, Michael S. Tsirkin, 2024/07/23
- [PULL v2 31/61] pcie_sriov: Check PCI Express for SR-IOV PF, Michael S. Tsirkin, 2024/07/23
- [PULL v2 33/61] virtio-pci: Implement SR-IOV PF, Michael S. Tsirkin, 2024/07/23
- [PULL v2 32/61] pcie_sriov: Allow user to create SR-IOV device, Michael S. Tsirkin, 2024/07/23
- [PULL v2 34/61] virtio-net: Implement SR-IOV VF, Michael S. Tsirkin, 2024/07/23