2 * vhost shadow virtqueue
4 * SPDX-FileCopyrightText: Red Hat, Inc. 2021
5 * SPDX-FileContributor: Author: Eugenio PĂ©rez <eperezma@redhat.com>
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #ifndef VHOST_SHADOW_VIRTQUEUE_H
11 #define VHOST_SHADOW_VIRTQUEUE_H
13 #include "qemu/event_notifier.h"
14 #include "hw/virtio/virtio.h"
15 #include "standard-headers/linux/vhost_types.h"
16 #include "hw/virtio/vhost-iova-tree.h"
18 typedef struct SVQDescState
{
19 VirtQueueElement
*elem
;
22 * Number of descriptors exposed to the device. May or may not match
28 typedef struct VhostShadowVirtqueue VhostShadowVirtqueue
;
31 * Callback to handle an avail buffer.
33 * @svq: Shadow virtqueue
34 * @elem: Element placed in the queue by the guest
35 * @vq_callback_opaque: Opaque
37 * Returns 0 if the vq is running as expected.
39 * Note that ownership of elem is transferred to the callback.
41 typedef int (*VirtQueueAvailCallback
)(VhostShadowVirtqueue
*svq
,
42 VirtQueueElement
*elem
,
43 void *vq_callback_opaque
);
45 typedef struct VhostShadowVirtqueueOps
{
46 VirtQueueAvailCallback avail_handler
;
47 } VhostShadowVirtqueueOps
;
49 /* Shadow virtqueue to relay notifications */
50 typedef struct VhostShadowVirtqueue
{
54 /* Shadow kick notifier, sent to vhost */
55 EventNotifier hdev_kick
;
56 /* Shadow call notifier, sent to vhost */
57 EventNotifier hdev_call
;
60 * Borrowed virtqueue's guest to host notifier. To borrow it in this event
61 * notifier allows to recover the VhostShadowVirtqueue from the event loop
62 * easily. If we use the VirtQueue's one, we don't have an easy way to
63 * retrieve VhostShadowVirtqueue.
65 * So shadow virtqueue must not clean it, or we would lose VirtQueue one.
67 EventNotifier svq_kick
;
69 /* Guest's call notifier, where the SVQ calls guest. */
70 EventNotifier svq_call
;
72 /* Virtio queue shadowing */
79 VhostIOVATree
*iova_tree
;
81 /* SVQ vring descriptors state */
82 SVQDescState
*desc_state
;
84 /* Next VirtQueue element that guest made available */
85 VirtQueueElement
*next_guest_avail_elem
;
88 * Backup next field for each descriptor so we can recover securely, not
89 * needing to trust the device access.
93 /* Caller callbacks */
94 const VhostShadowVirtqueueOps
*ops
;
96 /* Caller callbacks opaque */
99 /* Next head to expose to the device */
100 uint16_t shadow_avail_idx
;
102 /* Next free descriptor */
105 /* Last seen used idx */
106 uint16_t shadow_used_idx
;
108 /* Next head to consume from the device */
109 uint16_t last_used_idx
;
110 } VhostShadowVirtqueue
;
112 bool vhost_svq_valid_features(uint64_t features
, Error
**errp
);
114 void vhost_svq_push_elem(VhostShadowVirtqueue
*svq
,
115 const VirtQueueElement
*elem
, uint32_t len
);
116 int vhost_svq_add(VhostShadowVirtqueue
*svq
, const struct iovec
*out_sg
,
117 size_t out_num
, const struct iovec
*in_sg
, size_t in_num
,
118 VirtQueueElement
*elem
);
119 size_t vhost_svq_poll(VhostShadowVirtqueue
*svq
);
121 void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue
*svq
, int svq_kick_fd
);
122 void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue
*svq
, int call_fd
);
123 void vhost_svq_get_vring_addr(const VhostShadowVirtqueue
*svq
,
124 struct vhost_vring_addr
*addr
);
125 size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue
*svq
);
126 size_t vhost_svq_device_area_size(const VhostShadowVirtqueue
*svq
);
128 void vhost_svq_start(VhostShadowVirtqueue
*svq
, VirtIODevice
*vdev
,
129 VirtQueue
*vq
, VhostIOVATree
*iova_tree
);
130 void vhost_svq_stop(VhostShadowVirtqueue
*svq
);
132 VhostShadowVirtqueue
*vhost_svq_new(const VhostShadowVirtqueueOps
*ops
,
135 void vhost_svq_free(gpointer vq
);
136 G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue
, vhost_svq_free
);