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