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