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_VIRTQUEUE_H 11#define VIRTIO_VIRTQUEUE_H 12 13#include <barrelfish/barrelfish.h> 14 15#ifdef __VIRTIO_HOST__ 16#include <virtio/virtio_host.h> 17#endif 18 19/* 20 * Extracted from the Virtio Specification 1.0 21 * http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.pdf 22 * 23 * VIRQUEUES: 24 * 25 * Size is determined by a 16bit integer. 26 * The queue consists of a descriptor table, available ring, used ring 27 * Each of the three parts are physically-contiguous in guest memory. 28 * 29 */ 30 31// forward definition 32struct virtqueue; 33 34/// interrupt handler for virtqueue interrupts 35typedef void (*virtq_intr_hander_t)(struct virtqueue *, void *); 36 37/// virtqueue default alignment 38#define VIRTQUEUE_ALIGNMENT 4096 39 40/// the maximum length of the name field 41#define VIRTQUEUE_NAME_SIZE 32 42 43/// the maximum number of elements in a vring 44#define VIRTQUEUE_SIZE_MAX (1<<15) 45 46/// this value marks the end of a descriptor chain 47#define VIRTQUEUE_CHAIN_END VIRTQUEUE_SIZE_MAX 48 49/// Feature flag indicating that the ring supports indirect descriptors 50#define VIRTIO_RING_F_INDIRECT_DESC 28 51 52/// Feature flag indicating that the ring supports interrupt suppression 53#define VIRTIO_RING_F_EVENT_IDX 29 54 55 56/** 57 * this structure holds necessary data to allocate a new virtqueue 58 * 59 * XXX: this may be a bit revised and split into two different structs 60 * one for the host and one for the guest 61 */ 62struct virtqueue_setup { 63 char name[VIRTQUEUE_NAME_SIZE]; ///< the name of the queue 64 struct virtio_device *device; ///< device this queue belongs to 65 uint16_t queue_id; ///< the id of this queue 66 uint16_t vring_ndesc; ///< size of the vring 67 lvaddr_t vring_align; ///< alignment of the vring 68 uint16_t max_indirect; ///< maximum indirect descriptors 69#ifdef __VIRTIO_HOST__ 70 virtq_work_handler_t worker_fn; ///< callback when new work arrives 71 void *worker_arg; ///< argument for the worker function 72#else 73 uint8_t buffer_bits; ///< when non zero, will allocate buffer 74 uint8_t header_bits; ///< allocate additional space for headers 75 uint8_t auto_add; ///< adds this virtqueue to the device 76 void *intr_arg; ///< argument for the interrupt handler 77 virtq_intr_hander_t intr_handler; ///< interrupt handler function 78#endif 79}; 80 81/** 82 * 83 */ 84enum virtqueue_intr_postpone { 85 VIRTQUEUE_INTR_POSTPONE_SHORT, 86 VIRTQUEUE_INTR_POSTPONE_LONG, 87 VIRTQUEUE_INTR_POSTPONE_EMPTIED, 88}; 89 90 91/** 92 * \brief allocates and initiates a new virtqueue structure 93 * 94 * \param setup pointer to the setup information 95 * \param vq pointer where to store the new virtqueue pointer 96 * 97 * \returns SYS_ERR_OK on success 98 */ 99errval_t virtio_virtqueue_alloc(struct virtqueue_setup *setup, 100 struct virtqueue **vq); 101 102/** 103 * \brief allocates and initiates a new virtqueue structure 104 * 105 * \param setup pointer to the setup information 106 * \param vring_cap capability to be used for the vring 107 * \param vq pointer where to store the new virtqueue pointer 108 * 109 * \returns SYS_ERR_OK on success 110 */ 111errval_t virtio_virtqueue_alloc_with_caps(struct virtqueue_setup *setup, 112 struct capref vring_cap, 113 struct virtqueue **vq); 114 115/** 116 * \brief frees the resources of previously allocated virtqueues 117 * 118 * \param vq pointer to the virtqueue memory to be freed 119 * 120 * \returns SYS_ERR_OK on success 121 */ 122errval_t virtio_virtqueue_free(struct virtqueue *vq); 123 124/* 125void *virtqueue_drain(struct virtqueue *vq, int *last); 126int virtqueue_reinit(struct virtqueue *vq, uint16_t size); 127*/ 128 129 130/* 131 * =========================================================================== 132 * Getter functions for certain values of the virtqueue structure 133 */ 134 135/** 136 * \brief Returns the physical address of the vring. 137 * 138 * \param vq pointer to the virtqueue structure 139 * 140 * \returns the physical address of the vring 141 */ 142lpaddr_t virtio_virtqueue_get_vring_paddr(struct virtqueue *vq); 143 144 145/** 146 * \brief Returns the frame capability of the vring 147 * 148 * \param vq pointer to the virtqueue structure 149 * \param ret_cap memory location where to store the capref 150 */ 151void virtio_virtqueue_get_vring_cap(struct virtqueue *vq, 152 struct capref *ret_cap); 153 154/** 155 * \brief Returns the queue index of the virtqueue of the device 156 * 157 * \param vq pointer to the virtqueue structure 158 * 159 * \returns queue index 160 */ 161uint16_t virtio_virtqueue_get_queue_index(struct virtqueue *vq); 162 163/** 164 * \brief returns the alignment of the vring 165 * 166 * \param the virtqueue to get the alignment from 167 * 168 * \returns vring alignment 169 */ 170lvaddr_t virtio_virtqueue_get_vring_align(struct virtqueue *vq); 171 172/** 173 * \brief Returns the number of elements (number of descriptors)in the vring of 174 * this virtqueue 175 * 176 * \param vq pointer to the virtqueue structure 177 * 178 * \returns number of elements in the vring 179 */ 180uint16_t virtio_virtqueue_get_num_desc(struct virtqueue *vq); 181 182/** 183 * \brief Checks if the virtqueue is empty 184 * 185 * \param vq pointer to the virtqueue structure 186 * 187 * \returns 0 the queue is not empty 188 * 1 the queue is empty 189 */ 190bool virtio_virtqueue_is_empty(struct virtqueue *vq); 191 192/** 193 * \brief Checks if the virtqueue is full 194 * 195 * \param vq pointer to the virtqueue structure 196 * 197 * \returns 0 the queue is not full 198 * 1 the queue is full 199 */ 200bool virtio_virtqueue_is_full(struct virtqueue *vq); 201 202/** 203 * \brief Calculates the number of used descriptors in this queue 204 * 205 * \param vq pointer to the virtqueue structure 206 * 207 * \returns number of used descriptors 208 */ 209uint16_t virtio_virtqueue_get_num_used(struct virtqueue *vq); 210 211/** 212 * \brief returns the number of bits if there are alrady allocated buffers 213 * for this queue 214 * 215 * \param vq the virtqueue 216 * 217 * \returns size of allocated buffers 218 * 0 if none 219 */ 220uint8_t virtio_virtqueue_has_buffers(struct virtqueue *vq); 221 222/** 223 * \brief returns the virtual base of the previously allocated buffer 224 * 225 * \param vq the virtqueue 226 * 227 * \returns virtual address of allocated buffers 228 * 0 if no buffers are allocated 229 */ 230lvaddr_t virtio_virtqueue_buffer_vbase(struct virtqueue *vq); 231 232/* 233 * =========================================================================== 234 * Interrupt handling 235 */ 236 237/** 238 * \brief enables the interrupts on the next descriptor processed 239 * 240 * \param vq the virtqueue to enable the interrupts 241 * 242 * \returns 1 if the interrupts have been enabled 243 * 0 if the interrupts have not been enabled 244 */ 245bool virtio_virtqueue_intr_enable(struct virtqueue *vq); 246 247/** 248 * \brief postpones the interrupt to a later point of time 249 * 250 * \param vq the virtqueue to enable the interrupts 251 * \param 252 * 253 * \returns 1 if the interrupts have been enabled 254 * 0 if the interrupts have not been enabled 255 */ 256bool virtio_virtqueue_intr_postpone(struct virtqueue *vq, 257 enum virtqueue_intr_postpone hint); 258 259/** 260 * \brief checks if the interrupts can be disabled 261 * 262 * \param vq virtual queue to check 263 * 264 * \returns 1 if the interrupts have been disabled 265 * 0 if the interrupts are not changed 266 * 267 */ 268bool virtio_virtqueue_intr_filter(struct virtqueue *vq); 269 270/** 271 * \brief calls the interrupt handler for this virtqueue 272 * 273 * \param vq virtqueue to call the intr handler for 274 */ 275void virtio_virtqueue_intr_handle(struct virtqueue *vq); 276 277/** 278 * \brief disables the interrupts for the given virtqueue by giving a hint 279 * to the host 280 * 281 * \param vq virtqueue to disable the interrupts 282 */ 283void virtio_virtqueue_intr_disable(struct virtqueue *vq); 284 285 286/** 287 * \brief notifies the host about the new queued descriptors 288 * 289 * \param vq virtqueue to notify the host 290 */ 291void virtio_virtqueue_notify_host(struct virtqueue *vq); 292 293 294/** 295 * \brief masks the ring features out of a features bit mask 296 * 297 * \param features the features to mask 298 * 299 * \returns bitmask of masked features 300 */ 301static inline uint64_t virtio_virtqueue_mask_features(uint64_t features) 302{ 303 uint64_t mask; 304 305 mask = (1 << VIRTIO_TRANSPORT_F_START) - 1; 306 mask |= (1 << VIRTIO_RING_F_INDIRECT_DESC); 307 mask |= (1 <<VIRTIO_RING_F_EVENT_IDX); 308 309 return (features & mask); 310} 311 312/* 313 * =========================================================================== 314 * Virtqueue Queue Management 315 */ 316 317/** 318 * \brief Enqueues a new descriptor chain into the virtqueue 319 * 320 * \param vq the virtqueue the descriptor chain gets enqueued in 321 * \param bl list of buffers to enqueue into the virtqueue 322 * \param st state associated with this descriptor chain 323 * \param num_wr number of writable descriptors 324 * \param num_rd number of readable descriptors 325 * 326 * \returns SYS_ERR_OK on success 327 * VIRTIO_ERR_* on failure 328 */ 329errval_t virtio_virtqueue_desc_enqueue(struct virtqueue *vq, 330 struct virtio_buffer_list *bl, 331 void *st, 332 uint16_t writeable, 333 uint16_t readable); 334 335/** 336 * \brief dequeues a descriptor chain form the virtqueue 337 * 338 * \param vq the virtqueue to dequeue descriptors from 339 * \param ret_bl returns the associated buffer list structure 340 * \param ret_st returns the associated state of the queue list 341 * 342 * \returns SYS_ERR_OK when the dequeue is successful 343 * VIRTIO_ERR_NO_DESC_AVAIL when there was no descriptor to dequeue 344 * VIRTIO_ERR_* if there was an error 345 */ 346errval_t virtio_virtqueue_desc_dequeue(struct virtqueue *vq, 347 struct virtio_buffer_list **ret_bl, 348 void **ret_st); 349 350 351/** 352 * \brief polls the virtqueue 353 * 354 * \param vq the virtqueue to dequeue descriptors from 355 * \param ret_bl returns the associated buffer list structure 356 * \param ret_st returns the associated state of the queue list 357 * \param handle_msg flag to have messages handled 358 * 359 * \returns SYS_ERR_OK when the dequeue is successful 360 * VIRTIO_ERR_* if there was an error 361 */ 362errval_t virtio_virtqueue_poll(struct virtqueue *vq, 363 struct virtio_buffer_list **ret_bl, 364 void **ret_st, 365 uint8_t handle_msg); 366 367/** 368 * \brief returns a buffer allocator based on the buffers with the virtqueue 369 * (if any) 370 * 371 * \param vq the virtqueue to get the buffer allocator 372 * \param alloc returns the pointer to the allocator 373 * 374 * \returns SYS_ERR_OK on SUCCESS 375 * VIRTIO_ERR_BUFFER_SIZE if there are no buffers allocated 376 */ 377errval_t virtio_virtqueue_get_buf_alloc(struct virtqueue *vq, 378 struct virtio_buffer_allocator **alloc); 379 380#endif // VIRTIO_VIRTQUEUE_H 381