1 /*
2 * Copyright (c) 2013-2018, 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 #pragma once
25
26 #include <list.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <sys/types.h>
30
31 #include <kernel/event.h>
32 #include <kernel/mutex.h>
33 #include <kernel/usercopy.h>
34
35 #include <lib/trusty/refcount.h>
36
37 __BEGIN_CDECLS
38
39 /* bitmask */
40 enum {
41 IPC_HANDLE_POLL_NONE = 0x0,
42 IPC_HANDLE_POLL_READY = 0x1,
43 IPC_HANDLE_POLL_ERROR = 0x2,
44 IPC_HANDLE_POLL_HUP = 0x4,
45 IPC_HANDLE_POLL_MSG = 0x8,
46 IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10,
47 };
48
49 enum handle_flags {
50 HANDLE_FLAG_NO_SEND = (1U << 0),
51 };
52
53 struct handle_ops;
54
55 struct handle {
56 struct refcount refcnt;
57 uint32_t flags;
58
59 struct handle_ops* ops;
60
61 /* pointer to a wait queue on which threads wait for events for this
62 * handle.
63 */
64 event_t* wait_event;
65 spin_lock_t slock;
66
67 struct list_node hlist_node;
68 struct list_node waiter_list;
69
70 void* cookie;
71 };
72
73 struct handle_waiter {
74 struct list_node node;
75 void (*notify_proc)(struct handle_waiter*);
76 };
77
78 struct handle_event_waiter {
79 struct handle_waiter waiter;
80 struct event event;
81 };
82
handle_event_waiter_notify(struct handle_waiter * hw)83 static void handle_event_waiter_notify(struct handle_waiter* hw) {
84 struct handle_event_waiter* hew;
85 hew = containerof(hw, struct handle_event_waiter, waiter);
86 event_signal(&hew->event, false);
87 }
88
89 #define HANDLE_EVENT_WAITER_INITIAL_VALUE(ew) \
90 { \
91 .waiter = {.node = LIST_INITIAL_CLEARED_VALUE, \
92 .notify_proc = handle_event_waiter_notify}, \
93 .event = EVENT_INITIAL_VALUE((ew).event, false, \
94 EVENT_FLAG_AUTOUNSIGNAL), \
95 }
96
97 /**
98 * struct handle_ref - struct representing handle reference
99 * @set_node: list node used with set_list of handle_set struct
100 * @ready_node: list node used with ready_list of handle_set struct
101 * @uctx_node: list node used with ref_lists of uctx struct
102 * @waiter: used with waiter_list of handle struct
103 * @parent: pointer to parent handle set if any
104 * @handle: pointer to underlying handle struct
105 * @id: corresponds to handle field in uevent struct
106 * @emask: event mask
107 * @cookie: corresponds to cookie field in uevent struct
108 */
109 struct handle_ref {
110 struct list_node set_node;
111 struct list_node ready_node;
112 struct list_node uctx_node;
113 struct handle_waiter waiter;
114 struct handle* parent;
115 struct handle* handle;
116 uint32_t id;
117 uint32_t emask;
118 void* cookie;
119 };
120
121 struct handle_ops {
122 uint32_t (*poll)(struct handle* handle, uint32_t emask, bool finalize);
123 void (*shutdown)(struct handle* handle);
124 void (*destroy)(struct handle* handle);
125 ssize_t (*user_writev)(struct handle* handle,
126 user_addr_t iov_uaddr,
127 uint32_t iov_cnt);
128 ssize_t (*user_readv)(struct handle* handle,
129 user_addr_t iov_uaddr,
130 uint32_t iov_cnt);
131 status_t (*mmap)(struct handle* handle,
132 size_t offset,
133 user_size_t size,
134 uint32_t mmap_prot,
135 user_addr_t* addr);
136 };
137
138 struct handle_list {
139 struct list_node handles;
140 mutex_t lock;
141 event_t* wait_event;
142 };
143
144 #define HANDLE_LIST_INITIAL_VALUE(hs) \
145 { \
146 .handles = LIST_INITIAL_VALUE((hs).handles), \
147 .lock = MUTEX_INITIAL_VALUE((hs).lock), \
148 }
149
150 /* handle management */
151 void handle_init_etc(struct handle* handle,
152 struct handle_ops* ops,
153 uint32_t flags);
154
handle_init(struct handle * handle,struct handle_ops * ops)155 static inline void handle_init(struct handle* handle, struct handle_ops* ops) {
156 handle_init_etc(handle, ops, 0);
157 }
158 void handle_close(struct handle* handle);
159
160 void handle_incref(struct handle* handle);
161 void handle_decref(struct handle* handle);
162
163 void handle_add_waiter(struct handle* h, struct handle_waiter* w);
164 void handle_del_waiter(struct handle* h, struct handle_waiter* w);
165
166 int handle_wait(struct handle* handle,
167 uint32_t* handle_event,
168 lk_time_t timeout);
169 int handle_ref_wait(const struct handle_ref* in,
170 struct handle_ref* out,
171 lk_time_t timeout);
172 void handle_notify(struct handle* handle);
173 void handle_notify_waiters_locked(struct handle* handle);
174
handle_set_cookie(struct handle * handle,void * cookie)175 static inline void handle_set_cookie(struct handle* handle, void* cookie) {
176 handle->cookie = cookie;
177 }
178
handle_get_cookie(struct handle * handle)179 static inline void* handle_get_cookie(struct handle* handle) {
180 return handle->cookie;
181 }
182
183 void handle_list_init(struct handle_list* hlist);
184 void handle_list_add(struct handle_list* hlist, struct handle* handle);
185 void handle_list_del(struct handle_list* hlist, struct handle* handle);
186 void handle_list_delete_all(struct handle_list* hlist);
187 int handle_list_wait(struct handle_list* hlist,
188 struct handle** handle_ptr,
189 uint32_t* event_ptr,
190 lk_time_t timeout);
191
handle_is_sendable(struct handle * h)192 static inline bool handle_is_sendable(struct handle* h) {
193 return !(h->flags & HANDLE_FLAG_NO_SEND);
194 }
195
196 status_t handle_mmap(struct handle* handle,
197 size_t offset,
198 user_size_t size,
199 uint32_t mmap_prot,
200 user_addr_t* addr);
201
202 __END_CDECLS
203