1 /*
2  * Copyright (c) 2013-2014, Google, Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #ifndef _LIB_TRUSTY_VQUEUE_H
25 #define _LIB_TRUSTY_VQUEUE_H
26 
27 #include <arch/ops.h>
28 #include <kernel/event.h>
29 #include <kernel/mutex.h>
30 #include <lib/extmem/extmem.h>
31 #include <lib/trusty/uio.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <sys/types.h>
35 
36 #include <virtio/virtio_ring.h>
37 
38 struct vqueue;
39 typedef int (*vqueue_cb_t)(struct vqueue* vq, void* priv);
40 
41 struct vqueue {
42     uint32_t id;
43 
44     struct vring vring;
45     vaddr_t vring_addr;
46     size_t vring_sz;
47 
48     spin_lock_t slock;
49 
50     uint16_t last_avail_idx;
51 
52     event_t avail_event;
53 
54     /* called when the vq is kicked *from* the other side */
55     vqueue_cb_t notify_cb;
56 
57     /* called when we want to kick the other side */
58     vqueue_cb_t kick_cb;
59 
60     void* priv;
61 };
62 
63 struct vqueue_iovs {
64     uint cnt;   /* max number of iovs available */
65     uint used;  /* number of iovs currently in use */
66     size_t len; /* total length of all used iovs */
67     ext_mem_obj_id_t* shared_mem_id;
68     struct iovec_kern* iovs;
69 };
70 
71 struct vqueue_buf {
72     uint16_t head;
73     uint16_t padding;
74     struct vqueue_iovs in_iovs;
75     struct vqueue_iovs out_iovs;
76 };
77 
78 struct vqueue_mapped_list {
79     struct bst_root list;
80     mutex_t lock;
81     bool in_direction;
82 };
83 
84 int vqueue_init(struct vqueue* vq,
85                 uint32_t id,
86                 ext_mem_client_id_t client_id,
87                 ext_mem_obj_id_t shared_mem_id,
88                 uint num,
89                 ulong align,
90                 void* priv,
91                 vqueue_cb_t notify_cb,
92                 vqueue_cb_t kick_cb);
93 
94 void vqueue_destroy(struct vqueue* vq);
95 
96 int vqueue_get_avail_buf(struct vqueue* vq, struct vqueue_buf* iovbuf);
97 
98 int vqueue_map_iovs(ext_mem_client_id_t client_id,
99                     struct vqueue_iovs* vqiovs,
100                     u_int flags,
101                     struct vqueue_mapped_list* mapped_list);
102 void vqueue_unmap_iovs(struct vqueue_iovs* vqiovs,
103                        struct vqueue_mapped_list* mapped_list);
104 
105 int vqueue_unmap_memid(ext_mem_obj_id_t id,
106                        struct vqueue_mapped_list* mapped_list[],
107                        int list_cnt);
108 
109 int vqueue_add_buf(struct vqueue* vq, struct vqueue_buf* buf, uint32_t len);
110 
111 void vqueue_signal_avail(struct vqueue* vq);
112 
vqueue_id(struct vqueue * vq)113 static inline uint32_t vqueue_id(struct vqueue* vq) {
114     return vq->id;
115 }
116 
vqueue_notify(struct vqueue * vq)117 static inline int vqueue_notify(struct vqueue* vq) {
118     if (vq->notify_cb)
119         return vq->notify_cb(vq, vq->priv);
120     return 0;
121 }
122 
vqueue_kick(struct vqueue * vq)123 static inline int vqueue_kick(struct vqueue* vq) {
124     if (vq->kick_cb)
125         return vq->kick_cb(vq, vq->priv);
126     return 0;
127 }
128 
129 #endif /* _LIB_TRUSTY_VQUEUE_H */
130