renamed initialization functions of virtio devices to open instead of init.
[barrelfish] / lib / virtio / virtqueue.c
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 #include <string.h>
10
11 #include <barrelfish/barrelfish.h>
12
13 #include <virtio/virtio.h>
14 #include <virtio/virtio_ring.h>
15 #include <virtio/virtqueue.h>
16
17 #include "debug.h"
18
19
20 #define IS_POW2(num) (((num) != 0) && (((num) & (~(num) + 1)) == (num)))
21
22
23 #define VIRTQUEUE_FLAG_INDIRECT  0x0001
24 #define VIRTQUEUE_FLAG_EVENT_IDX 0x0002
25
26 /**
27  * this data structure stores additional information to the descriptors
28  */
29 struct vring_desc_info
30 {
31     void *buf;          ///< virtual address of this descriptor
32     struct capref cap;  ///< capability of this descriptor
33     size_t size;        ///< the size of the capability in bytes
34     lpaddr_t paddr;     ///< physical address of this descriptor
35     lpaddr_t offset;    ///< offset into the capability for mapping
36 };
37
38 /**
39  * this data structure represents a VirtIO queue. It contains additional
40  * information not stored with the vring structure
41  */
42 struct virtqueue
43 {
44     /* device information */
45     struct virtio_device *device;       ///< pointer to to the virtio device
46     uint16_t              queue_index;  ///< index of this queue in the device
47     char name[VIRTQUEUE_NAME_SIZE];     ///< name of the queue for debugging
48
49     /* vring information */
50     struct vring vring;                 ///< vring data structure
51     uint16_t vring_ndesc;               ///< number of descriptors of this vring
52     uint32_t flags;                     ///< flags
53     uint16_t free_head;                 ///< head of the free descriptor chain
54     uint16_t free_count;                ///< number of available free descriptors
55     uint16_t used_tail;                 ///< last consumed descriptor used table
56     uint16_t used_count;                ///< number of queued used descriptors
57
58     /* vring memory information */
59     struct capref vring_cap;            ///< capability of the vring data structure
60     lvaddr_t vring_vaddr;               ///< virtual address of the vring in memory
61     lpaddr_t vring_paddr;               ///< physical address of the vring
62     size_t vring_size;                  ///< the size of the vring in memory
63     lvaddr_t vring_align;               ///< the alignment of the vring
64
65     /* interrupt handling */
66     virtq_intr_hander_t intr_handler;   ///< interrupt handler
67     void               *intr_arg;       ///< user argument for the handler
68
69     struct vring_desc_info vring_di[0]; ///< array of additional desc information
70 #if 0
71     /* indirect descriptors */
72     uint16_t max_indirect;
73     size_t   indirect_size;
74     struct vq_desc_extra {
75             void          *cookie;  << virtual address?
76             struct vring_desc *indirect;
77             vm_paddr_t     indirect_paddr;
78             uint16_t       ndescs;
79         } vq_descx[0];
80 #endif
81 };
82
83 /**
84  * \brief sets the interrupt threshold to num_desc processed descriptors
85  *
86  * \param vq        virtqueue to enable the interrupts
87  * \param num_desc  the interrupt threshold
88  *
89  * \returns 1 if the interrupts have been enabled
90  *          0 if the interrupts have not been enabled
91  */
92 static bool virtqueue_interrupt_enable(struct virtqueue *vq,
93                                        uint16_t num_desc)
94 {
95     if (vq->flags & VIRTQUEUE_FLAG_EVENT_IDX) {
96         uint16_t *used_event = vring_get_used_event(&vq->vring);
97         *used_event = vq->used_tail + num_desc;
98     } else {
99         vq->vring.avail->flags &= ~VIRTIO_RING_AVAIL_F_NO_INTERRUPT;
100     }
101
102     assert(!"NYI: memory barrier mb()");
103
104     if (virtio_virtqueue_get_num_used(vq) > num_desc) {
105         return 1;
106     }
107
108     return 0;
109 }
110
111
112 /**
113  * \brief initializes the vring structure of the virtqueue
114  *
115  * \param vq virtqueue of the vring to initialize
116  */
117 static void virtqueue_init_vring(struct virtqueue *vq)
118 {
119     struct vring *vr = &vq->vring;
120
121     assert(vq);
122     assert(vq->vring_ndesc);
123     assert(vq->vring_vaddr);
124
125     /*
126      * initialize the vring structure in memory
127      */
128     vring_init(vr, vq->vring_ndesc, vq->vring_align, (void *)vq->vring_vaddr);
129
130     /*
131      * initialize the descriptor chains
132      */
133     uint32_t i;
134     for (i = 0; i < vq->vring_ndesc; ++i) {
135         vr->desc[i].next = i+1;
136     }
137     vr->desc[i].next = VIRTQUEUE_CHAIN_END;
138
139 }
140
141
142 /*
143  * ============================================================================
144  * Public Interface
145  * ============================================================================
146  */
147
148
149 /*
150  * ----------------------------------------------------------------------------
151  *  Virtqueue Allocation / Deallocation
152  */
153
154 /**
155  * \brief allocates and initiates a new virtqueue structure
156  *
157  * \param setup  pointer to the setup information
158  * \param vq     pointer where to store the new virtqueue pointer
159  *
160  * \returns SYS_ERR_OK on success
161  */
162 errval_t virtio_virtqueue_alloc(struct virtqueue_setup *setup,
163                                 struct virtqueue **vq)
164 {
165     errval_t err;
166
167     assert(vq);
168
169     if (setup->vring_ndesc == 0 || !IS_POW2(setup->vring_ndesc)) {
170         VIRTIO_DEBUG_VQ("ERROR: invalid size: %u\n", setup->vring_ndesc);
171         return VIRTIO_ERR_SIZE_INVALID;
172     }
173
174     size_t size = vring_size(setup->vring_ndesc, setup->vring_align);
175     size = ROUND_UP(size, BASE_PAGE_SIZE);
176
177     struct capref vring_cap;
178     size_t framesize;
179     err = frame_alloc(&vring_cap, size, &framesize);
180     if (err_is_fail(err)) {
181         return err;
182     }
183
184     VIRTIO_DEBUG_VQ("Allocated memory for vring: [%lx & %lx]",
185                     (uint64_t)size, (uint64_t)framesize);
186
187     err = virtio_virtqueue_alloc_with_caps(setup, vring_cap, vq);
188     if (err_is_fail(err)) {
189         cap_destroy(vring_cap);
190         return err;
191     }
192
193     return SYS_ERR_OK;
194 }
195
196 /**
197  * \brief allocates and initiates a new virtqueue structure
198  *
199  * \param setup     pointer to the setup information
200  * \param vring_cap capability to be used for the vring
201  * \param vq        pointer where to store the new virtqueue pointer
202  *
203  * \returns SYS_ERR_OK on success
204  */
205 errval_t virtio_virtqueue_alloc_with_caps(struct virtqueue_setup *setup,
206                                           struct capref vring_cap,
207                                           struct virtqueue **ret_vq)
208 {
209     errval_t err;
210
211     assert(ret_vq);
212
213     if (setup->vring_ndesc == 0 || !IS_POW2(setup->vring_ndesc)) {
214         VIRTIO_DEBUG_VQ("ERROR: invalid size: %u\n", setup->vring_ndesc);
215         return VIRTIO_ERR_SIZE_INVALID;
216     }
217
218     if (setup->max_indirect > VIRTIO_RING_MAX_INDIRECT) {
219         VIRTIO_DEBUG_VQ("ERROR: too many indirect descriptors requested: [%u / %u]\n", setup->vring_ndesc, VIRTIO_RING_MAX_INDIRECT);
220         return VIRTIO_ERR_MAX_INDIRECT;
221     }
222
223     assert(!capref_is_null(vring_cap));
224
225     struct frame_identity id;
226     err = invoke_frame_identify(vring_cap, &id);
227     if (err_is_fail(err)) {
228         return err;
229     }
230
231     size_t vring_mem_size = vring_size(setup->vring_ndesc, setup->vring_align);
232     vring_mem_size = ROUND_UP(vring_mem_size, BASE_PAGE_SIZE);
233
234     if (vring_mem_size > (1UL << id.bits)) {
235         VIRTIO_DEBUG_VQ("ERROR: supplied cap was too small %lx, needed %lx\n",
236                         ((1UL << id.bits)), (uint64_t)vring_mem_size);
237         return VIRTIO_ERR_CAP_SIZE;
238     }
239
240     void *vring_addr;
241     err = vspace_map_one_frame(&vring_addr, vring_mem_size, vring_cap, NULL, NULL);
242     if (err_is_fail(err)) {
243         return err;
244     }
245
246     struct virtqueue *vq = calloc(1, sizeof(struct virtqueue)
247                                   + (setup->vring_ndesc * sizeof(struct vring_desc_info)));
248     if (vq == NULL) {
249         vspace_unmap(vring_addr);
250         return LIB_ERR_MALLOC_FAIL;
251     }
252
253     vq->device = setup->device;
254     strncpy(vq->name, setup->name, sizeof(vq->name));
255     vq->queue_index = setup->queue_id;
256     vq->vring_ndesc = setup->vring_ndesc;
257     vq->vring_align = setup->vring_align;
258     vq->vring_size = vring_mem_size;
259     vq->vring_cap = vring_cap;
260     vq->vring_paddr = id.base;
261     vq->vring_vaddr = (lvaddr_t)vring_addr;
262     vq->free_count = setup->vring_ndesc;
263
264
265     vq->intr_handler = setup->intr_handler;
266     vq->intr_arg = setup->intr_arg;
267
268     if (setup->max_indirect > 0) {
269         /*
270          * TODO: initialize indirect descriptors
271          */
272     }
273
274 #if 0
275     if (VIRTIO_BUS_WITH_FEATURE(dev, VIRTIO_RING_F_EVENT_IDX) != 0)
276         vq->vq_flags |= VIRTQUEUE_FLAG_EVENT_IDX;
277 #endif
278
279     virtqueue_init_vring(vq);
280     virtio_virtqueue_intr_disable(vq);
281
282     if (ret_vq) {
283         *ret_vq = vq;
284     }
285
286     return SYS_ERR_OK;
287 }
288
289
290 /**
291  * \brief frees the resources of previously allocated virtqueues
292  *
293  * \param vq pointer to the virtqueue memory to be freed
294  *
295  * \returns SYS_ERR_OK on success
296  */
297 errval_t virtio_virtqueue_free(struct virtqueue *vq)
298 {
299     assert(!"NYI: virtio_virtqueue_free");
300
301     return SYS_ERR_OK;
302 }
303
304 /*
305  * ----------------------------------------------------------------------------
306  *  Virtqueue Getter Functions
307  */
308
309 /**
310  * \brief Returns the physical address of the vring.
311  *
312  * \param vq pointer to the virtqueue structure
313  *
314  * \returns the physical address of the vring
315  */
316 lpaddr_t virtio_virtqueue_get_vring_paddr(struct virtqueue *vq)
317 {
318     return vq->vring_paddr;
319 }
320
321 /**
322  * \brief returns the alignment of the vring
323  *
324  * \param the virtqueue to get the alignment from
325  *
326  * \returns vring alignment
327  */
328 lvaddr_t virtio_virtqueue_get_vring_align(struct virtqueue *vq)
329 {
330     return vq->vring_align;
331 }
332
333 /**
334  * \brief Returns the frame capability of the vring
335  *
336  * \param vq        pointer to the virtqueue structure
337  * \param ret_cap   memory location where to store the capref
338  */
339 void virtio_virtqueue_get_vring_cap(struct virtqueue *vq,
340                                     struct capref *ret_cap)
341 {
342     if (ret_cap) {
343         *ret_cap = vq->vring_cap;
344     }
345 }
346
347 /**
348  * \brief Returns the number of elements (number of descriptors)in the vring of
349  *        this virtqueue
350  *
351  * \param vq pointer to the virtqueue structure
352  *
353  * \returns number of elements in the vring
354  */
355 uint16_t virtio_virtqueue_get_num_desc(struct virtqueue *vq)
356 {
357     return vq->vring_ndesc;
358 }
359
360 /**
361  * \brief Returns the queue index of the virtqueue of the device
362  *
363  * \param vq pointer to the virtqueue structure
364  *
365  * \returns queue index
366  */
367 uint16_t virtio_virtqueue_get_queue_index(struct virtqueue *vq)
368 {
369     return vq->queue_index;
370 }
371
372
373 /**
374  * \brief Checks if the virtqueue is empty
375  *
376  * \param vq pointer to the virtqueue structure
377  *
378  * \returns 0 the queue is not empty
379  *          1 the queue is empty
380  */
381 bool virtio_virtqueue_is_empty(struct virtqueue *vq)
382 {
383     return (vq->vring_ndesc == vq->free_count);
384 }
385
386 /**
387  * \brief Checks if the virtqueue is full
388  *
389  * \param vq pointer to the virtqueue structure
390  *
391  * \returns 0 the queue is not full
392  *          1 the queue is full
393  */
394 bool virtio_virtqueue_is_full(struct virtqueue *vq)
395 {
396     return (vq->free_count == 0);
397 }
398
399 /**
400  * \brief Calculates the number of used descriptors in this queue
401  *
402  * \param vq pointer to the virtqueue structure
403  *
404  * \returns number of used descriptors
405  */
406 uint16_t virtio_virtqueue_get_num_used(struct virtqueue *vq)
407 {
408     uint16_t num_used;
409
410     num_used = vq->vring.used->idx - vq->used_tail;
411
412     /* sanity check */
413     assert(num_used <= vq->vring_ndesc);
414
415     return num_used;
416 }
417
418 /*
419  * ----------------------------------------------------------------------------
420  *  Interrupt handling
421  */
422
423 /**
424  * \brief checks if the interrupts can be disabled
425  *
426  * \param vq virtual queue to check
427  *
428  * \returns 1 if the interrupts have been disabled
429  *          0 if the interrupts are not changed
430  *
431  */
432 bool virtio_virtqueue_intr_filter(struct virtqueue *vq)
433 {
434     if (vq->used_tail == vq->vring.used->idx) {
435         return 0;
436     }
437
438     virtio_virtqueue_intr_disable(vq);
439
440     return 1;
441 }
442
443 /**
444  * \brief calls the interrupt handler for this virtqueue
445  *
446  * \param vq virtqueue to call the intr handler for
447  */
448 void virtio_virtqueue_intr_handle(struct virtqueue *vq)
449 {
450     if (vq->intr_handler == NULL) {
451         VIRTIO_DEBUG_VQ("Notice: Interrupt handler is not set\n");
452         return;
453     }
454     vq->intr_handler(vq, vq->intr_arg);
455 }
456
457
458 /**
459  * \brief enables the interrupts on the next descriptor processed
460  *
461  * \param vq the virtqueue to enable the interrupts
462  *
463  * \returns 1 if the interrupts have been enabled
464  *          0 if the interrupts have not been enabled
465  */
466 bool virtio_virtqueue_intr_enable(struct virtqueue *vq)
467 {
468     return virtqueue_interrupt_enable(vq, 0);
469 }
470
471 /**
472  * \brief postpones the interrupt to a later point of time
473  *
474  * \param vq the virtqueue to enable the interrupts
475  * \param
476  *
477  * \returns 1 if the interrupts have been enabled
478  *          0 if the interrupts have not been enabled
479  */
480 bool virtio_virtqueue_intr_postpone(struct virtqueue *vq,
481                                     enum virtqueue_intr_postpone hint)
482 {
483     uint16_t ndesc = vq->vring.avail->idx - vq->used_tail;
484
485     switch (hint) {
486         case VIRTQUEUE_INTR_POSTPONE_SHORT:
487             ndesc = ndesc / 4;
488             break;
489         case VIRTQUEUE_INTR_POSTPONE_LONG:
490             ndesc = (ndesc * 3) / 4;
491             break;
492         case VIRTQUEUE_INTR_POSTPONE_EMPTIED:
493             break;
494     }
495
496     return virtqueue_interrupt_enable(vq, ndesc);
497 }
498
499
500 /**
501  * \brief disables the interrupts for the given virtqueue
502  *
503  * \param vq        virtqueue to disable the interrupts
504  */
505 void virtio_virtqueue_intr_disable(struct virtqueue *vq)
506 {
507     if (vq->flags & VIRTQUEUE_FLAG_EVENT_IDX) {
508         uint16_t *used_event = vring_get_used_event(&vq->vring);
509         *used_event = vq->used_tail - vq->vring_ndesc - 1;
510     } else {
511         vq->vring.avail->flags |= VIRTIO_RING_AVAIL_F_NO_INTERRUPT;
512     }
513 }
514
515 /**
516  * \brief notifies the host about the new queued descriptors
517  *
518  * \param vq virtqueue to notify the host
519  */
520 void virtio_virtqueue_notify_host(struct virtqueue *vq)
521 {
522     assert(!"NYI: host notify");
523 }
524
525
526 /*
527  * We layout the vring structure in memory as follows:
528  *
529  * struct vring {
530  *      // The actual descriptors (16 bytes each)
531  *      struct vring_desc desc[num];
532  *
533  *      // A ring of available descriptor heads with free-running index.
534  *      uint16_t avail_flags;
535  *      uint16_t avail_idx;
536  *      uint16_t available[num];
537  *      uint16_t used_event_idx;
538  *
539  *      // Padding to the next align boundary.
540  *      char pad[];
541  *
542  *      // A ring of used descriptor heads with free-running index.
543  *      uint16_t used_flags;
544  *      uint16_t used_idx;
545  *      struct vring_used_elem used[num];
546  *      uint16_t avail_event_idx;
547  * };
548  */
549
550 /**
551  * \brief Maps the given capability and initializes the vring on the memory
552  *        backed by the supplied capability
553  *
554  * \param vr    pointer to the vring structure to be initialized
555  * \param num   the number of elements in the ring
556  * \param align alignment constraints for the vring
557  * \param cap   frame capability used as backing memory for the structure
558  *
559  * \return SYS_ERR_OK on success
560  *         errno      on failure
561  */
562 errval_t vring_init_from_cap(struct vring *vr,
563                              uint16_t num,
564                              uintptr_t align,
565                              struct capref cap)
566 {
567     errval_t err;
568
569     /* num must be a power of two */
570     assert(((num != 0) && ((num & (~num + 1)) == num)));
571
572     size_t size = vring_size(num, align);
573
574     struct frame_identity id;
575     err = invoke_frame_identify(cap, &id);
576     if (err_is_fail(err)) {
577         return err_push(err, LIB_ERR_FRAME_IDENTIFY);
578     }
579
580     /* check if we have enough space in the given cap */
581     if ((1UL << id.bits) < size) {
582         return SYS_ERR_INVALID_SIZE_BITS;
583     }
584
585     void *addr;
586     err = vspace_map_one_frame(&addr, (1UL << id.bits), cap, NULL, NULL);
587     if (err_is_fail(err)) {
588         return err_push(err, LIB_ERR_VSPACE_MAP);
589     }
590
591     vring_init(vr, num, align, addr);
592
593     return SYS_ERR_OK;
594 }
595
596 /**
597  * \brief allocates a new vring structure
598  *
599  * \param vr        pointer to the vring structure
600  * \param num       the number of queue elements
601  * \param align     the alignment constraints for the vring
602  * \param ret_frame returned frame capability
603  *
604  * \return SYS_ERR_OK on success
605  *         errno      on failure
606  */
607 errval_t vring_alloc(struct vring *vr,
608                      uint16_t num,
609                      uintptr_t align,
610                      struct capref *ret_frame)
611 {
612     errval_t err;
613
614     /* num must be a power of two */
615     assert(((num != 0) && ((num & (~num + 1)) == num)));
616
617     size_t size = vring_size(num, align);
618
619     struct capref frame;
620     err = frame_alloc(&frame, size, &size);
621     if (err_is_fail(err)) {
622         return err;
623     }
624
625     err = vring_init_from_cap(vr, num, align, frame);
626     if (err_is_fail(err)) {
627         return err;
628     }
629
630     if (ret_frame) {
631         *ret_frame = frame;
632     }
633
634     return SYS_ERR_OK;
635 }
636
637 /**
638  * \brief frees the resources used by the vring structure
639  *
640  * \param vr the vring to be freed
641  *
642  * \return SYS_ERR_OK on success
643  *         errno      on failure
644  */
645 errval_t vring_free(struct vring *vr)
646 {
647     errval_t err;
648
649     err = vspace_unmap(vr->desc);
650     if (err_is_fail(err)) {
651         return err;
652     }
653
654     assert(!"NYI: returning the cap to the origin");
655     return SYS_ERR_OK;
656 }
657
658 /*
659  * ----------------------------------------------------------------------------
660  *  Queue Management
661  */
662
663 #if 0
664
665 /**
666  *
667  */
668 errval_t virtio_virtqueue_desc_alloc(struct virtqueue *vq,
669                                      size_t )
670
671 errval_t virtio_virtqueue_desc_enq(struct virtqueue *vq,
672                               )
673 {
674     assert(!"NYI: virtio_virtqueue_enq");
675     return SYS_ERR_OK;
676 }
677
678 void *virtio_virtqueue_desc_deq(struct virtqueue *vq)
679 {
680     return NULL;
681 }
682
683
684
685 void *virtio_virtqueue_poll(struct virtqueue *vq)
686 {
687     return NULL;
688 };
689
690 #endif
691