[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH v8 10/21] vhost: Add vhost_svq_inject
From: |
Eugenio Pérez |
Subject: |
[RFC PATCH v8 10/21] vhost: Add vhost_svq_inject |
Date: |
Thu, 19 May 2022 21:12:55 +0200 |
This allows qemu to inject buffers to the device without guest's notice.
This will be use to inject net CVQ messages to restore status in the
destination.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
hw/virtio/vhost-shadow-virtqueue.h | 5 +++
hw/virtio/vhost-shadow-virtqueue.c | 72 +++++++++++++++++++++++++-----
2 files changed, 65 insertions(+), 12 deletions(-)
diff --git a/hw/virtio/vhost-shadow-virtqueue.h
b/hw/virtio/vhost-shadow-virtqueue.h
index 79cb2d301f..8fe0367944 100644
--- a/hw/virtio/vhost-shadow-virtqueue.h
+++ b/hw/virtio/vhost-shadow-virtqueue.h
@@ -23,6 +23,9 @@ typedef struct SVQElement {
/* Length of in buffer */
size_t in_len;
+
+ /* Buffer has been injected by QEMU, not by the guest */
+ bool not_from_guest;
} SVQElement;
typedef void (*VirtQueueElementCallback)(VirtIODevice *vdev,
@@ -115,6 +118,8 @@ typedef struct VhostShadowVirtqueue {
bool vhost_svq_valid_features(uint64_t features, Error **errp);
+int vhost_svq_inject(VhostShadowVirtqueue *svq, const struct iovec *iov,
+ size_t out_num, size_t in_num);
void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd);
void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd);
void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq,
diff --git a/hw/virtio/vhost-shadow-virtqueue.c
b/hw/virtio/vhost-shadow-virtqueue.c
index 5a8feb1cbc..c535c99905 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -312,6 +312,43 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq)
event_notifier_set(&svq->hdev_kick);
}
+/**
+ * Inject a chain of buffers to the device
+ *
+ * @svq: Shadow VirtQueue
+ * @iov: Descriptors buffer
+ * @out_num: Number of out elements
+ * @in_num: Number of in elements
+ */
+int vhost_svq_inject(VhostShadowVirtqueue *svq, const struct iovec *iov,
+ size_t out_num, size_t in_num)
+{
+ SVQElement *svq_elem;
+ uint16_t num_slots = (in_num ? 1 : 0) + (out_num ? 1 : 0);
+
+ /*
+ * To inject buffers in a SVQ that does not copy descriptors is not
+ * supported. All vhost_svq_inject calls are controlled by qemu so we won't
+ * hit these assertions.
+ */
+ assert(svq->copy_descs);
+ assert(num_slots > 0);
+
+ if (unlikely(svq->next_guest_avail_elem)) {
+ error_report("Injecting in a full queue");
+ return -ENOMEM;
+ }
+
+ svq_elem = virtqueue_alloc_element(sizeof(*svq_elem), out_num, in_num);
+ iov_copy(svq_elem->elem.in_sg, in_num, iov + out_num, in_num, 0, SIZE_MAX);
+ iov_copy(svq_elem->elem.out_sg, out_num, iov, out_num, 0, SIZE_MAX);
+ svq_elem->not_from_guest = true;
+ vhost_svq_add(svq, svq_elem);
+ vhost_svq_kick(svq);
+
+ return 0;
+}
+
/**
* Forward available buffers.
*
@@ -350,6 +387,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue
*svq)
break;
}
+ svq_elem->not_from_guest = false;
elem = &svq_elem->elem;
needed_slots = svq->copy_descs ? 1 : elem->out_num + elem->in_num;
if (needed_slots > vhost_svq_available_slots(svq)) {
@@ -575,19 +613,24 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
svq->ops->used_elem_handler(svq->vdev, elem);
}
- if (unlikely(i >= svq->vring.num)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "More than %u used buffers obtained in a %u size SVQ",
- i, svq->vring.num);
- virtqueue_fill(vq, elem, len, i);
- virtqueue_flush(vq, i);
- return;
+ if (!svq_elem->not_from_guest) {
+ if (unlikely(i >= svq->vring.num)) {
+ qemu_log_mask(
+ LOG_GUEST_ERROR,
+ "More than %u used buffers obtained in a %u size SVQ",
+ i, svq->vring.num);
+ virtqueue_fill(vq, elem, len, i);
+ virtqueue_flush(vq, i);
+ return;
+ }
+ virtqueue_fill(vq, elem, len, i++);
}
- virtqueue_fill(vq, elem, len, i++);
}
- virtqueue_flush(vq, i);
- event_notifier_set(&svq->svq_call);
+ if (i > 0) {
+ virtqueue_flush(vq, i);
+ event_notifier_set(&svq->svq_call);
+ }
if (check_for_avail_queue && svq->next_guest_avail_elem) {
/*
@@ -755,7 +798,10 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
if (svq->copy_descs) {
vhost_svq_unmap_elem(svq, svq_elem, 0, false);
}
- virtqueue_detach_element(svq->vq, &svq_elem->elem, 0);
+
+ if (!svq_elem->not_from_guest) {
+ virtqueue_detach_element(svq->vq, &svq_elem->elem, 0);
+ }
}
}
@@ -764,7 +810,9 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
if (svq->copy_descs) {
vhost_svq_unmap_elem(svq, next_avail_elem, 0, false);
}
- virtqueue_detach_element(svq->vq, &next_avail_elem->elem, 0);
+ if (!next_avail_elem->not_from_guest) {
+ virtqueue_detach_element(svq->vq, &next_avail_elem->elem, 0);
+ }
}
svq->vq = NULL;
g_free(svq->desc_next);
--
2.27.0
- [RFC PATCH v8 02/21] vhost: Add custom used buffer callback, (continued)
- [RFC PATCH v8 02/21] vhost: Add custom used buffer callback, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 01/21] virtio-net: Expose ctrl virtqueue logic, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 03/21] vdpa: control virtqueue support on shadow virtqueue, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 04/21] virtio: Make virtqueue_alloc_element non-static, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 05/21] vhost: Add vhost_iova_tree_find, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 06/21] vdpa: Add map/unmap operation callback to SVQ, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 07/21] vhost: move descriptor translation to vhost_svq_vring_write_descs, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 08/21] vhost: Add SVQElement, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 09/21] vhost: Add svq copy desc mode, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 11/21] vhost: Update kernel headers, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 10/21] vhost: Add vhost_svq_inject,
Eugenio Pérez <=
- [RFC PATCH v8 12/21] vdpa: delay set_vring_ready after DRIVER_OK, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 13/21] vhost: Add ShadowVirtQueueStart operation, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 14/21] vhost: Make possible to check for device exclusive vq group, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 16/21] vdpa: Add vhost_vdpa_start_control_svq, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 17/21] vdpa: Add asid attribute to vdpa device, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 18/21] vdpa: Extract get features part from vhost_vdpa_get_max_queue_pairs, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 21/21] vdpa: Add x-cvq-svq, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 15/21] vhost: add vhost_svq_poll, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 19/21] vhost: Add reference counting to vhost_iova_tree, Eugenio Pérez, 2022/05/19
- [RFC PATCH v8 20/21] vdpa: Add x-svq to NetdevVhostVDPAOptions, Eugenio Pérez, 2022/05/19