qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

vhost-shadow-virtqueue.h (4238B)


      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);
    130 void vhost_svq_stop(VhostShadowVirtqueue *svq);
    131 
    132 VhostShadowVirtqueue *vhost_svq_new(VhostIOVATree *iova_tree,
    133                                     const VhostShadowVirtqueueOps *ops,
    134                                     void *ops_opaque);
    135 
    136 void vhost_svq_free(gpointer vq);
    137 G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostShadowVirtqueue, vhost_svq_free);
    138 
    139 #endif