@@ -16,6 +16,13 @@
typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
+typedef void (*VirtQueueElementCallback)(VirtIODevice *vdev,
+ const VirtQueueElement *elem);
+
+typedef struct VhostShadowVirtqueueOps {
+ VirtQueueElementCallback used_elem_handler;
+} VhostShadowVirtqueueOps;
+
bool vhost_svq_valid_device_features(uint64_t *features);
bool vhost_svq_valid_guest_features(uint64_t *features);
bool vhost_svq_ack_guest_features(uint64_t dev_features,
@@ -39,7 +46,8 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
VirtQueue *vq);
void vhost_svq_stop(VhostShadowVirtqueue *svq);
-VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_map);
+VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_map,
+ const VhostShadowVirtqueueOps *ops);
void vhost_svq_free(VhostShadowVirtqueue *vq);
@@ -17,6 +17,7 @@
#include "hw/virtio/vhost-iova-tree.h"
#include "hw/virtio/virtio.h"
#include "standard-headers/linux/vhost_types.h"
+#include "hw/virtio/vhost-shadow-virtqueue.h"
typedef struct VhostVDPAHostNotifier {
MemoryRegion mr;
@@ -34,6 +35,7 @@ typedef struct vhost_vdpa {
/* IOVA mapping used by Shadow Virtqueue */
VhostIOVATree *iova_tree;
GPtrArray *shadow_vqs;
+ const VhostShadowVirtqueueOps *shadow_vq_ops;
struct vhost_dev *dev;
VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
} VhostVDPA;
@@ -59,6 +59,12 @@ struct VhostShadowVirtqueue {
/* Next VirtQueue element that guest made available */
SVQElement *next_guest_avail_elem;
+ /* Optional callbacks */
+ const VhostShadowVirtqueueOps *ops;
+
+ /* Optional custom used virtqueue element handler */
+ VirtQueueElementCallback used_elem_cb;
+
/* Next head to expose to device */
uint16_t avail_idx_shadow;
@@ -509,6 +515,10 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
i = 0;
}
virtqueue_fill(vq, elem, elem->len, i++);
+
+ if (svq->ops && svq->ops->used_elem_handler) {
+ svq->ops->used_elem_handler(svq->vdev, elem);
+ }
}
virtqueue_flush(vq, i);
@@ -707,12 +717,14 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq)
*
* @qsize Shadow VirtQueue size
* @iova_tree Tree to perform descriptors translations
+ * @used_cb Optional callback for each device's used buffer
*
* Returns the new virtqueue or NULL.
*
* In case of error, reason is reported through error_report.
*/
-VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_tree)
+VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_tree,
+ const VhostShadowVirtqueueOps *ops)
{
size_t desc_size = sizeof(vring_desc_t) * qsize;
size_t device_size, driver_size;
@@ -747,6 +759,7 @@ VhostShadowVirtqueue *vhost_svq_new(uint16_t qsize, VhostIOVATree *iova_tree)
svq->iova_tree = iova_tree;
svq->ring_id_maps = g_new0(SVQElement *, qsize);
event_notifier_set_handler(&svq->hdev_call, vhost_svq_handle_call);
+ svq->ops = ops;
return g_steal_pointer(&svq);
err_init_hdev_call:
@@ -17,7 +17,6 @@
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
#include "hw/virtio/virtio-net.h"
-#include "hw/virtio/vhost-shadow-virtqueue.h"
#include "hw/virtio/vhost-vdpa.h"
#include "exec/address-spaces.h"
#include "qemu/main-loop.h"
@@ -1219,7 +1218,8 @@ static int vhost_vdpa_init_svq(struct vhost_dev *hdev, struct vhost_vdpa *v,
for (unsigned n = 0; n < hdev->nvqs; ++n) {
DMAMap device_region, driver_region;
struct vhost_vring_addr addr;
- VhostShadowVirtqueue *svq = vhost_svq_new(qsize, v->iova_tree);
+ VhostShadowVirtqueue *svq = vhost_svq_new(qsize, v->iova_tree,
+ v->shadow_vq_ops);
if (unlikely(!svq)) {
error_setg(errp, "Cannot create svq %u", n);
return -1;
The callback allows SVQ users to know the VirtQueue requests and responses. QEMU can use this to synchronize virtio device model state, allowing to migrate it with minimum changes to the migration code. In the case of networking, this will be used to inspect control virtqueue messages. Signed-off-by: Eugenio PĂ©rez <eperezma@redhat.com> --- hw/virtio/vhost-shadow-virtqueue.h | 10 +++++++++- include/hw/virtio/vhost-vdpa.h | 2 ++ hw/virtio/vhost-shadow-virtqueue.c | 15 ++++++++++++++- hw/virtio/vhost-vdpa.c | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-)