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