]> git.proxmox.com Git - mirror_qemu.git/blob - hw/virtio/vhost-shadow-virtqueue.h
Merge tag 'pull-maintainer-may24-160524-2' of https://gitlab.com/stsquad/qemu into...
[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
111 /* Size of SVQ vring free descriptors */
112 uint16_t num_free;
113 } VhostShadowVirtqueue;
114
115 bool vhost_svq_valid_features(uint64_t features, Error **errp);
116
117 uint16_t vhost_svq_available_slots(const VhostShadowVirtqueue *svq);
118 void vhost_svq_push_elem(VhostShadowVirtqueue *svq,
119 const VirtQueueElement *elem, uint32_t len);
120 int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
121 size_t out_num, const struct iovec *in_sg, size_t in_num,
122 VirtQueueElement *elem);
123 size_t vhost_svq_poll(VhostShadowVirtqueue *svq, size_t num);
124
125 void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd);
126 void vhost_svq_set_svq_call_fd(VhostShadowVirtqueue *svq, int call_fd);
127 void vhost_svq_get_vring_addr(const VhostShadowVirtqueue *svq,
128 struct vhost_vring_addr *addr);
129 size_t vhost_svq_driver_area_size(const VhostShadowVirtqueue *svq);
130 size_t vhost_svq_device_area_size(const VhostShadowVirtqueue *svq);
131
132 void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
133 VirtQueue *vq, VhostIOVATree *iova_tree);
134 void vhost_svq_stop(VhostShadowVirtqueue *svq);
135
136 VhostShadowVirtqueue *vhost_svq_new(const VhostShadowVirtqueueOps *ops,
137 void *ops_opaque);
138
139 void vhost_svq_free(gpointer vq);
140 G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free);
141
142 #endif