1 /**
2 * \file
3 * Common task related definitions.
4 */
5 /*
6 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
7 * Alexander Warg <warg@os.inf.tu-dresden.de>,
8 * Björn Döbel <doebel@os.inf.tu-dresden.de>,
9 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
10 * economic rights: Technische Universität Dresden (Germany)
11 *
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU General Public License 2.
14 * Please see the COPYING-GPL-2 file for details.
15 *
16 * As a special exception, you may use this file as part of a free software
17 * library without restriction. Specifically, if other files instantiate
18 * templates or use macros or inline functions from this file, or you compile
19 * this file and link it with other files to produce an executable, this
20 * file does not by itself cause the resulting executable to be covered by
21 * the GNU General Public License. This exception does not however
22 * invalidate any other reasons why the executable file might be covered by
23 * the GNU General Public License.
24 */
25 #pragma once
26 #include <l4/sys/types.h>
27 #include <l4/sys/utcb.h>
28
29 /**
30 * \defgroup l4_task_api Task
31 * \ingroup l4_kernel_object_api
32 * C interface of the Task kernel object, see L4::Task for the C++ interface.
33 *
34 * A task represents a combination of the address spaces provided
35 * by the L4Re micro kernel. A task consists of at least a memory address space
36 * and an object address space. On IA32 there is also an IO-port address space.
37 *
38 * Task objects are created using the \ref l4_factory_api interface.
39 *
40 * \includefile{l4/sys/task.h}
41 */
42
43 /**
44 * Map resources available in the source task to a destination task.
45 * \ingroup l4_task_api
46 *
47 * \param dst_task Capability selector of destination task
48 * \param src_task Capability selector of source task
49 * \param snd_fpage Send flexpage that describes an area in the
50 * address space or object space of the source task.
51 * \param snd_base Send base that describes an offset in the receive
52 * window of the destination task.
53 *
54 * \return Syscall return tag
55 *
56 * This method allows for asynchronous transfer of capabilities, memory
57 * mappings, and IO-port mappings (on IA32) from one task to another.
58 * The receive window is the whole address space of `dst_task`.
59 *
60 * For more information on spaces and mappings, see
61 * \ref l4re_concepts_mapping. The flexpage API is described in more detail at
62 * \ref l4_fpage_api.
63 */
64 L4_INLINE l4_msgtag_t
65 l4_task_map(l4_cap_idx_t dst_task, l4_cap_idx_t src_task,
66 l4_fpage_t snd_fpage, l4_umword_t snd_base) L4_NOTHROW;
67
68 /**
69 * \internal
70 */
71 L4_INLINE l4_msgtag_t
72 l4_task_map_u(l4_cap_idx_t dst_task, l4_cap_idx_t src_task,
73 l4_fpage_t snd_fpage, l4_umword_t snd_base, l4_utcb_t *utcb) L4_NOTHROW;
74
75 /**
76 * Revoke rights from the task.
77 * \ingroup l4_task_api
78 *
79 * \param task Capability selector of destination task
80 * \param fpage Flexpage that describes an area in one capability space
81 * of the destination task
82 * \param map_mask Unmap mask, see #l4_unmap_flags_t
83 *
84 * \return Syscall return tag
85 *
86 * This method allows to revoke rights from the destination task. For a flex
87 * page describing IO ports or memory, it also revokes rights from all the
88 * tasks that got the rights delegated from the destination task (i.e., this
89 * operation does a recursive rights revocation). If the set of rights is empty
90 * after the revocation, the capability is unmapped.
91 *
92 * \note If the reference counter of a kernel object referenced in `fpage`
93 * goes down to zero (as a result of deleting capabilities), the deletion
94 * of the object is initiated. Objects are not destroyed until all other
95 * kernel objects holding a reference to it drop the reference.
96 */
97 L4_INLINE l4_msgtag_t
98 l4_task_unmap(l4_cap_idx_t task, l4_fpage_t fpage,
99 l4_umword_t map_mask) L4_NOTHROW;
100
101 /**
102 * \internal
103 */
104 L4_INLINE l4_msgtag_t
105 l4_task_unmap_u(l4_cap_idx_t task, l4_fpage_t fpage,
106 l4_umword_t map_mask, l4_utcb_t *utcb) L4_NOTHROW;
107
108 /**
109 * Revoke rights from a task.
110 * \ingroup l4_task_api
111 *
112 * \param task Capability selector of destination task
113 * \param fpages An array of flexpages. Each item describes an area in
114 * one capability space of the destination task.
115 * \param num_fpages The size of the fpages array in elements (number of
116 * fpages sent).
117 * \param map_mask Unmap mask, see #l4_unmap_flags_t
118 *
119 * \return Syscall return tag
120 *
121 * Revoke rights specified in an array of flexpages, see #l4_task_unmap for
122 * details.
123 *
124 * \pre The caller needs to take care that num_fpages is not bigger
125 * than L4_UTCB_GENERIC_DATA_SIZE - 2.
126 */
127 L4_INLINE l4_msgtag_t
128 l4_task_unmap_batch(l4_cap_idx_t task, l4_fpage_t const *fpages,
129 unsigned num_fpages, l4_umword_t map_mask) L4_NOTHROW;
130
131 /**
132 * \internal
133 */
134 L4_INLINE l4_msgtag_t
135 l4_task_unmap_batch_u(l4_cap_idx_t task, l4_fpage_t const *fpages,
136 unsigned num_fpages, l4_umword_t map_mask,
137 l4_utcb_t *u) L4_NOTHROW;
138
139 /**
140 * Release capability and delete object.
141 * \ingroup l4_task_api
142 *
143 * \param task Capability selector of destination task
144 * \param obj Capability selector of object to delete
145 *
146 * \return Syscall return tag
147 *
148 * Initiates the deletion of the object if `obj` has the delete permission.
149 * Objects are not destroyed until all other kernel objects holding a reference
150 * to it drop the reference. No error will be reported if the rights are
151 * insufficient, however, the capability is removed in all cases from the
152 * destination task.
153 *
154 * This operation calls l4_task_unmap() with #L4_FP_DELETE_OBJ.
155 */
156 L4_INLINE l4_msgtag_t
157 l4_task_delete_obj(l4_cap_idx_t task, l4_cap_idx_t obj) L4_NOTHROW;
158
159 /**
160 * \internal
161 */
162 L4_INLINE l4_msgtag_t
163 l4_task_delete_obj_u(l4_cap_idx_t task, l4_cap_idx_t obj,
164 l4_utcb_t *u) L4_NOTHROW;
165
166 /**
167 * Release object capability.
168 * \ingroup l4_task_api
169 *
170 * \param task Capability selector of destination task
171 * \param cap Capability selector of object to release
172 *
173 * \return Syscall return tag
174 *
175 * This operation unmaps the capability from the specified task.
176 *
177 * \note If the reference counter of the kernel object referenced by `cap`
178 * goes down to zero, deletion of the object is initiated. Objects are not
179 * destroyed until all other kernel objects holding a reference to it drop
180 * the reference.
181 */
182 L4_INLINE l4_msgtag_t
183 l4_task_release_cap(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW;
184
185 /**
186 * \internal
187 */
188 L4_INLINE l4_msgtag_t
189 l4_task_release_cap_u(l4_cap_idx_t task, l4_cap_idx_t cap,
190 l4_utcb_t *u) L4_NOTHROW;
191
192
193 /**
194 * Check whether a capability is present (refers to an object).
195 * \ingroup l4_task_api
196 *
197 * \param task Task to check the capability in.
198 * \param cap Valid capability to check for presence.
199 *
200 * \retval tag.label() > 0 Capability is present (refers to an object).
201 * \retval tag.label() == 0 No capability present (void object).
202 *
203 * A capability is considered present when it refers to an existing
204 * kernel object.
205 *
206 * \pre `cap` must be a valid capability index (i.e. not L4_INVALID_CAP or
207 * the like).
208 */
209 L4_INLINE l4_msgtag_t
210 l4_task_cap_valid(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW;
211
212 /**
213 * \internal
214 */
215 L4_INLINE l4_msgtag_t
216 l4_task_cap_valid_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW;
217
218 /**
219 * Test whether two capabilities point to the same object with the same
220 * rights.
221 * \ingroup l4_task_api
222 *
223 * \param task Capability selector of the destination task to do the
224 * lookup in
225 * \param cap_a Capability selector to compare
226 * \param cap_b Capability selector to compare
227 *
228 * \return label contains 1 if equal, 0 if not equal
229 */
230 L4_INLINE l4_msgtag_t
231 l4_task_cap_equal(l4_cap_idx_t task, l4_cap_idx_t cap_a,
232 l4_cap_idx_t cap_b) L4_NOTHROW;
233
234 /**
235 * \internal
236 */
237 L4_INLINE l4_msgtag_t
238 l4_task_add_ku_mem_u(l4_cap_idx_t task, l4_fpage_t ku_mem,
239 l4_utcb_t *u) L4_NOTHROW;
240
241 /**
242 * Add kernel-user memory.
243 * \ingroup l4_task_api
244 *
245 * \param task Capability selector of the task to add the memory to
246 * \param ku_mem Flexpage describing the virtual area the memory goes to.
247 *
248 * \return Syscall return tag
249 */
250 L4_INLINE l4_msgtag_t
251 l4_task_add_ku_mem(l4_cap_idx_t task, l4_fpage_t ku_mem) L4_NOTHROW;
252
253
254 /**
255 * \internal
256 */
257 L4_INLINE l4_msgtag_t
258 l4_task_cap_equal_u(l4_cap_idx_t task, l4_cap_idx_t cap_a,
259 l4_cap_idx_t cap_b, l4_utcb_t *utcb) L4_NOTHROW;
260
261 /**
262 * Operations on task objects.
263 * \ingroup l4_protocol_ops
264 */
265 enum L4_task_ops
266 {
267 L4_TASK_MAP_OP = 0UL, /**< Map */
268 L4_TASK_UNMAP_OP = 1UL, /**< Unmap */
269 L4_TASK_CAP_INFO_OP = 2UL, /**< Cap info */
270 L4_TASK_ADD_KU_MEM_OP = 3UL, /**< Add kernel-user memory */
271 L4_TASK_LDT_SET_X86_OP = 0x11UL, /**< x86: LDT set */
272 L4_TASK_MAP_VGICC_ARM_OP = 0x12UL, /**< Arm: Map virtual GICC area */
273 };
274
275
276 /* IMPLEMENTATION -----------------------------------------------------------*/
277
278 #include <l4/sys/ipc.h>
279
280
281 L4_INLINE l4_msgtag_t
l4_task_map_u(l4_cap_idx_t dst_task,l4_cap_idx_t src_task,l4_fpage_t snd_fpage,l4_umword_t snd_base,l4_utcb_t * u)282 l4_task_map_u(l4_cap_idx_t dst_task, l4_cap_idx_t src_task,
283 l4_fpage_t snd_fpage, l4_umword_t snd_base, l4_utcb_t *u) L4_NOTHROW
284 {
285 l4_msg_regs_t *v = l4_utcb_mr_u(u);
286 v->mr[0] = L4_TASK_MAP_OP;
287 v->mr[3] = l4_map_obj_control(0,0);
288 v->mr[4] = l4_obj_fpage(src_task, 0, L4_CAP_FPAGE_RWS).raw;
289 v->mr[1] = snd_base;
290 v->mr[2] = snd_fpage.raw;
291 return l4_ipc_call(dst_task, u, l4_msgtag(L4_PROTO_TASK, 3, 1, 0), L4_IPC_NEVER);
292 }
293
294 L4_INLINE l4_msgtag_t
l4_task_unmap_u(l4_cap_idx_t task,l4_fpage_t fpage,l4_umword_t map_mask,l4_utcb_t * u)295 l4_task_unmap_u(l4_cap_idx_t task, l4_fpage_t fpage,
296 l4_umword_t map_mask, l4_utcb_t *u) L4_NOTHROW
297 {
298 l4_msg_regs_t *v = l4_utcb_mr_u(u);
299 v->mr[0] = L4_TASK_UNMAP_OP;
300 v->mr[1] = map_mask;
301 v->mr[2] = fpage.raw;
302 return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), L4_IPC_NEVER);
303 }
304
305 L4_INLINE l4_msgtag_t
l4_task_unmap_batch_u(l4_cap_idx_t task,l4_fpage_t const * fpages,unsigned num_fpages,l4_umword_t map_mask,l4_utcb_t * u)306 l4_task_unmap_batch_u(l4_cap_idx_t task, l4_fpage_t const *fpages,
307 unsigned num_fpages, l4_umword_t map_mask,
308 l4_utcb_t *u) L4_NOTHROW
309 {
310 l4_msg_regs_t *v = l4_utcb_mr_u(u);
311 v->mr[0] = L4_TASK_UNMAP_OP;
312 v->mr[1] = map_mask;
313 __builtin_memcpy(&v->mr[2], fpages, num_fpages * sizeof(l4_fpage_t));
314 return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2 + num_fpages, 0, 0), L4_IPC_NEVER);
315 }
316
317 L4_INLINE l4_msgtag_t
l4_task_cap_valid_u(l4_cap_idx_t task,l4_cap_idx_t cap,l4_utcb_t * u)318 l4_task_cap_valid_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *u) L4_NOTHROW
319 {
320 l4_msg_regs_t *v = l4_utcb_mr_u(u);
321 v->mr[0] = L4_TASK_CAP_INFO_OP;
322 v->mr[1] = cap & ~1UL;
323 return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2, 0, 0), L4_IPC_NEVER);
324 }
325
326 L4_INLINE l4_msgtag_t
l4_task_cap_equal_u(l4_cap_idx_t task,l4_cap_idx_t cap_a,l4_cap_idx_t cap_b,l4_utcb_t * u)327 l4_task_cap_equal_u(l4_cap_idx_t task, l4_cap_idx_t cap_a,
328 l4_cap_idx_t cap_b, l4_utcb_t *u) L4_NOTHROW
329 {
330 l4_msg_regs_t *v = l4_utcb_mr_u(u);
331 v->mr[0] = L4_TASK_CAP_INFO_OP;
332 v->mr[1] = cap_a;
333 v->mr[2] = cap_b;
334 return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), L4_IPC_NEVER);
335 }
336
337 L4_INLINE l4_msgtag_t
l4_task_add_ku_mem_u(l4_cap_idx_t task,l4_fpage_t ku_mem,l4_utcb_t * u)338 l4_task_add_ku_mem_u(l4_cap_idx_t task, l4_fpage_t ku_mem,
339 l4_utcb_t *u) L4_NOTHROW
340 {
341 l4_msg_regs_t *v = l4_utcb_mr_u(u);
342 v->mr[0] = L4_TASK_ADD_KU_MEM_OP;
343 v->mr[1] = ku_mem.raw;
344 return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2, 0, 0), L4_IPC_NEVER);
345 }
346
347
348
349 L4_INLINE l4_msgtag_t
l4_task_map(l4_cap_idx_t dst_task,l4_cap_idx_t src_task,l4_fpage_t snd_fpage,l4_umword_t snd_base)350 l4_task_map(l4_cap_idx_t dst_task, l4_cap_idx_t src_task,
351 l4_fpage_t snd_fpage, l4_umword_t snd_base) L4_NOTHROW
352 {
353 return l4_task_map_u(dst_task, src_task, snd_fpage, snd_base, l4_utcb());
354 }
355
356 L4_INLINE l4_msgtag_t
l4_task_unmap(l4_cap_idx_t task,l4_fpage_t fpage,l4_umword_t map_mask)357 l4_task_unmap(l4_cap_idx_t task, l4_fpage_t fpage,
358 l4_umword_t map_mask) L4_NOTHROW
359 {
360 return l4_task_unmap_u(task, fpage, map_mask, l4_utcb());
361 }
362
363 L4_INLINE l4_msgtag_t
l4_task_unmap_batch(l4_cap_idx_t task,l4_fpage_t const * fpages,unsigned num_fpages,l4_umword_t map_mask)364 l4_task_unmap_batch(l4_cap_idx_t task, l4_fpage_t const *fpages,
365 unsigned num_fpages, l4_umword_t map_mask) L4_NOTHROW
366 {
367 return l4_task_unmap_batch_u(task, fpages, num_fpages, map_mask,
368 l4_utcb());
369 }
370
371 L4_INLINE l4_msgtag_t
l4_task_delete_obj_u(l4_cap_idx_t task,l4_cap_idx_t obj,l4_utcb_t * u)372 l4_task_delete_obj_u(l4_cap_idx_t task, l4_cap_idx_t obj,
373 l4_utcb_t *u) L4_NOTHROW
374 {
375 return l4_task_unmap_u(task, l4_obj_fpage(obj, 0, L4_CAP_FPAGE_RWSD),
376 L4_FP_DELETE_OBJ, u);
377 }
378
379 L4_INLINE l4_msgtag_t
l4_task_delete_obj(l4_cap_idx_t task,l4_cap_idx_t obj)380 l4_task_delete_obj(l4_cap_idx_t task, l4_cap_idx_t obj) L4_NOTHROW
381 {
382 return l4_task_delete_obj_u(task, obj, l4_utcb());
383 }
384
385
386 L4_INLINE l4_msgtag_t
l4_task_release_cap_u(l4_cap_idx_t task,l4_cap_idx_t cap,l4_utcb_t * u)387 l4_task_release_cap_u(l4_cap_idx_t task, l4_cap_idx_t cap,
388 l4_utcb_t *u) L4_NOTHROW
389 {
390 return l4_task_unmap_u(task, l4_obj_fpage(cap, 0, L4_CAP_FPAGE_RWSD),
391 L4_FP_ALL_SPACES, u);
392 }
393
394 L4_INLINE l4_msgtag_t
l4_task_release_cap(l4_cap_idx_t task,l4_cap_idx_t cap)395 l4_task_release_cap(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW
396 {
397 return l4_task_release_cap_u(task, cap, l4_utcb());
398 }
399
400 L4_INLINE l4_msgtag_t
l4_task_cap_valid(l4_cap_idx_t task,l4_cap_idx_t cap)401 l4_task_cap_valid(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW
402 {
403 return l4_task_cap_valid_u(task, cap, l4_utcb());
404 }
405
406 L4_INLINE l4_msgtag_t
l4_task_cap_equal(l4_cap_idx_t task,l4_cap_idx_t cap_a,l4_cap_idx_t cap_b)407 l4_task_cap_equal(l4_cap_idx_t task, l4_cap_idx_t cap_a,
408 l4_cap_idx_t cap_b) L4_NOTHROW
409 {
410 return l4_task_cap_equal_u(task, cap_a, cap_b, l4_utcb());
411 }
412
413 L4_INLINE l4_msgtag_t
l4_task_add_ku_mem(l4_cap_idx_t task,l4_fpage_t ku_mem)414 l4_task_add_ku_mem(l4_cap_idx_t task, l4_fpage_t ku_mem) L4_NOTHROW
415 {
416 return l4_task_add_ku_mem_u(task, ku_mem, l4_utcb());
417 }
418