]> git.proxmox.com Git - mirror_qemu.git/blob - hw/virtio/vhost-shadow-virtqueue.h
vhost: move iova_tree set to vhost_svq_start
[mirror_qemu.git] / hw / virtio / vhost-shadow-virtqueue.h
1 /*
2 * vhost shadow virtqueue
3 *
4 * SPDX-FileCopyrightText: Red Hat, Inc. 2021
5 * SPDX-FileContributor: Author: Eugenio PĂ©rez <eperezma@redhat.com>
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #ifndef VHOST_SHADOW_VIRTQUEUE_H
11 #define VHOST_SHADOW_VIRTQUEUE_H
12
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"
17
18 typedef struct SVQDescState {
19 VirtQueueElement *elem;
20
21 /*
22 * Number of descriptors exposed to the device. May or may not match
23 * guest's
24 */
25 unsigned int ndescs;
26 } SVQDescState;
27
28 typedef struct VhostShadowVirtqueue VhostShadowVirtqueue;
29
30 /**
31 * Callback to handle an avail buffer.
32 *
33 * @svq: Shadow virtqueue
34 * @elem: Element placed in the queue by the guest
35 * @vq_callback_opaque: Opaque
36 *
37 * Returns 0 if the vq is running as expected.
38 *
39 * Note that ownership of elem is transferred to the callback.
40 */
41 typedef int (*VirtQueueAvailCallback)(VhostShadowVirtqueue *svq,
42 VirtQueueElement *elem,
43 void *vq_callback_opaque);
44
45 typedef struct VhostShadowVirtqueueOps {
46 VirtQueueAvailCallback avail_handler;
47 } VhostShadowVirtqueueOps;
48
49 /* Shadow virtqueue to relay notifications */
50 typedef struct VhostShadowVirtqueue {
51 /* Shadow vring */
52 struct vring vring;
53
54 /* Shadow kick notifier, sent to vhost */
55 EventNotifier hdev_kick;
56 /* Shadow call notifier, sent to vhost */
57 EventNotifier hdev_call;
58
59 /*
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.
64 *
65 * So shadow virtqueue must not clean it, or we would lose VirtQueue one.
66 */
67 EventNotifier svq_kick;
68
69 /* Guest's call notifier, where the SVQ calls guest. */
70 EventNotifier svq_call;
71
72 /* Virtio queue shadowing */
73 VirtQueue *vq;
74
75 /* Virtio device */
76 VirtIODevice *vdev;
77
78 /* IOVA mapping */
79 VhostIOVATree *iova_tree;
80
81 /* SVQ vring descriptors state */
82 SVQDescState *desc_state;
83
84 /* Next VirtQueue element that guest made available */
85 VirtQueueElement *next_guest_avail_elem;
86
87 /*
88 * Backup next field for each descriptor so we can recover securely, not
89 * needing to trust the device access.
90 */
91 uint16_t *desc_next;
92
93 /* Caller callbacks */
94 const VhostShadowVirtqueueOps *ops;
95
96 /* Caller callbacks opaque */
97 void *ops_opaque;
98
99 /* Next head to expose to the device */
100 uint16_t shadow_avail_idx;
101
102 /* Next free descriptor */
103 uint16_t free_head;
104
105 /* Last seen used idx */
106 uint16_t shadow_used_idx;
107
108 /* Next head to consume from the device */
109 uint16_t last_used_idx;
110 } VhostShadowVirtqueue;
111
112 bool vhost_svq_valid_features(uint64_t features, Error **errp);
113
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);
120
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);
127
128 void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
129 VirtQueue *vq, VhostIOVATree *iova_tree);
130 void vhost_svq_stop(VhostShadowVirtqueue *svq);
131
132 VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops,
133 void *ops_opaque);
134
135 void vhost_svq_free(gpointer vq);
136 G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free);
137
138 #endif