cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

libvhost-user.h (19141B)


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