]>
Commit | Line | Data |
---|---|---|
7b2e5c65 MAL |
1 | /* |
2 | * Vhost User library | |
3 | * | |
4 | * Copyright (c) 2016 Red Hat, Inc. | |
5 | * | |
6 | * Authors: | |
7 | * Victor Kaplansky <victork@redhat.com> | |
8 | * Marc-André Lureau <mlureau@redhat.com> | |
9 | * | |
10 | * This work is licensed under the terms of the GNU GPL, version 2 or | |
11 | * later. See the COPYING file in the top-level directory. | |
12 | */ | |
13 | ||
14 | #ifndef LIBVHOST_USER_H | |
15 | #define LIBVHOST_USER_H | |
16 | ||
17 | #include <stdint.h> | |
18 | #include <stdbool.h> | |
19 | #include <stddef.h> | |
49cc0340 | 20 | #include <sys/poll.h> |
7b2e5c65 MAL |
21 | #include <linux/vhost.h> |
22 | #include "standard-headers/linux/virtio_ring.h" | |
23 | ||
24 | /* Based on qemu/hw/virtio/vhost-user.c */ | |
25 | #define VHOST_USER_F_PROTOCOL_FEATURES 30 | |
26 | #define VHOST_LOG_PAGE 4096 | |
27 | ||
7b2e5c65 MAL |
28 | #define VIRTQUEUE_MAX_SIZE 1024 |
29 | ||
30 | #define VHOST_MEMORY_MAX_NREGIONS 8 | |
31 | ||
0bc24d83 CL |
32 | typedef enum VhostSetConfigType { |
33 | VHOST_SET_CONFIG_TYPE_MASTER = 0, | |
34 | VHOST_SET_CONFIG_TYPE_MIGRATION = 1, | |
35 | } VhostSetConfigType; | |
36 | ||
37 | /* | |
38 | * Maximum size of virtio device config space | |
39 | */ | |
40 | #define VHOST_USER_MAX_CONFIG_SIZE 256 | |
41 | ||
7b2e5c65 MAL |
42 | enum VhostUserProtocolFeature { |
43 | VHOST_USER_PROTOCOL_F_MQ = 0, | |
44 | VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, | |
45 | VHOST_USER_PROTOCOL_F_RARP = 2, | |
ea642e22 DDAG |
46 | VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, |
47 | VHOST_USER_PROTOCOL_F_NET_MTU = 4, | |
48 | VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, | |
49 | VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, | |
9ccbfe14 DDAG |
50 | VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, |
51 | VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, | |
ea3e6f5a | 52 | VHOST_USER_PROTOCOL_F_CONFIG = 9, |
d84599f5 TB |
53 | VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, |
54 | VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, | |
5f9ff1ef | 55 | VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, |
7b2e5c65 MAL |
56 | |
57 | VHOST_USER_PROTOCOL_F_MAX | |
58 | }; | |
59 | ||
60 | #define VHOST_USER_PROTOCOL_FEATURE_MASK ((1 << VHOST_USER_PROTOCOL_F_MAX) - 1) | |
61 | ||
62 | typedef enum VhostUserRequest { | |
63 | VHOST_USER_NONE = 0, | |
64 | VHOST_USER_GET_FEATURES = 1, | |
65 | VHOST_USER_SET_FEATURES = 2, | |
66 | VHOST_USER_SET_OWNER = 3, | |
67 | VHOST_USER_RESET_OWNER = 4, | |
68 | VHOST_USER_SET_MEM_TABLE = 5, | |
69 | VHOST_USER_SET_LOG_BASE = 6, | |
70 | VHOST_USER_SET_LOG_FD = 7, | |
71 | VHOST_USER_SET_VRING_NUM = 8, | |
72 | VHOST_USER_SET_VRING_ADDR = 9, | |
73 | VHOST_USER_SET_VRING_BASE = 10, | |
74 | VHOST_USER_GET_VRING_BASE = 11, | |
75 | VHOST_USER_SET_VRING_KICK = 12, | |
76 | VHOST_USER_SET_VRING_CALL = 13, | |
77 | VHOST_USER_SET_VRING_ERR = 14, | |
78 | VHOST_USER_GET_PROTOCOL_FEATURES = 15, | |
79 | VHOST_USER_SET_PROTOCOL_FEATURES = 16, | |
80 | VHOST_USER_GET_QUEUE_NUM = 17, | |
81 | VHOST_USER_SET_VRING_ENABLE = 18, | |
82 | VHOST_USER_SEND_RARP = 19, | |
ea642e22 DDAG |
83 | VHOST_USER_NET_SET_MTU = 20, |
84 | VHOST_USER_SET_SLAVE_REQ_FD = 21, | |
85 | VHOST_USER_IOTLB_MSG = 22, | |
86 | VHOST_USER_SET_VRING_ENDIAN = 23, | |
0bc24d83 CL |
87 | VHOST_USER_GET_CONFIG = 24, |
88 | VHOST_USER_SET_CONFIG = 25, | |
d3dff7a5 DDAG |
89 | VHOST_USER_CREATE_CRYPTO_SESSION = 26, |
90 | VHOST_USER_CLOSE_CRYPTO_SESSION = 27, | |
91 | VHOST_USER_POSTCOPY_ADVISE = 28, | |
6864a7b5 | 92 | VHOST_USER_POSTCOPY_LISTEN = 29, |
c639187e | 93 | VHOST_USER_POSTCOPY_END = 30, |
5f9ff1ef XY |
94 | VHOST_USER_GET_INFLIGHT_FD = 31, |
95 | VHOST_USER_SET_INFLIGHT_FD = 32, | |
bd2e44fe | 96 | VHOST_USER_GPU_SET_SOCKET = 33, |
7b2e5c65 MAL |
97 | VHOST_USER_MAX |
98 | } VhostUserRequest; | |
99 | ||
d84599f5 TB |
100 | typedef enum VhostUserSlaveRequest { |
101 | VHOST_USER_SLAVE_NONE = 0, | |
102 | VHOST_USER_SLAVE_IOTLB_MSG = 1, | |
103 | VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2, | |
104 | VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3, | |
105 | VHOST_USER_SLAVE_MAX | |
106 | } VhostUserSlaveRequest; | |
107 | ||
7b2e5c65 MAL |
108 | typedef struct VhostUserMemoryRegion { |
109 | uint64_t guest_phys_addr; | |
110 | uint64_t memory_size; | |
111 | uint64_t userspace_addr; | |
112 | uint64_t mmap_offset; | |
113 | } VhostUserMemoryRegion; | |
114 | ||
115 | typedef struct VhostUserMemory { | |
116 | uint32_t nregions; | |
117 | uint32_t padding; | |
118 | VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS]; | |
119 | } VhostUserMemory; | |
120 | ||
121 | typedef struct VhostUserLog { | |
122 | uint64_t mmap_size; | |
123 | uint64_t mmap_offset; | |
124 | } VhostUserLog; | |
125 | ||
0bc24d83 CL |
126 | typedef struct VhostUserConfig { |
127 | uint32_t offset; | |
128 | uint32_t size; | |
129 | uint32_t flags; | |
130 | uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; | |
131 | } VhostUserConfig; | |
132 | ||
133 | static VhostUserConfig c __attribute__ ((unused)); | |
134 | #define VHOST_USER_CONFIG_HDR_SIZE (sizeof(c.offset) \ | |
135 | + sizeof(c.size) \ | |
136 | + sizeof(c.flags)) | |
137 | ||
d84599f5 TB |
138 | typedef struct VhostUserVringArea { |
139 | uint64_t u64; | |
140 | uint64_t size; | |
141 | uint64_t offset; | |
142 | } VhostUserVringArea; | |
143 | ||
5f9ff1ef XY |
144 | typedef struct VhostUserInflight { |
145 | uint64_t mmap_size; | |
146 | uint64_t mmap_offset; | |
147 | uint16_t num_queues; | |
148 | uint16_t queue_size; | |
149 | } VhostUserInflight; | |
150 | ||
48bb55bf | 151 | #if defined(_WIN32) && (defined(__x86_64__) || defined(__i386__)) |
7b2e5c65 MAL |
152 | # define VU_PACKED __attribute__((gcc_struct, packed)) |
153 | #else | |
154 | # define VU_PACKED __attribute__((packed)) | |
155 | #endif | |
156 | ||
157 | typedef struct VhostUserMsg { | |
ba275e9d | 158 | int request; |
7b2e5c65 MAL |
159 | |
160 | #define VHOST_USER_VERSION_MASK (0x3) | |
161 | #define VHOST_USER_REPLY_MASK (0x1 << 2) | |
d84599f5 | 162 | #define VHOST_USER_NEED_REPLY_MASK (0x1 << 3) |
7b2e5c65 MAL |
163 | uint32_t flags; |
164 | uint32_t size; /* the following payload size */ | |
165 | ||
166 | union { | |
167 | #define VHOST_USER_VRING_IDX_MASK (0xff) | |
168 | #define VHOST_USER_VRING_NOFD_MASK (0x1 << 8) | |
169 | uint64_t u64; | |
170 | struct vhost_vring_state state; | |
171 | struct vhost_vring_addr addr; | |
172 | VhostUserMemory memory; | |
173 | VhostUserLog log; | |
0bc24d83 | 174 | VhostUserConfig config; |
d84599f5 | 175 | VhostUserVringArea area; |
5f9ff1ef | 176 | VhostUserInflight inflight; |
7b2e5c65 MAL |
177 | } payload; |
178 | ||
179 | int fds[VHOST_MEMORY_MAX_NREGIONS]; | |
180 | int fd_num; | |
181 | uint8_t *data; | |
182 | } VU_PACKED VhostUserMsg; | |
183 | ||
184 | typedef struct VuDevRegion { | |
185 | /* Guest Physical address. */ | |
186 | uint64_t gpa; | |
187 | /* Memory region size. */ | |
188 | uint64_t size; | |
189 | /* QEMU virtual address (userspace). */ | |
190 | uint64_t qva; | |
191 | /* Starting offset in our mmaped space. */ | |
192 | uint64_t mmap_offset; | |
193 | /* Start address of mmaped space. */ | |
194 | uint64_t mmap_addr; | |
195 | } VuDevRegion; | |
196 | ||
197 | typedef struct VuDev VuDev; | |
198 | ||
199 | typedef uint64_t (*vu_get_features_cb) (VuDev *dev); | |
200 | typedef void (*vu_set_features_cb) (VuDev *dev, uint64_t features); | |
201 | typedef int (*vu_process_msg_cb) (VuDev *dev, VhostUserMsg *vmsg, | |
202 | int *do_reply); | |
203 | typedef void (*vu_queue_set_started_cb) (VuDev *dev, int qidx, bool started); | |
35480cbf | 204 | typedef bool (*vu_queue_is_processed_in_order_cb) (VuDev *dev, int qidx); |
0bc24d83 CL |
205 | typedef int (*vu_get_config_cb) (VuDev *dev, uint8_t *config, uint32_t len); |
206 | typedef int (*vu_set_config_cb) (VuDev *dev, const uint8_t *data, | |
207 | uint32_t offset, uint32_t size, | |
208 | uint32_t flags); | |
7b2e5c65 MAL |
209 | |
210 | typedef struct VuDevIface { | |
211 | /* called by VHOST_USER_GET_FEATURES to get the features bitmask */ | |
212 | vu_get_features_cb get_features; | |
213 | /* enable vhost implementation features */ | |
214 | vu_set_features_cb set_features; | |
215 | /* get the protocol feature bitmask from the underlying vhost | |
216 | * implementation */ | |
217 | vu_get_features_cb get_protocol_features; | |
218 | /* enable protocol features in the underlying vhost implementation. */ | |
219 | vu_set_features_cb set_protocol_features; | |
220 | /* process_msg is called for each vhost-user message received */ | |
221 | /* skip libvhost-user processing if return value != 0 */ | |
222 | vu_process_msg_cb process_msg; | |
223 | /* tells when queues can be processed */ | |
224 | vu_queue_set_started_cb queue_set_started; | |
35480cbf MAL |
225 | /* |
226 | * If the queue is processed in order, in which case it will be | |
227 | * resumed to vring.used->idx. This can help to support resuming | |
228 | * on unmanaged exit/crash. | |
229 | */ | |
230 | vu_queue_is_processed_in_order_cb queue_is_processed_in_order; | |
0bc24d83 CL |
231 | /* get the config space of the device */ |
232 | vu_get_config_cb get_config; | |
233 | /* set the config space of the device */ | |
234 | vu_set_config_cb set_config; | |
7b2e5c65 MAL |
235 | } VuDevIface; |
236 | ||
237 | typedef void (*vu_queue_handler_cb) (VuDev *dev, int qidx); | |
238 | ||
239 | typedef struct VuRing { | |
240 | unsigned int num; | |
241 | struct vring_desc *desc; | |
242 | struct vring_avail *avail; | |
243 | struct vring_used *used; | |
244 | uint64_t log_guest_addr; | |
245 | uint32_t flags; | |
246 | } VuRing; | |
247 | ||
5f9ff1ef XY |
248 | typedef struct VuDescStateSplit { |
249 | /* Indicate whether this descriptor is inflight or not. | |
250 | * Only available for head-descriptor. */ | |
251 | uint8_t inflight; | |
252 | ||
253 | /* Padding */ | |
254 | uint8_t padding[5]; | |
255 | ||
256 | /* Maintain a list for the last batch of used descriptors. | |
257 | * Only available when batching is used for submitting */ | |
258 | uint16_t next; | |
259 | ||
260 | /* Used to preserve the order of fetching available descriptors. | |
261 | * Only available for head-descriptor. */ | |
262 | uint64_t counter; | |
263 | } VuDescStateSplit; | |
264 | ||
265 | typedef struct VuVirtqInflight { | |
266 | /* The feature flags of this region. Now it's initialized to 0. */ | |
267 | uint64_t features; | |
268 | ||
269 | /* The version of this region. It's 1 currently. | |
270 | * Zero value indicates a vm reset happened. */ | |
271 | uint16_t version; | |
272 | ||
273 | /* The size of VuDescStateSplit array. It's equal to the virtqueue | |
274 | * size. Slave could get it from queue size field of VhostUserInflight. */ | |
275 | uint16_t desc_num; | |
276 | ||
277 | /* The head of list that track the last batch of used descriptors. */ | |
278 | uint16_t last_batch_head; | |
279 | ||
280 | /* Storing the idx value of used ring */ | |
281 | uint16_t used_idx; | |
282 | ||
283 | /* Used to track the state of each descriptor in descriptor table */ | |
284 | VuDescStateSplit desc[0]; | |
285 | } VuVirtqInflight; | |
286 | ||
287 | typedef struct VuVirtqInflightDesc { | |
288 | uint16_t index; | |
289 | uint64_t counter; | |
290 | } VuVirtqInflightDesc; | |
291 | ||
7b2e5c65 MAL |
292 | typedef struct VuVirtq { |
293 | VuRing vring; | |
294 | ||
5f9ff1ef XY |
295 | VuVirtqInflight *inflight; |
296 | ||
297 | VuVirtqInflightDesc *resubmit_list; | |
298 | ||
299 | uint16_t resubmit_num; | |
300 | ||
301 | uint64_t counter; | |
302 | ||
7b2e5c65 MAL |
303 | /* Next head to pop */ |
304 | uint16_t last_avail_idx; | |
305 | ||
306 | /* Last avail_idx read from VQ. */ | |
307 | uint16_t shadow_avail_idx; | |
308 | ||
309 | uint16_t used_idx; | |
310 | ||
311 | /* Last used index value we have signalled on */ | |
312 | uint16_t signalled_used; | |
313 | ||
314 | /* Last used index value we have signalled on */ | |
315 | bool signalled_used_valid; | |
316 | ||
317 | /* Notification enabled? */ | |
318 | bool notification; | |
319 | ||
320 | int inuse; | |
321 | ||
322 | vu_queue_handler_cb handler; | |
323 | ||
324 | int call_fd; | |
325 | int kick_fd; | |
326 | int err_fd; | |
327 | unsigned int enable; | |
328 | bool started; | |
329 | } VuVirtq; | |
330 | ||
331 | enum VuWatchCondtion { | |
49cc0340 FF |
332 | VU_WATCH_IN = POLLIN, |
333 | VU_WATCH_OUT = POLLOUT, | |
334 | VU_WATCH_PRI = POLLPRI, | |
335 | VU_WATCH_ERR = POLLERR, | |
336 | VU_WATCH_HUP = POLLHUP, | |
7b2e5c65 MAL |
337 | }; |
338 | ||
339 | typedef void (*vu_panic_cb) (VuDev *dev, const char *err); | |
340 | typedef void (*vu_watch_cb) (VuDev *dev, int condition, void *data); | |
341 | typedef void (*vu_set_watch_cb) (VuDev *dev, int fd, int condition, | |
342 | vu_watch_cb cb, void *data); | |
343 | typedef void (*vu_remove_watch_cb) (VuDev *dev, int fd); | |
344 | ||
5f9ff1ef XY |
345 | typedef struct VuDevInflightInfo { |
346 | int fd; | |
347 | void *addr; | |
348 | uint64_t size; | |
349 | } VuDevInflightInfo; | |
350 | ||
7b2e5c65 MAL |
351 | struct VuDev { |
352 | int sock; | |
353 | uint32_t nregions; | |
354 | VuDevRegion regions[VHOST_MEMORY_MAX_NREGIONS]; | |
6f5fd837 | 355 | VuVirtq *vq; |
5f9ff1ef | 356 | VuDevInflightInfo inflight_info; |
7b2e5c65 | 357 | int log_call_fd; |
13384f15 | 358 | int slave_fd; |
7b2e5c65 MAL |
359 | uint64_t log_size; |
360 | uint8_t *log_table; | |
361 | uint64_t features; | |
362 | uint64_t protocol_features; | |
363 | bool broken; | |
6f5fd837 | 364 | uint16_t max_queues; |
7b2e5c65 MAL |
365 | |
366 | /* @set_watch: add or update the given fd to the watch set, | |
367 | * call cb when condition is met */ | |
368 | vu_set_watch_cb set_watch; | |
369 | ||
370 | /* @remove_watch: remove the given fd from the watch set */ | |
371 | vu_remove_watch_cb remove_watch; | |
372 | ||
373 | /* @panic: encountered an unrecoverable error, you may try to | |
374 | * re-initialize */ | |
375 | vu_panic_cb panic; | |
376 | const VuDevIface *iface; | |
2a84ffc0 DDAG |
377 | |
378 | /* Postcopy data */ | |
379 | int postcopy_ufd; | |
6864a7b5 | 380 | bool postcopy_listening; |
7b2e5c65 MAL |
381 | }; |
382 | ||
383 | typedef struct VuVirtqElement { | |
384 | unsigned int index; | |
385 | unsigned int out_num; | |
386 | unsigned int in_num; | |
387 | struct iovec *in_sg; | |
388 | struct iovec *out_sg; | |
389 | } VuVirtqElement; | |
390 | ||
391 | /** | |
392 | * vu_init: | |
393 | * @dev: a VuDev context | |
6f5fd837 | 394 | * @max_queues: maximum number of virtqueues |
7b2e5c65 MAL |
395 | * @socket: the socket connected to vhost-user master |
396 | * @panic: a panic callback | |
397 | * @set_watch: a set_watch callback | |
398 | * @remove_watch: a remove_watch callback | |
399 | * @iface: a VuDevIface structure with vhost-user device callbacks | |
400 | * | |
401 | * Intializes a VuDev vhost-user context. | |
6f5fd837 SH |
402 | * |
403 | * Returns: true on success, false on failure. | |
7b2e5c65 | 404 | **/ |
6f5fd837 SH |
405 | bool vu_init(VuDev *dev, |
406 | uint16_t max_queues, | |
7b2e5c65 MAL |
407 | int socket, |
408 | vu_panic_cb panic, | |
409 | vu_set_watch_cb set_watch, | |
410 | vu_remove_watch_cb remove_watch, | |
411 | const VuDevIface *iface); | |
412 | ||
413 | ||
414 | /** | |
415 | * vu_deinit: | |
416 | * @dev: a VuDev context | |
417 | * | |
418 | * Cleans up the VuDev context | |
419 | */ | |
420 | void vu_deinit(VuDev *dev); | |
421 | ||
422 | /** | |
423 | * vu_dispatch: | |
424 | * @dev: a VuDev context | |
425 | * | |
426 | * Process one vhost-user message. | |
427 | * | |
428 | * Returns: TRUE on success, FALSE on failure. | |
429 | */ | |
430 | bool vu_dispatch(VuDev *dev); | |
431 | ||
432 | /** | |
433 | * vu_gpa_to_va: | |
434 | * @dev: a VuDev context | |
293084a7 | 435 | * @plen: guest memory size |
7b2e5c65 MAL |
436 | * @guest_addr: guest address |
437 | * | |
438 | * Translate a guest address to a pointer. Returns NULL on failure. | |
439 | */ | |
293084a7 | 440 | void *vu_gpa_to_va(VuDev *dev, uint64_t *plen, uint64_t guest_addr); |
7b2e5c65 MAL |
441 | |
442 | /** | |
443 | * vu_get_queue: | |
444 | * @dev: a VuDev context | |
445 | * @qidx: queue index | |
446 | * | |
447 | * Returns the queue number @qidx. | |
448 | */ | |
449 | VuVirtq *vu_get_queue(VuDev *dev, int qidx); | |
450 | ||
451 | /** | |
452 | * vu_set_queue_handler: | |
453 | * @dev: a VuDev context | |
454 | * @vq: a VuVirtq queue | |
455 | * @handler: the queue handler callback | |
456 | * | |
457 | * Set the queue handler. This function may be called several times | |
458 | * for the same queue. If called with NULL @handler, the handler is | |
459 | * removed. | |
460 | */ | |
461 | void vu_set_queue_handler(VuDev *dev, VuVirtq *vq, | |
462 | vu_queue_handler_cb handler); | |
463 | ||
d84599f5 TB |
464 | /** |
465 | * vu_set_queue_host_notifier: | |
466 | * @dev: a VuDev context | |
467 | * @vq: a VuVirtq queue | |
468 | * @fd: a file descriptor | |
469 | * @size: host page size | |
470 | * @offset: notifier offset in @fd file | |
471 | * | |
472 | * Set queue's host notifier. This function may be called several | |
473 | * times for the same queue. If called with -1 @fd, the notifier | |
474 | * is removed. | |
475 | */ | |
476 | bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, | |
477 | int size, int offset); | |
7b2e5c65 MAL |
478 | |
479 | /** | |
480 | * vu_queue_set_notification: | |
481 | * @dev: a VuDev context | |
482 | * @vq: a VuVirtq queue | |
483 | * @enable: state | |
484 | * | |
485 | * Set whether the queue notifies (via event index or interrupt) | |
486 | */ | |
487 | void vu_queue_set_notification(VuDev *dev, VuVirtq *vq, int enable); | |
488 | ||
489 | /** | |
490 | * vu_queue_enabled: | |
491 | * @dev: a VuDev context | |
492 | * @vq: a VuVirtq queue | |
493 | * | |
494 | * Returns: whether the queue is enabled. | |
495 | */ | |
496 | bool vu_queue_enabled(VuDev *dev, VuVirtq *vq); | |
497 | ||
bcf0836d DDAG |
498 | /** |
499 | * vu_queue_started: | |
500 | * @dev: a VuDev context | |
501 | * @vq: a VuVirtq queue | |
502 | * | |
503 | * Returns: whether the queue is started. | |
504 | */ | |
505 | bool vu_queue_started(const VuDev *dev, const VuVirtq *vq); | |
506 | ||
7b2e5c65 | 507 | /** |
640601c7 | 508 | * vu_queue_empty: |
7b2e5c65 MAL |
509 | * @dev: a VuDev context |
510 | * @vq: a VuVirtq queue | |
511 | * | |
640601c7 | 512 | * Returns: true if the queue is empty or not ready. |
7b2e5c65 | 513 | */ |
640601c7 | 514 | bool vu_queue_empty(VuDev *dev, VuVirtq *vq); |
7b2e5c65 MAL |
515 | |
516 | /** | |
517 | * vu_queue_notify: | |
518 | * @dev: a VuDev context | |
519 | * @vq: a VuVirtq queue | |
520 | * | |
521 | * Request to notify the queue via callfd (skipped if unnecessary) | |
522 | */ | |
523 | void vu_queue_notify(VuDev *dev, VuVirtq *vq); | |
524 | ||
525 | /** | |
526 | * vu_queue_pop: | |
527 | * @dev: a VuDev context | |
528 | * @vq: a VuVirtq queue | |
529 | * @sz: the size of struct to return (must be >= VuVirtqElement) | |
530 | * | |
19409df8 MAL |
531 | * Returns: a VuVirtqElement filled from the queue or NULL. The |
532 | * returned element must be free()-d by the caller. | |
7b2e5c65 MAL |
533 | */ |
534 | void *vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz); | |
535 | ||
b13919ab MAL |
536 | |
537 | /** | |
538 | * vu_queue_unpop: | |
539 | * @dev: a VuDev context | |
540 | * @vq: a VuVirtq queue | |
541 | * @elem: The #VuVirtqElement | |
542 | * @len: number of bytes written | |
543 | * | |
544 | * Pretend the most recent element wasn't popped from the virtqueue. The next | |
545 | * call to vu_queue_pop() will refetch the element. | |
546 | */ | |
547 | void vu_queue_unpop(VuDev *dev, VuVirtq *vq, VuVirtqElement *elem, | |
548 | size_t len); | |
549 | ||
7b2e5c65 MAL |
550 | /** |
551 | * vu_queue_rewind: | |
552 | * @dev: a VuDev context | |
553 | * @vq: a VuVirtq queue | |
554 | * @num: number of elements to push back | |
555 | * | |
556 | * Pretend that elements weren't popped from the virtqueue. The next | |
557 | * virtqueue_pop() will refetch the oldest element. | |
558 | * | |
559 | * Returns: true on success, false if @num is greater than the number of in use | |
560 | * elements. | |
561 | */ | |
562 | bool vu_queue_rewind(VuDev *dev, VuVirtq *vq, unsigned int num); | |
563 | ||
564 | /** | |
565 | * vu_queue_fill: | |
566 | * @dev: a VuDev context | |
567 | * @vq: a VuVirtq queue | |
568 | * @elem: a VuVirtqElement | |
569 | * @len: length in bytes to write | |
570 | * @idx: optional offset for the used ring index (0 in general) | |
571 | * | |
572 | * Fill the used ring with @elem element. | |
573 | */ | |
574 | void vu_queue_fill(VuDev *dev, VuVirtq *vq, | |
575 | const VuVirtqElement *elem, | |
576 | unsigned int len, unsigned int idx); | |
577 | ||
578 | /** | |
579 | * vu_queue_push: | |
580 | * @dev: a VuDev context | |
581 | * @vq: a VuVirtq queue | |
582 | * @elem: a VuVirtqElement | |
583 | * @len: length in bytes to write | |
584 | * | |
585 | * Helper that combines vu_queue_fill() with a vu_queue_flush(). | |
586 | */ | |
587 | void vu_queue_push(VuDev *dev, VuVirtq *vq, | |
588 | const VuVirtqElement *elem, unsigned int len); | |
589 | ||
590 | /** | |
591 | * vu_queue_flush: | |
592 | * @dev: a VuDev context | |
593 | * @vq: a VuVirtq queue | |
594 | * @num: number of elements to flush | |
595 | * | |
596 | * Mark the last number of elements as done (used.idx is updated by | |
597 | * num elements). | |
598 | */ | |
599 | void vu_queue_flush(VuDev *dev, VuVirtq *vq, unsigned int num); | |
600 | ||
601 | /** | |
602 | * vu_queue_get_avail_bytes: | |
603 | * @dev: a VuDev context | |
604 | * @vq: a VuVirtq queue | |
605 | * @in_bytes: in bytes | |
606 | * @out_bytes: out bytes | |
607 | * @max_in_bytes: stop counting after max_in_bytes | |
608 | * @max_out_bytes: stop counting after max_out_bytes | |
609 | * | |
610 | * Count the number of available bytes, up to max_in_bytes/max_out_bytes. | |
611 | */ | |
612 | void vu_queue_get_avail_bytes(VuDev *vdev, VuVirtq *vq, unsigned int *in_bytes, | |
613 | unsigned int *out_bytes, | |
614 | unsigned max_in_bytes, unsigned max_out_bytes); | |
615 | ||
616 | /** | |
617 | * vu_queue_avail_bytes: | |
618 | * @dev: a VuDev context | |
619 | * @vq: a VuVirtq queue | |
620 | * @in_bytes: expected in bytes | |
621 | * @out_bytes: expected out bytes | |
622 | * | |
623 | * Returns: true if in_bytes <= in_total && out_bytes <= out_total | |
624 | */ | |
625 | bool vu_queue_avail_bytes(VuDev *dev, VuVirtq *vq, unsigned int in_bytes, | |
626 | unsigned int out_bytes); | |
627 | ||
628 | #endif /* LIBVHOST_USER_H */ |