• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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