1/*
2 * Copyright (c) 2014 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#ifndef VIRTIO_VIRTIO_RING_H
11#define VIRTIO_VIRTIO_RING_H
12
13#include <barrelfish/barrelfish.h>
14
15/*
16 * This file contains the Virtio VRing description as defined in the VirtIO
17 * specification.
18 *
19 * Extracted from the Virtio Specification 1.0
20 * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf
21 */
22
23/**
24 * 2.4.5 The Virtqueue Descriptor Table
25 *
26 * The descriptor table refers to the buffers the driver is using for the device.
27 *
28 * Alignment Constraint: 16 byte boundary
29 */
30struct vring_desc
31{
32    lpaddr_t addr;   ///< Address (guest-physical).
33    uint32_t length; ///< Length of the data in the buffer
34    uint16_t flags;  ///< The flags, see VRING_DESC_F_*
35    uint16_t next;   ///< Next field used for chaining if flags & NEXT
36};
37
38/// This marks a buffer as continuing via the next field.
39#define VIRTIO_RING_DESC_F_NEXT       0x01
40
41/// This marks a buffer as device write-only (otherwise device read-only).
42#define VIRTIO_RING_DESC_F_WRITE      0x02
43
44/// This means the buffer contains a list of buffer descriptors.
45#define VIRTIO_RING_DESC_F_INDIRECT   0x04
46
47
48
49/**
50 * 2.4.5.3 Indirect Descriptors
51 */
52struct indirect_vring_desc
53{
54    struct vring_desc desc[0];  ///< The actual descriptors (16 bytes each)
55};
56
57/// gets the number of Virtqueue descriptors of the table
58#define VIRTIO_RING_NUM_INDIRECT(vdesc) \
59    ((vdesc)->length)/16;
60
61#define VIRTIO_RING_MAX_INDIRECT ((uint32_t) (BASE_PAGE_SIZE / 16))
62
63/**
64 * 2.4.6 The Virtqueue Available Ring
65 *
66 * The driver uses the available ring to offer buffers to the device.
67 * It is only written by the driver and read by the device.
68 *
69 * Alignment Constraint: 2 byte boundary
70 */
71
72struct vring_avail
73{
74    uint16_t flags;        ///< Ring flags see VRING_AVAIL_F_*
75    uint16_t idx;          ///< where the driver would put the next descriptor
76    uint16_t ring[0];       ///< refers to a head of descriptor chain
77    /* Only if VIRTIO_RING_F_EVENT_IDX uint16_t used_event;  */
78};
79
80/// disable sending interrupts when the host consumes a buffer
81#define VIRTIO_RING_AVAIL_F_NO_INTERRUPT 1
82
83/**
84 * is an element of the used ring
85 */
86struct vring_used_elem
87{
88    uint32_t id;        ///< index of start of used descriptor chain
89    uint32_t length;    ///< total length of descriptor chain
90};
91
92/**
93 * 2.4.8 The Virtqueue Used Ring
94 *
95 * The used ring is where the device returns buffers once it is done with them:
96 * it is only written to by the device, and read by the driver.
97 *
98 * Alignment Constraint: 4 byte boundary
99 */
100struct vring_used
101{
102    uint16_t flags;                 ///< see VRING_USED_F*
103    uint16_t idx;                   ///< where the driver would put next desc
104    struct vring_used_elem ring[0]; ///< refers to a head of a descriptor chain
105    /* Only if VIRTIO_RING_F_EVENT_IDX uint16_t avail_event; */
106};
107
108
109
110/// disable the notification when the guest adds a buffer
111#define VIRTIO_RING_USED_F_NO_NOTIFY 1
112
113/**
114 * 2.4 Virtqueues
115 *
116 * Queue Size corresponds to the maximum number of buffers in the virtqueue.
117 * Queue Size value is always a power of 2. The maximum Queue Size value is 32768.
118 * This value is specified in a bus-specific way.
119 */
120struct vring
121{
122    uint16_t num;               ///< the number of buffers in the queue
123    struct vring_desc *desc;    ///< the actual descriptors (16 bytes each)
124    struct vring_avail *avail;  ///< ring of available descriptor heads
125    struct vring_used *used;    ///< ring of used descriptor heads
126};
127
128/**
129 * \brief Calculates the size of a vring structure in memory aligned
130 *
131 * \param num   the queue size
132 * \param align the alignment constraints
133 */
134static inline size_t vring_size(uint16_t num, uintptr_t align)
135{
136    // calcualte the size of the descriptor table
137    size_t size = num * sizeof(struct vring_desc);
138
139    // calculate the size of the available ring:
140    // flags + idx + num * ring + used_event
141    size += sizeof(uint16_t) * (2 + num + 1);
142
143    // do the alignment
144    size = (size + align - 1) & ~(align - 1);
145
146    // calculate the size of the used ring:
147    // flags + idx + num *  used_element + avail_event
148    size += sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num;
149
150    return size;
151}
152
153/**
154 *
155 */
156static inline uint16_t vring_need_event(uint16_t event_idx,
157                                        uint16_t new_idx,
158                                        uint16_t old_idx)
159{
160    return (uint16_t) (new_idx - event_idx - 1) < (uint16_t) (new_idx - old_idx);
161}
162
163/**
164 * \brief Returns the index of the used event (Only if  VIRTIO_F_EVENT_IDX)
165 *
166 * Note: This field is located at the very end of of the available ring data
167 *       structure.
168 */
169static inline uint16_t *vring_get_used_event(struct vring *vr)
170{
171    return &vr->avail->ring[vr->num];
172}
173
174/**
175 * \brief Returns the index of the available event (Only if  VIRTIO_F_EVENT_IDX)
176 *
177 * Note: This field is located at the very end of of the used ring data
178 *       structure.
179 */
180static inline uint16_t *vring_get_avail_event(struct vring *vr)
181{
182    return (uint16_t *) &vr->used->ring[vr->num];
183}
184
185/*
186 * We layout the vring structure in memory as follows:
187 *
188 * struct vring {
189 *      // The actual descriptors (16 bytes each)
190 *      struct vring_desc desc[num];
191 *
192 *      // A ring of available descriptor heads with free-running index.
193 *      uint16_t avail_flags;
194 *      uint16_t avail_idx;
195 *      uint16_t available[num];
196 *      uint16_t used_event_idx;
197 *
198 *      // Padding to the next align boundary.
199 *      char pad[];
200 *
201 *      // A ring of used descriptor heads with free-running index.
202 *      uint16_t used_flags;
203 *      uint16_t used_idx;
204 *      struct vring_used_elem used[num];
205 *      uint16_t avail_event_idx;
206 * };
207 */
208
209
210/**
211 * \brief Initializes a vring structure
212 *
213 * \param vr    vring structure to initialize
214 * \param num   the number of vring descriptors
215 * \param addr  pointer to a contiguous memory range for the rings
216 * \param align alignment constraints for the vring
217 *
218 */
219static inline void vring_init(struct vring *vr,
220                              uint16_t num,
221                              uintptr_t align,
222                              void *addr)
223{
224    /* num must be a power of two */
225    assert(((num != 0) && ((num & (~num + 1)) == num)));
226
227    uintptr_t p = (uintptr_t)addr;
228
229    vr->num = num;
230    vr->desc = (struct vring_desc *) p;
231
232    vr->avail = (struct vring_avail *) (p + num * sizeof(struct vring_desc));
233
234    p = (uintptr_t)&vr->avail->ring[num];
235    vr->used = (void *) ((p + align-1) & ~(align-1));
236
237}
238
239/**
240 * \brief Maps the given capability and initializes the vring on the memory
241 *        backed by the supplied capability
242 *
243 * \param vr    pointer to the vring structure to be initialized
244 * \param num   the number of elements in the ring
245 * \param align alignment constraints for the vring
246 * \param cap   frame capability used as backing memory for the structure
247 *
248 * \return SYS_ERR_OK on success
249 *         errno      on failure
250 */
251errval_t vring_init_from_cap(struct vring *vr,
252                             uint16_t num,
253                             uintptr_t align,
254                             struct capref cap);
255
256/**
257 * \brief allocates a new vring structure
258 *
259 * \param vr        pointer to the vring structure
260 * \param num       the number of queue elements
261 * \param align     the alignment constraints for the vring
262 * \param ret_frame returned frame capability
263 *
264 * \return SYS_ERR_OK on success
265 *         errno      on failure
266 */
267errval_t vring_alloc(struct vring *vr,
268                     uint16_t num,
269                     uintptr_t align,
270                     struct capref *ret_frame);
271
272/**
273 * \brief frees the resources used by the vring structure
274 *
275 * \param vr the vring to be freed
276 *
277 * \return SYS_ERR_OK on success
278 *         errno      on failure
279 */
280errval_t vring_free(struct vring *vr);
281
282
283#endif // VIRTIO_VIRTIO_RING_H
284