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