/* * VDUSE (vDPA Device in Userspace) library * * Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights reserved. * * Author: * Xie Yongji * * This work is licensed under the terms of the GNU GPL, version 2 or * later. See the COPYING file in the top-level directory. */ #ifndef LIBVDUSE_H #define LIBVDUSE_H #include #include #define VIRTQUEUE_MAX_SIZE 1024 /* VDUSE device structure */ typedef struct VduseDev VduseDev; /* Virtqueue structure */ typedef struct VduseVirtq VduseVirtq; /* Some operation of VDUSE backend */ typedef struct VduseOps { /* Called when virtqueue can be processed */ void (*enable_queue)(VduseDev *dev, VduseVirtq *vq); /* Called when virtqueue processing should be stopped */ void (*disable_queue)(VduseDev *dev, VduseVirtq *vq); } VduseOps; /* Describing elements of the I/O buffer */ typedef struct VduseVirtqElement { /* Descriptor table index */ unsigned int index; /* Number of physically-contiguous device-readable descriptors */ unsigned int out_num; /* Number of physically-contiguous device-writable descriptors */ unsigned int in_num; /* Array to store physically-contiguous device-writable descriptors */ struct iovec *in_sg; /* Array to store physically-contiguous device-readable descriptors */ struct iovec *out_sg; } VduseVirtqElement; /** * vduse_get_virtio_features: * * Get supported virtio features * * Returns: supported feature bits */ uint64_t vduse_get_virtio_features(void); /** * vduse_queue_get_dev: * @vq: specified virtqueue * * Get corresponding VDUSE device from the virtqueue. * * Returns: a pointer to VDUSE device on success, NULL on failure. */ VduseDev *vduse_queue_get_dev(VduseVirtq *vq); /** * vduse_queue_get_fd: * @vq: specified virtqueue * * Get the kick fd for the virtqueue. * * Returns: file descriptor on success, -1 on failure. */ int vduse_queue_get_fd(VduseVirtq *vq); /** * vduse_queue_pop: * @vq: specified virtqueue * @sz: the size of struct to return (must be >= VduseVirtqElement) * * Pop an element from virtqueue available ring. * * Returns: a pointer to a structure containing VduseVirtqElement on success, * NULL on failure. */ void *vduse_queue_pop(VduseVirtq *vq, size_t sz); /** * vduse_queue_push: * @vq: specified virtqueue * @elem: pointer to VduseVirtqElement returned by vduse_queue_pop() * @len: length in bytes to write * * Push an element to virtqueue used ring. */ void vduse_queue_push(VduseVirtq *vq, const VduseVirtqElement *elem, unsigned int len); /** * vduse_queue_notify: * @vq: specified virtqueue * * Request to notify the queue. */ void vduse_queue_notify(VduseVirtq *vq); /** * vduse_dev_get_priv: * @dev: VDUSE device * * Get the private pointer passed to vduse_dev_create(). * * Returns: private pointer on success, NULL on failure. */ void *vduse_dev_get_priv(VduseDev *dev); /** * vduse_dev_get_queue: * @dev: VDUSE device * @index: virtqueue index * * Get the specified virtqueue. * * Returns: a pointer to the virtqueue on success, NULL on failure. */ VduseVirtq *vduse_dev_get_queue(VduseDev *dev, int index); /** * vduse_dev_get_fd: * @dev: VDUSE device * * Get the control message fd for the VDUSE device. * * Returns: file descriptor on success, -1 on failure. */ int vduse_dev_get_fd(VduseDev *dev); /** * vduse_dev_handler: * @dev: VDUSE device * * Used to process the control message. * * Returns: file descriptor on success, -errno on failure. */ int vduse_dev_handler(VduseDev *dev); /** * vduse_dev_update_config: * @dev: VDUSE device * @size: the size to write to configuration space * @offset: the offset from the beginning of configuration space * @buffer: the buffer used to write from * * Update device configuration space and inject a config interrupt. * * Returns: 0 on success, -errno on failure. */ int vduse_dev_update_config(VduseDev *dev, uint32_t size, uint32_t offset, char *buffer); /** * vduse_dev_setup_queue: * @dev: VDUSE device * @index: virtqueue index * @max_size: the max size of virtqueue * * Setup the specified virtqueue. * * Returns: 0 on success, -errno on failure. */ int vduse_dev_setup_queue(VduseDev *dev, int index, int max_size); /** * vduse_set_reconnect_log_file: * @dev: VDUSE device * @file: filename of reconnect log * * Specify the file to store log for reconnecting. It should * be called before vduse_dev_setup_queue(). * * Returns: 0 on success, -errno on failure. */ int vduse_set_reconnect_log_file(VduseDev *dev, const char *filename); /** * vduse_dev_create_by_fd: * @fd: passed file descriptor * @num_queues: the number of virtqueues * @ops: the operation of VDUSE backend * @priv: private pointer * * Create VDUSE device from a passed file descriptor. * * Returns: pointer to VDUSE device on success, NULL on failure. */ VduseDev *vduse_dev_create_by_fd(int fd, uint16_t num_queues, const VduseOps *ops, void *priv); /** * vduse_dev_create_by_name: * @name: VDUSE device name * @num_queues: the number of virtqueues * @ops: the operation of VDUSE backend * @priv: private pointer * * Create VDUSE device on /dev/vduse/$NAME. * * Returns: pointer to VDUSE device on success, NULL on failure. */ VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues, const VduseOps *ops, void *priv); /** * vduse_dev_create: * @name: VDUSE device name * @device_id: virtio device id * @vendor_id: virtio vendor id * @features: virtio features * @num_queues: the number of virtqueues * @config_size: the size of the configuration space * @config: the buffer of the configuration space * @ops: the operation of VDUSE backend * @priv: private pointer * * Create VDUSE device. * * Returns: pointer to VDUSE device on success, NULL on failure. */ VduseDev *vduse_dev_create(const char *name, uint32_t device_id, uint32_t vendor_id, uint64_t features, uint16_t num_queues, uint32_t config_size, char *config, const VduseOps *ops, void *priv); /** * vduse_dev_destroy: * @dev: VDUSE device * * Destroy the VDUSE device. * * Returns: 0 on success, -errno on failure. */ int vduse_dev_destroy(VduseDev *dev); #endif