diff options
Diffstat (limited to 'virtio.h')
-rw-r--r-- | virtio.h | 171 |
1 files changed, 117 insertions, 54 deletions
@@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -// -/* come parts copied from QEMU subprojects/libvhost-user/libvhost-user.h */ +/* + * virtio API, vring and virtqueue functions definition + * + * Copyright Red Hat + * Author: Laurent Vivier <lvivier@redhat.com> + */ #ifndef VIRTIO_H #define VIRTIO_H @@ -8,61 +12,81 @@ #include <stdbool.h> #include <linux/vhost_types.h> +/* Maximum size of a virtqueue */ #define VIRTQUEUE_MAX_SIZE 1024 -#define vu_panic(vdev, ...) \ - do { \ - (vdev)->broken = true; \ - err( __VA_ARGS__ ); \ - } while (0) - -typedef struct VuRing { +/** + * struct vu_ring - Virtqueue rings + * @num: Size of the queue + * @desc: Descriptor ring + * @avail: Available ring + * @used: Used ring + * @log_guest_addr: Guest address for logging + * @flags: Vring flags + * VHOST_VRING_F_LOG is set if log address is valid + */ +struct vu_ring { unsigned int num; struct vring_desc *desc; struct vring_avail *avail; struct vring_used *used; uint64_t log_guest_addr; uint32_t flags; -} VuRing; - -typedef struct VuVirtq { - VuRing vring; - - /* Next head to pop */ +}; + +/** + * struct vu_virtq - Virtqueue definition + * @vring: Virtqueue rings + * @last_avail_idx: Next head to pop + * @shadow_avail_idx: Last avail_idx read from VQ. + * @used_idx: Descriptor ring current index + * @signalled_used: Last used index value we have signalled on + * @signalled_used_valid: True if signalled_used if valid + * @notification: True if the queues notify (via event + * index or interrupt) + * @inuse: Number of entries in use + * @call_fd: The event file descriptor to signal when + * buffers are used. + * @kick_fd: The event file descriptor for adding + * buffers to the vring + * @err_fd: The event file descriptor to signal when + * error occurs + * @enable: True if the virtqueue is enabled + * @started: True if the virtqueue is started + * @vra: QEMU address of our rings + */ +struct vu_virtq { + struct vu_ring vring; uint16_t last_avail_idx; - - /* Last avail_idx read from VQ. */ uint16_t shadow_avail_idx; - uint16_t used_idx; - - /* Last used index value we have signalled on */ uint16_t signalled_used; - - /* Last used index value we have signalled on */ bool signalled_used_valid; - bool notification; - unsigned int inuse; - int call_fd; int kick_fd; int err_fd; unsigned int enable; bool started; - - /* Guest addresses of our ring */ struct vhost_vring_addr vra; -} VuVirtq; - -typedef struct VuDevRegion { +}; + +/** + * struct vu_dev_region - guest shared memory region + * @gpa: Guest physical address of the region + * @size: Memory size in bytes + * @qva: QEMU virtual address + * @mmap_offset: Offset where the region starts in the mapped memory + * @mmap_addr: Address of the mapped memory + */ +struct vu_dev_region { uint64_t gpa; uint64_t size; uint64_t qva; uint64_t mmap_offset; uint64_t mmap_addr; -} VuDevRegion; +}; #define VHOST_USER_MAX_QUEUES 2 @@ -72,50 +96,89 @@ typedef struct VuDevRegion { */ #define VHOST_USER_MAX_RAM_SLOTS 32 -typedef struct VuDev { +/** + * struct vu_dev - vhost-user device information + * @context: Execution context + * @nregions: Number of shared memory regions + * @regions: Guest shared memory regions + * @features: Vhost-user features + * @protocol_features: Vhost-user protocol features + */ +struct vu_dev { + struct ctx *context; uint32_t nregions; - VuDevRegion regions[VHOST_USER_MAX_RAM_SLOTS]; - VuVirtq vq[VHOST_USER_MAX_QUEUES]; + struct vu_dev_region regions[VHOST_USER_MAX_RAM_SLOTS]; + struct vu_virtq vq[VHOST_USER_MAX_QUEUES]; uint64_t features; uint64_t protocol_features; - bool broken; - int hdrlen; -} VuDev; - -typedef struct VuVirtqElement { +}; + +/** + * struct vu_virtq_element - virtqueue element + * @index: Descriptor ring index + * @out_num: Number of outgoing iovec buffers + * @in_num: Number of incoming iovec buffers + * @in_sg: Incoming iovec buffers + * @out_sg: Outgoing iovec buffers + */ +struct vu_virtq_element { unsigned int index; unsigned int out_num; unsigned int in_num; struct iovec *in_sg; struct iovec *out_sg; -} VuVirtqElement; - +}; + +/** + * has_feature() - Check a feature bit in a features set + * @features: Features set + * @fb: Feature bit to check + * + * Return: True if the feature bit is set + */ static inline bool has_feature(uint64_t features, unsigned int fbit) { return !!(features & (1ULL << fbit)); } -static inline bool vu_has_feature(VuDev *vdev, unsigned int fbit) +/** + * vu_has_feature() - Check if a virtio-net feature is available + * @vdev: Vhost-user device + * @bit: Feature to check + * + * Return: True if the feature is available + */ +static inline bool vu_has_feature(const struct vu_dev *vdev, + unsigned int fbit) { return has_feature(vdev->features, fbit); } -static inline bool vu_has_protocol_feature(VuDev *vdev, unsigned int fbit) +/** + * vu_has_protocol_feature() - Check if a vhost-user feature is available + * @vdev: Vhost-user device + * @bit: Feature to check + * + * Return: True if the feature is available + */ +/* cppcheck-suppress unusedFunction */ +static inline bool vu_has_protocol_feature(const struct vu_dev *vdev, + unsigned int fbit) { return has_feature(vdev->protocol_features, fbit); } -bool vu_queue_empty(VuDev *dev, VuVirtq *vq); -void vu_queue_notify(VuDev *dev, VuVirtq *vq); -void *vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz, unsigned char *buffer); -void vu_queue_detach_element(VuDev *dev, VuVirtq *vq, unsigned int index, size_t len); -void vu_queue_unpop(VuDev *dev, VuVirtq *vq, unsigned int index, size_t len); -bool vu_queue_rewind(VuDev *dev, VuVirtq *vq, unsigned int num); - -void vu_queue_fill_by_index(VuDev *dev, VuVirtq *vq, unsigned int index, +bool vu_queue_empty(struct vu_virtq *vq); +void vu_queue_notify(const struct vu_dev *dev, struct vu_virtq *vq); +int vu_queue_pop(struct vu_dev *dev, struct vu_virtq *vq, + struct vu_virtq_element *elem); +void vu_queue_detach_element(struct vu_virtq *vq); +void vu_queue_unpop(struct vu_virtq *vq); +bool vu_queue_rewind(struct vu_virtq *vq, unsigned int num); +void vu_queue_fill_by_index(struct vu_virtq *vq, unsigned int index, unsigned int len, unsigned int idx); -void vu_queue_fill(VuDev *dev, VuVirtq *vq, VuVirtqElement *elem, unsigned int len, +void vu_queue_fill(struct vu_virtq *vq, + const struct vu_virtq_element *elem, unsigned int len, unsigned int idx); -void vu_queue_flush(VuDev *dev, VuVirtq *vq, unsigned int count); -void vu_queue_push(VuDev *dev, VuVirtq *vq, VuVirtqElement *elem, unsigned int len); +void vu_queue_flush(struct vu_virtq *vq, unsigned int count); #endif /* VIRTIO_H */ |