1a6caeee8SXie Yongji /* 2a6caeee8SXie Yongji * VDUSE (vDPA Device in Userspace) library 3a6caeee8SXie Yongji * 4a6caeee8SXie Yongji * Copyright (C) 2022 Bytedance Inc. and/or its affiliates. All rights reserved. 5a6caeee8SXie Yongji * 6a6caeee8SXie Yongji * Author: 7a6caeee8SXie Yongji * Xie Yongji <xieyongji@bytedance.com> 8a6caeee8SXie Yongji * 9a6caeee8SXie Yongji * This work is licensed under the terms of the GNU GPL, version 2 or 10a6caeee8SXie Yongji * later. See the COPYING file in the top-level directory. 11a6caeee8SXie Yongji */ 12a6caeee8SXie Yongji 13a6caeee8SXie Yongji #ifndef LIBVDUSE_H 14a6caeee8SXie Yongji #define LIBVDUSE_H 15a6caeee8SXie Yongji 16a6caeee8SXie Yongji #include <stdint.h> 17a6caeee8SXie Yongji #include <sys/uio.h> 18a6caeee8SXie Yongji 19a6caeee8SXie Yongji #define VIRTQUEUE_MAX_SIZE 1024 20a6caeee8SXie Yongji 21a6caeee8SXie Yongji /* VDUSE device structure */ 22a6caeee8SXie Yongji typedef struct VduseDev VduseDev; 23a6caeee8SXie Yongji 24a6caeee8SXie Yongji /* Virtqueue structure */ 25a6caeee8SXie Yongji typedef struct VduseVirtq VduseVirtq; 26a6caeee8SXie Yongji 27a6caeee8SXie Yongji /* Some operation of VDUSE backend */ 28a6caeee8SXie Yongji typedef struct VduseOps { 29a6caeee8SXie Yongji /* Called when virtqueue can be processed */ 30a6caeee8SXie Yongji void (*enable_queue)(VduseDev *dev, VduseVirtq *vq); 31a6caeee8SXie Yongji /* Called when virtqueue processing should be stopped */ 32a6caeee8SXie Yongji void (*disable_queue)(VduseDev *dev, VduseVirtq *vq); 33a6caeee8SXie Yongji } VduseOps; 34a6caeee8SXie Yongji 35a6caeee8SXie Yongji /* Describing elements of the I/O buffer */ 36a6caeee8SXie Yongji typedef struct VduseVirtqElement { 37a6caeee8SXie Yongji /* Descriptor table index */ 38a6caeee8SXie Yongji unsigned int index; 39a6caeee8SXie Yongji /* Number of physically-contiguous device-readable descriptors */ 40a6caeee8SXie Yongji unsigned int out_num; 41a6caeee8SXie Yongji /* Number of physically-contiguous device-writable descriptors */ 42a6caeee8SXie Yongji unsigned int in_num; 43a6caeee8SXie Yongji /* Array to store physically-contiguous device-writable descriptors */ 44a6caeee8SXie Yongji struct iovec *in_sg; 45a6caeee8SXie Yongji /* Array to store physically-contiguous device-readable descriptors */ 46a6caeee8SXie Yongji struct iovec *out_sg; 47a6caeee8SXie Yongji } VduseVirtqElement; 48a6caeee8SXie Yongji 49a6caeee8SXie Yongji 50a6caeee8SXie Yongji /** 51a6caeee8SXie Yongji * vduse_get_virtio_features: 52a6caeee8SXie Yongji * 53a6caeee8SXie Yongji * Get supported virtio features 54a6caeee8SXie Yongji * 55a6caeee8SXie Yongji * Returns: supported feature bits 56a6caeee8SXie Yongji */ 57a6caeee8SXie Yongji uint64_t vduse_get_virtio_features(void); 58a6caeee8SXie Yongji 59a6caeee8SXie Yongji /** 60a6caeee8SXie Yongji * vduse_queue_get_dev: 61a6caeee8SXie Yongji * @vq: specified virtqueue 62a6caeee8SXie Yongji * 63a6caeee8SXie Yongji * Get corresponding VDUSE device from the virtqueue. 64a6caeee8SXie Yongji * 65a6caeee8SXie Yongji * Returns: a pointer to VDUSE device on success, NULL on failure. 66a6caeee8SXie Yongji */ 67a6caeee8SXie Yongji VduseDev *vduse_queue_get_dev(VduseVirtq *vq); 68a6caeee8SXie Yongji 69a6caeee8SXie Yongji /** 70a6caeee8SXie Yongji * vduse_queue_get_fd: 71a6caeee8SXie Yongji * @vq: specified virtqueue 72a6caeee8SXie Yongji * 73a6caeee8SXie Yongji * Get the kick fd for the virtqueue. 74a6caeee8SXie Yongji * 75a6caeee8SXie Yongji * Returns: file descriptor on success, -1 on failure. 76a6caeee8SXie Yongji */ 77a6caeee8SXie Yongji int vduse_queue_get_fd(VduseVirtq *vq); 78a6caeee8SXie Yongji 79a6caeee8SXie Yongji /** 80a6caeee8SXie Yongji * vduse_queue_pop: 81a6caeee8SXie Yongji * @vq: specified virtqueue 82a6caeee8SXie Yongji * @sz: the size of struct to return (must be >= VduseVirtqElement) 83a6caeee8SXie Yongji * 84a6caeee8SXie Yongji * Pop an element from virtqueue available ring. 85a6caeee8SXie Yongji * 86a6caeee8SXie Yongji * Returns: a pointer to a structure containing VduseVirtqElement on success, 87a6caeee8SXie Yongji * NULL on failure. 88a6caeee8SXie Yongji */ 89a6caeee8SXie Yongji void *vduse_queue_pop(VduseVirtq *vq, size_t sz); 90a6caeee8SXie Yongji 91a6caeee8SXie Yongji /** 92a6caeee8SXie Yongji * vduse_queue_push: 93a6caeee8SXie Yongji * @vq: specified virtqueue 94a6caeee8SXie Yongji * @elem: pointer to VduseVirtqElement returned by vduse_queue_pop() 95a6caeee8SXie Yongji * @len: length in bytes to write 96a6caeee8SXie Yongji * 97a6caeee8SXie Yongji * Push an element to virtqueue used ring. 98a6caeee8SXie Yongji */ 99a6caeee8SXie Yongji void vduse_queue_push(VduseVirtq *vq, const VduseVirtqElement *elem, 100a6caeee8SXie Yongji unsigned int len); 101a6caeee8SXie Yongji /** 102a6caeee8SXie Yongji * vduse_queue_notify: 103a6caeee8SXie Yongji * @vq: specified virtqueue 104a6caeee8SXie Yongji * 105a6caeee8SXie Yongji * Request to notify the queue. 106a6caeee8SXie Yongji */ 107a6caeee8SXie Yongji void vduse_queue_notify(VduseVirtq *vq); 108a6caeee8SXie Yongji 109a6caeee8SXie Yongji /** 110a6caeee8SXie Yongji * vduse_dev_get_priv: 111a6caeee8SXie Yongji * @dev: VDUSE device 112a6caeee8SXie Yongji * 113a6caeee8SXie Yongji * Get the private pointer passed to vduse_dev_create(). 114a6caeee8SXie Yongji * 115a6caeee8SXie Yongji * Returns: private pointer on success, NULL on failure. 116a6caeee8SXie Yongji */ 117a6caeee8SXie Yongji void *vduse_dev_get_priv(VduseDev *dev); 118a6caeee8SXie Yongji 119a6caeee8SXie Yongji /** 120a6caeee8SXie Yongji * vduse_dev_get_queue: 121a6caeee8SXie Yongji * @dev: VDUSE device 122a6caeee8SXie Yongji * @index: virtqueue index 123a6caeee8SXie Yongji * 124a6caeee8SXie Yongji * Get the specified virtqueue. 125a6caeee8SXie Yongji * 126a6caeee8SXie Yongji * Returns: a pointer to the virtqueue on success, NULL on failure. 127a6caeee8SXie Yongji */ 128a6caeee8SXie Yongji VduseVirtq *vduse_dev_get_queue(VduseDev *dev, int index); 129a6caeee8SXie Yongji 130a6caeee8SXie Yongji /** 131a6caeee8SXie Yongji * vduse_dev_get_fd: 132a6caeee8SXie Yongji * @dev: VDUSE device 133a6caeee8SXie Yongji * 134a6caeee8SXie Yongji * Get the control message fd for the VDUSE device. 135a6caeee8SXie Yongji * 136a6caeee8SXie Yongji * Returns: file descriptor on success, -1 on failure. 137a6caeee8SXie Yongji */ 138a6caeee8SXie Yongji int vduse_dev_get_fd(VduseDev *dev); 139a6caeee8SXie Yongji 140a6caeee8SXie Yongji /** 141a6caeee8SXie Yongji * vduse_dev_handler: 142a6caeee8SXie Yongji * @dev: VDUSE device 143a6caeee8SXie Yongji * 144a6caeee8SXie Yongji * Used to process the control message. 145a6caeee8SXie Yongji * 146a6caeee8SXie Yongji * Returns: file descriptor on success, -errno on failure. 147a6caeee8SXie Yongji */ 148a6caeee8SXie Yongji int vduse_dev_handler(VduseDev *dev); 149a6caeee8SXie Yongji 150a6caeee8SXie Yongji /** 151a6caeee8SXie Yongji * vduse_dev_update_config: 152a6caeee8SXie Yongji * @dev: VDUSE device 153a6caeee8SXie Yongji * @size: the size to write to configuration space 154a6caeee8SXie Yongji * @offset: the offset from the beginning of configuration space 155a6caeee8SXie Yongji * @buffer: the buffer used to write from 156a6caeee8SXie Yongji * 157a6caeee8SXie Yongji * Update device configuration space and inject a config interrupt. 158a6caeee8SXie Yongji * 159a6caeee8SXie Yongji * Returns: 0 on success, -errno on failure. 160a6caeee8SXie Yongji */ 161a6caeee8SXie Yongji int vduse_dev_update_config(VduseDev *dev, uint32_t size, 162a6caeee8SXie Yongji uint32_t offset, char *buffer); 163a6caeee8SXie Yongji 164a6caeee8SXie Yongji /** 165a6caeee8SXie Yongji * vduse_dev_setup_queue: 166a6caeee8SXie Yongji * @dev: VDUSE device 167a6caeee8SXie Yongji * @index: virtqueue index 168a6caeee8SXie Yongji * @max_size: the max size of virtqueue 169a6caeee8SXie Yongji * 170a6caeee8SXie Yongji * Setup the specified virtqueue. 171a6caeee8SXie Yongji * 172a6caeee8SXie Yongji * Returns: 0 on success, -errno on failure. 173a6caeee8SXie Yongji */ 174a6caeee8SXie Yongji int vduse_dev_setup_queue(VduseDev *dev, int index, int max_size); 175a6caeee8SXie Yongji 176a6caeee8SXie Yongji /** 177*d043e2dbSXie Yongji * vduse_set_reconnect_log_file: 178*d043e2dbSXie Yongji * @dev: VDUSE device 179*d043e2dbSXie Yongji * @file: filename of reconnect log 180*d043e2dbSXie Yongji * 181*d043e2dbSXie Yongji * Specify the file to store log for reconnecting. It should 182*d043e2dbSXie Yongji * be called before vduse_dev_setup_queue(). 183*d043e2dbSXie Yongji * 184*d043e2dbSXie Yongji * Returns: 0 on success, -errno on failure. 185*d043e2dbSXie Yongji */ 186*d043e2dbSXie Yongji int vduse_set_reconnect_log_file(VduseDev *dev, const char *filename); 187*d043e2dbSXie Yongji 188*d043e2dbSXie Yongji /** 189a6caeee8SXie Yongji * vduse_dev_create_by_fd: 190a6caeee8SXie Yongji * @fd: passed file descriptor 191a6caeee8SXie Yongji * @num_queues: the number of virtqueues 192a6caeee8SXie Yongji * @ops: the operation of VDUSE backend 193a6caeee8SXie Yongji * @priv: private pointer 194a6caeee8SXie Yongji * 195a6caeee8SXie Yongji * Create VDUSE device from a passed file descriptor. 196a6caeee8SXie Yongji * 197a6caeee8SXie Yongji * Returns: pointer to VDUSE device on success, NULL on failure. 198a6caeee8SXie Yongji */ 199a6caeee8SXie Yongji VduseDev *vduse_dev_create_by_fd(int fd, uint16_t num_queues, 200a6caeee8SXie Yongji const VduseOps *ops, void *priv); 201a6caeee8SXie Yongji 202a6caeee8SXie Yongji /** 203a6caeee8SXie Yongji * vduse_dev_create_by_name: 204a6caeee8SXie Yongji * @name: VDUSE device name 205a6caeee8SXie Yongji * @num_queues: the number of virtqueues 206a6caeee8SXie Yongji * @ops: the operation of VDUSE backend 207a6caeee8SXie Yongji * @priv: private pointer 208a6caeee8SXie Yongji * 209a6caeee8SXie Yongji * Create VDUSE device on /dev/vduse/$NAME. 210a6caeee8SXie Yongji * 211a6caeee8SXie Yongji * Returns: pointer to VDUSE device on success, NULL on failure. 212a6caeee8SXie Yongji */ 213a6caeee8SXie Yongji VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues, 214a6caeee8SXie Yongji const VduseOps *ops, void *priv); 215a6caeee8SXie Yongji 216a6caeee8SXie Yongji /** 217a6caeee8SXie Yongji * vduse_dev_create: 218a6caeee8SXie Yongji * @name: VDUSE device name 219a6caeee8SXie Yongji * @device_id: virtio device id 220a6caeee8SXie Yongji * @vendor_id: virtio vendor id 221a6caeee8SXie Yongji * @features: virtio features 222a6caeee8SXie Yongji * @num_queues: the number of virtqueues 223a6caeee8SXie Yongji * @config_size: the size of the configuration space 224a6caeee8SXie Yongji * @config: the buffer of the configuration space 225a6caeee8SXie Yongji * @ops: the operation of VDUSE backend 226a6caeee8SXie Yongji * @priv: private pointer 227a6caeee8SXie Yongji * 228a6caeee8SXie Yongji * Create VDUSE device. 229a6caeee8SXie Yongji * 230a6caeee8SXie Yongji * Returns: pointer to VDUSE device on success, NULL on failure. 231a6caeee8SXie Yongji */ 232a6caeee8SXie Yongji VduseDev *vduse_dev_create(const char *name, uint32_t device_id, 233a6caeee8SXie Yongji uint32_t vendor_id, uint64_t features, 234a6caeee8SXie Yongji uint16_t num_queues, uint32_t config_size, 235a6caeee8SXie Yongji char *config, const VduseOps *ops, void *priv); 236a6caeee8SXie Yongji 237a6caeee8SXie Yongji /** 238a6caeee8SXie Yongji * vduse_dev_destroy: 239a6caeee8SXie Yongji * @dev: VDUSE device 240a6caeee8SXie Yongji * 241a6caeee8SXie Yongji * Destroy the VDUSE device. 242a6caeee8SXie Yongji * 243a6caeee8SXie Yongji * Returns: 0 on success, -errno on failure. 244a6caeee8SXie Yongji */ 245a6caeee8SXie Yongji int vduse_dev_destroy(VduseDev *dev); 246a6caeee8SXie Yongji 247a6caeee8SXie Yongji #endif 248