1 /**
2 * \file
3 * \brief Common factory related definitions.
4 * \ingroup l4_api
5 */
6 /*
7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8 * Alexander Warg <warg@os.inf.tu-dresden.de>,
9 * Björn Döbel <doebel@os.inf.tu-dresden.de>,
10 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>,
11 * Henning Schild <hschild@os.inf.tu-dresden.de>
12 * economic rights: Technische Universität Dresden (Germany)
13 *
14 * This file is part of TUD:OS and distributed under the terms of the
15 * GNU General Public License 2.
16 * Please see the COPYING-GPL-2 file for details.
17 *
18 * As a special exception, you may use this file as part of a free software
19 * library without restriction. Specifically, if other files instantiate
20 * templates or use macros or inline functions from this file, or you compile
21 * this file and link it with other files to produce an executable, this
22 * file does not by itself cause the resulting executable to be covered by
23 * the GNU General Public License. This exception does not however
24 * invalidate any other reasons why the executable file might be covered by
25 * the GNU General Public License.
26 */
27 #pragma once
28
29 #include <l4/sys/compiler.h>
30 #include <l4/sys/types.h>
31 #include <l4/sys/utcb.h>
32
33 /**
34 * \defgroup l4_factory_api Factory
35 * \ingroup l4_kernel_object_api
36 *
37 * C factory interface to create kernel objects.
38 *
39 * A factory is used to create all kinds of kernel objects:
40 * - \ref l4_task_api
41 * - \ref l4_thread_api
42 * - \ref l4_factory_api
43 * - \ref l4_kernel_object_gate_api
44 * - \ref l4_irq_api
45 * - \ref l4_vm_api
46 *
47 * To create a new kernel object the caller has to specify the factory to use
48 * for creation. The caller has to allocate a capability slot where the kernel
49 * stores the new object's capability.
50 *
51 * The factory is equipped with a limit that limits the amount of kernel
52 * memory available for that factory.
53 *
54 * \note The limit does not give any guarantee for the amount of available
55 * kernel memory.
56 *
57 * \includefile{l4/sys/factory.h}
58 *
59 * For the C++ interface refer to L4::Factory.
60 */
61
62 /**
63 * \defgroup l4_vm_api Virtual Machines
64 * \ingroup l4_kernel_object_api
65 * \brief Virtual Machine API
66 */
67
68 /**
69 * \ingroup l4_factory_api
70 * \copybrief L4::Factory::create_task
71 * \param factory Capability selector for factory to use for creation.
72 * \param[out] target_cap The kernel stores the new task's capability into
73 * this slot.
74 * \param utcb_area Flexpage that describes an area of kernel-user
75 * memory that can be used for UTCBs and vCPU
76 * state-save-areas of the new task.
77 *
78 * \return Syscall return tag.
79 *
80 * \note The size of the UTCB area specifies indirectly the number
81 * of UTCBs available for this task. Refer to L4::Task::add_ku_mem
82 * / l4_task_add_ku_mem() for adding more of this type of memory.
83 *
84 * \see \ref l4_task_api
85 */
86 L4_INLINE l4_msgtag_t
87 l4_factory_create_task(l4_cap_idx_t factory,
88 l4_cap_idx_t target_cap, l4_fpage_t utcb_area) L4_NOTHROW;
89
90 /**
91 * \ingroup l4_factory_api
92 * \copybrief L4::Factory::create_task
93 * \param factory Capability selector for factory to use for creation.
94 * \copydetails L4::Factory::create_task
95 */
96 L4_INLINE l4_msgtag_t
97 l4_factory_create_task_u(l4_cap_idx_t factory, l4_cap_idx_t target_cap,
98 l4_fpage_t utcb_area, l4_utcb_t *utcb) L4_NOTHROW;
99
100 /**
101 * \ingroup l4_factory_api
102 * \copybrief L4::Factory::create_thread
103 * \param factory Capability selector for factory to use for creation.
104 * \param[out] target_cap The kernel stores the new thread's capability into
105 * this slot.
106 *
107 * \return Syscall return tag
108 *
109 * \see \ref l4_thread_api
110 */
111 L4_INLINE l4_msgtag_t
112 l4_factory_create_thread(l4_cap_idx_t factory,
113 l4_cap_idx_t target_cap) L4_NOTHROW;
114
115 /**
116 * \ingroup l4_factory_api
117 * \copybrief L4::Factory::create_thread
118 * \param factory Capability selector for factory to use for creation.
119 * \copydetails L4::Factory::create_thread
120 */
121 L4_INLINE l4_msgtag_t
122 l4_factory_create_thread_u(l4_cap_idx_t factory,
123 l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW;
124
125 /**
126 * \ingroup l4_factory_api
127 * \copybrief L4::Factory::create_factory
128 * \param factory Capability selector for factory to use for creation.
129 * \param[out] target_cap The kernel stores the new factory's capability into
130 * this slot.
131 * \param limit Limit for the new factory in bytes.
132 *
133 * \return Syscall return tag
134 *
135 * \note The limit of the new factory is subtracted from the available amount
136 * of the factory used for creation.
137 */
138 L4_INLINE l4_msgtag_t
139 l4_factory_create_factory(l4_cap_idx_t factory, l4_cap_idx_t target_cap,
140 unsigned long limit) L4_NOTHROW;
141
142 /**
143 * \ingroup l4_factory_api
144 * \copybrief L4::Factory::create_factory
145 * \param factory Capability selector for factory to use for creation.
146 * \copydetails L4::Factory::create_factory
147 */
148 L4_INLINE l4_msgtag_t
149 l4_factory_create_factory_u(l4_cap_idx_t factory, l4_cap_idx_t target_cap,
150 unsigned long limit, l4_utcb_t *utcb) L4_NOTHROW;
151
152 /**
153 * \ingroup l4_factory_api
154 * \copybrief L4::Factory::create_gate
155 * \param factory Capability selector for factory to use for creation.
156 * \param[out] target_cap The kernel stores the new IPC gate's capability into
157 * this slot.
158 * \param thread_cap Optional capability selector of the thread to
159 * bind the gate to. Use #L4_INVALID_CAP to create
160 * an unbound IPC gate.
161 * \param label Optional label of the gate (is used if
162 * `thread_cap` is valid).
163 *
164 * \return Syscall return tag containing one of the following return codes.
165 *
166 * \retval L4_EOK No error occurred.
167 * \retval -L4_ENOMEM Out-of-memory during allocation of the Ipc_gate object.
168 * \retval -L4_ENOENT `thread_cap` is void or points to something that is not
169 * a thread.
170 * \retval -L4_EPERM No #L4_CAP_FPAGE_S rights on `thread_cap`.
171 *
172 * An unbound IPC gate can be bound to a thread using #l4_ipc_gate_bind_thread.
173 *
174 * \see l4_kernel_object_gate_api
175 */
176 L4_INLINE l4_msgtag_t
177 l4_factory_create_gate(l4_cap_idx_t factory,
178 l4_cap_idx_t target_cap,
179 l4_cap_idx_t thread_cap, l4_umword_t label) L4_NOTHROW;
180
181 /**
182 * \ingroup l4_factory_api
183 * \copybrief L4::Factory::create_gate
184 * \param factory Capability selector for factory to use for creation.
185 * \copydetails L4::Factory::create_gate
186 */
187 L4_INLINE l4_msgtag_t
188 l4_factory_create_gate_u(l4_cap_idx_t factory,
189 l4_cap_idx_t target_cap,
190 l4_cap_idx_t thread_cap, l4_umword_t label,
191 l4_utcb_t *utcb) L4_NOTHROW;
192
193 /**
194 * \ingroup l4_factory_api
195 * Create a new IRQ sender.
196 *
197 * \param factory Factory to use for creation.
198 * \param[out] target_cap The kernel stores the new IRQ's capability into this
199 * slot.
200 *
201 * \return Syscall return tag
202 *
203 * \see \ref l4_irq_api
204 */
205 L4_INLINE l4_msgtag_t
206 l4_factory_create_irq(l4_cap_idx_t factory,
207 l4_cap_idx_t target_cap) L4_NOTHROW;
208
209 /**
210 * \ingroup l4_factory_api
211 * \copybrief L4::Factory::create_irq
212 * \param factory Factory to use for creation.
213 * \copydetails L4::Factory::create_irq
214 */
215 L4_INLINE l4_msgtag_t
216 l4_factory_create_irq_u(l4_cap_idx_t factory,
217 l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW;
218
219 /**
220 * \ingroup l4_factory_api
221 * \copybrief L4::Factory::create_vm
222 * \param factory Capability selector for factory to use for creation.
223 * \param[out] target_cap The kernel stores the new VM's capability into this
224 * slot.
225 *
226 * \return Syscall return tag
227 *
228 * \see \ref l4_vm_api
229 */
230 L4_INLINE l4_msgtag_t
231 l4_factory_create_vm(l4_cap_idx_t factory,
232 l4_cap_idx_t target_cap) L4_NOTHROW;
233
234 /**
235 * \ingroup l4_factory_api
236 * \copybrief L4::Factory::create_vm
237 * \param factory Capability selector for factory to use for creation.
238 * \copydetails L4::Factory::create_vm
239 */
240 L4_INLINE l4_msgtag_t
241 l4_factory_create_vm_u(l4_cap_idx_t factory,
242 l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW;
243
244 L4_INLINE l4_msgtag_t
245 l4_factory_create_start_u(long obj, l4_cap_idx_t target,
246 l4_utcb_t *utcb) L4_NOTHROW;
247
248 L4_INLINE int
249 l4_factory_create_add_fpage_u(l4_fpage_t d, l4_msgtag_t *tag,
250 l4_utcb_t *utcb) L4_NOTHROW;
251
252 L4_INLINE int
253 l4_factory_create_add_int_u(l4_mword_t d, l4_msgtag_t *tag,
254 l4_utcb_t *utcb) L4_NOTHROW;
255
256 L4_INLINE int
257 l4_factory_create_add_uint_u(l4_umword_t d, l4_msgtag_t *tag,
258 l4_utcb_t *utcb) L4_NOTHROW;
259
260 L4_INLINE int
261 l4_factory_create_add_str_u(char const *s, l4_msgtag_t *tag,
262 l4_utcb_t *utcb) L4_NOTHROW;
263
264 L4_INLINE int
265 l4_factory_create_add_lstr_u(char const *s, unsigned len, l4_msgtag_t *tag,
266 l4_utcb_t *utcb) L4_NOTHROW;
267
268 L4_INLINE int
269 l4_factory_create_add_nil_u(l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW;
270
271 L4_INLINE l4_msgtag_t
272 l4_factory_create_commit_u(l4_cap_idx_t factory, l4_msgtag_t tag,
273 l4_utcb_t *utcb) L4_NOTHROW;
274
275 L4_INLINE l4_msgtag_t
276 l4_factory_create_u(l4_cap_idx_t factory, long obj, l4_cap_idx_t target,
277 l4_utcb_t *utcb) L4_NOTHROW;
278
279
280 L4_INLINE l4_msgtag_t
281 l4_factory_create(l4_cap_idx_t factory, long obj,
282 l4_cap_idx_t target) L4_NOTHROW;
283
284 /* IMPLEMENTATION -----------------------------------------------------------*/
285
286 #include <l4/sys/ipc.h>
287
288 L4_INLINE l4_msgtag_t
l4_factory_create_task_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_fpage_t utcb_area,l4_utcb_t * u)289 l4_factory_create_task_u(l4_cap_idx_t factory,
290 l4_cap_idx_t target_cap, l4_fpage_t utcb_area,
291 l4_utcb_t *u) L4_NOTHROW
292 {
293 l4_msgtag_t t;
294 t = l4_factory_create_start_u(L4_PROTO_TASK, target_cap, u);
295 l4_factory_create_add_fpage_u(utcb_area, &t, u);
296 return l4_factory_create_commit_u(factory, t, u);
297 }
298
299 L4_INLINE l4_msgtag_t
l4_factory_create_thread_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_utcb_t * u)300 l4_factory_create_thread_u(l4_cap_idx_t factory,
301 l4_cap_idx_t target_cap, l4_utcb_t *u) L4_NOTHROW
302 {
303 return l4_factory_create_u(factory, L4_PROTO_THREAD, target_cap, u);
304 }
305
306 L4_INLINE l4_msgtag_t
l4_factory_create_factory_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,unsigned long limit,l4_utcb_t * u)307 l4_factory_create_factory_u(l4_cap_idx_t factory,
308 l4_cap_idx_t target_cap, unsigned long limit,
309 l4_utcb_t *u) L4_NOTHROW
310 {
311 l4_msgtag_t t;
312 t = l4_factory_create_start_u(L4_PROTO_FACTORY, target_cap, u);
313 l4_factory_create_add_uint_u(limit, &t, u);
314 return l4_factory_create_commit_u(factory, t, u);
315 }
316
317 L4_INLINE l4_msgtag_t
l4_factory_create_gate_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_cap_idx_t thread_cap,l4_umword_t label,l4_utcb_t * u)318 l4_factory_create_gate_u(l4_cap_idx_t factory,
319 l4_cap_idx_t target_cap,
320 l4_cap_idx_t thread_cap, l4_umword_t label,
321 l4_utcb_t *u) L4_NOTHROW
322 {
323 l4_msgtag_t t;
324 l4_msg_regs_t *v;
325 int items = 0;
326 t = l4_factory_create_start_u(0, target_cap, u);
327 l4_factory_create_add_uint_u(label, &t, u);
328 v = l4_utcb_mr_u(u);
329 if (!(thread_cap & L4_INVALID_CAP_BIT))
330 {
331 items = 1;
332 v->mr[3] = l4_map_obj_control(0,0);
333 v->mr[4] = l4_obj_fpage(thread_cap, 0, L4_CAP_FPAGE_RWS).raw;
334 }
335 t = l4_msgtag(l4_msgtag_label(t), l4_msgtag_words(t), items, l4_msgtag_flags(t));
336 return l4_factory_create_commit_u(factory, t, u);
337 }
338
339 L4_INLINE l4_msgtag_t
l4_factory_create_irq_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_utcb_t * u)340 l4_factory_create_irq_u(l4_cap_idx_t factory,
341 l4_cap_idx_t target_cap, l4_utcb_t *u) L4_NOTHROW
342 {
343 return l4_factory_create_u(factory, L4_PROTO_IRQ_SENDER, target_cap, u);
344 }
345
346 L4_INLINE l4_msgtag_t
l4_factory_create_vm_u(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_utcb_t * u)347 l4_factory_create_vm_u(l4_cap_idx_t factory,
348 l4_cap_idx_t target_cap,
349 l4_utcb_t *u) L4_NOTHROW
350 {
351 return l4_factory_create_u(factory, L4_PROTO_VM, target_cap, u);
352 }
353
354
355
356
357
358 L4_INLINE l4_msgtag_t
l4_factory_create_task(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_fpage_t utcb_area)359 l4_factory_create_task(l4_cap_idx_t factory,
360 l4_cap_idx_t target_cap, l4_fpage_t utcb_area) L4_NOTHROW
361 {
362 return l4_factory_create_task_u(factory, target_cap, utcb_area, l4_utcb());
363 }
364
365 L4_INLINE l4_msgtag_t
l4_factory_create_thread(l4_cap_idx_t factory,l4_cap_idx_t target_cap)366 l4_factory_create_thread(l4_cap_idx_t factory,
367 l4_cap_idx_t target_cap) L4_NOTHROW
368 {
369 return l4_factory_create_thread_u(factory, target_cap, l4_utcb());
370 }
371
372 L4_INLINE l4_msgtag_t
l4_factory_create_factory(l4_cap_idx_t factory,l4_cap_idx_t target_cap,unsigned long limit)373 l4_factory_create_factory(l4_cap_idx_t factory,
374 l4_cap_idx_t target_cap, unsigned long limit) L4_NOTHROW
375
376 {
377 return l4_factory_create_factory_u(factory, target_cap, limit, l4_utcb());
378 }
379
380 L4_INLINE l4_msgtag_t
l4_factory_create_gate(l4_cap_idx_t factory,l4_cap_idx_t target_cap,l4_cap_idx_t thread_cap,l4_umword_t label)381 l4_factory_create_gate(l4_cap_idx_t factory,
382 l4_cap_idx_t target_cap,
383 l4_cap_idx_t thread_cap, l4_umword_t label) L4_NOTHROW
384 {
385 return l4_factory_create_gate_u(factory, target_cap, thread_cap, label, l4_utcb());
386 }
387
388 L4_INLINE l4_msgtag_t
l4_factory_create_irq(l4_cap_idx_t factory,l4_cap_idx_t target_cap)389 l4_factory_create_irq(l4_cap_idx_t factory,
390 l4_cap_idx_t target_cap) L4_NOTHROW
391 {
392 return l4_factory_create_irq_u(factory, target_cap, l4_utcb());
393 }
394
395 L4_INLINE l4_msgtag_t
l4_factory_create_vm(l4_cap_idx_t factory,l4_cap_idx_t target_cap)396 l4_factory_create_vm(l4_cap_idx_t factory,
397 l4_cap_idx_t target_cap) L4_NOTHROW
398 {
399 return l4_factory_create_vm_u(factory, target_cap, l4_utcb());
400 }
401
402 L4_INLINE l4_msgtag_t
l4_factory_create_start_u(long obj,l4_cap_idx_t target_cap,l4_utcb_t * u)403 l4_factory_create_start_u(long obj, l4_cap_idx_t target_cap,
404 l4_utcb_t *u) L4_NOTHROW
405 {
406 l4_msg_regs_t *v = l4_utcb_mr_u(u);
407 l4_buf_regs_t *b = l4_utcb_br_u(u);
408 v->mr[0] = obj;
409 b->bdr = 0;
410 b->br[0] = target_cap | L4_RCV_ITEM_SINGLE_CAP;
411 return l4_msgtag(L4_PROTO_FACTORY, 1, 0, 0);
412 }
413
414 L4_INLINE int
l4_factory_create_add_fpage_u(l4_fpage_t d,l4_msgtag_t * tag,l4_utcb_t * u)415 l4_factory_create_add_fpage_u(l4_fpage_t d, l4_msgtag_t *tag,
416 l4_utcb_t *u) L4_NOTHROW
417 {
418 l4_msg_regs_t *v = l4_utcb_mr_u(u);
419 int w = l4_msgtag_words(*tag);
420 if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE)
421 return 0;
422 v->mr[w] = L4_VARG_TYPE_FPAGE | (sizeof(l4_fpage_t) << 16);
423 v->mr[w + 1] = d.raw;
424 w += 2;
425 tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f);
426 return 1;
427 }
428
429 L4_INLINE int
l4_factory_create_add_int_u(l4_mword_t d,l4_msgtag_t * tag,l4_utcb_t * u)430 l4_factory_create_add_int_u(l4_mword_t d, l4_msgtag_t *tag,
431 l4_utcb_t *u) L4_NOTHROW
432 {
433 l4_msg_regs_t *v = l4_utcb_mr_u(u);
434 int w = l4_msgtag_words(*tag);
435 if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE)
436 return 0;
437 v->mr[w] = L4_VARG_TYPE_MWORD | (sizeof(l4_mword_t) << 16);
438 v->mr[w + 1] = d;
439 w += 2;
440 tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f);
441 return 1;
442 }
443
444 L4_INLINE int
l4_factory_create_add_uint_u(l4_umword_t d,l4_msgtag_t * tag,l4_utcb_t * u)445 l4_factory_create_add_uint_u(l4_umword_t d, l4_msgtag_t *tag,
446 l4_utcb_t *u) L4_NOTHROW
447 {
448 l4_msg_regs_t *v = l4_utcb_mr_u(u);
449 int w = l4_msgtag_words(*tag);
450 if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE)
451 return 0;
452 v->mr[w] = L4_VARG_TYPE_UMWORD | (sizeof(l4_umword_t) << 16);
453 v->mr[w + 1] = d;
454 w += 2;
455 tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f);
456 return 1;
457 }
458
459 L4_INLINE int
l4_factory_create_add_str_u(char const * s,l4_msgtag_t * tag,l4_utcb_t * u)460 l4_factory_create_add_str_u(char const *s, l4_msgtag_t *tag,
461 l4_utcb_t *u) L4_NOTHROW
462 {
463 return l4_factory_create_add_lstr_u(s, __builtin_strlen(s) + 1, tag, u);
464 }
465
466 L4_INLINE int
l4_factory_create_add_lstr_u(char const * s,unsigned len,l4_msgtag_t * tag,l4_utcb_t * u)467 l4_factory_create_add_lstr_u(char const *s, unsigned len, l4_msgtag_t *tag,
468 l4_utcb_t *u) L4_NOTHROW
469 {
470
471 l4_msg_regs_t *v = l4_utcb_mr_u(u);
472 unsigned w = l4_msgtag_words(*tag);
473 char *c;
474 unsigned i;
475
476 if (w + 1 + l4_bytes_to_mwords(len) > L4_UTCB_GENERIC_DATA_SIZE)
477 return 0;
478
479 v->mr[w] = L4_VARG_TYPE_STRING | (len << 16);
480 c = (char*)&v->mr[w + 1];
481 for (i = 0; i < len; ++i)
482 *c++ = *s++;
483
484 w = w + 1 + l4_bytes_to_mwords(len);
485
486 tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f);
487 return 1;
488 }
489
490 L4_INLINE int
l4_factory_create_add_nil_u(l4_msgtag_t * tag,l4_utcb_t * utcb)491 l4_factory_create_add_nil_u(l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW
492 {
493 l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
494 int w = l4_msgtag_words(*tag);
495 v->mr[w] = L4_VARG_TYPE_NIL;
496 ++w;
497 tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f);
498 return 1;
499 }
500
501
502 L4_INLINE l4_msgtag_t
l4_factory_create_commit_u(l4_cap_idx_t factory,l4_msgtag_t tag,l4_utcb_t * u)503 l4_factory_create_commit_u(l4_cap_idx_t factory, l4_msgtag_t tag,
504 l4_utcb_t *u) L4_NOTHROW
505 {
506 return l4_ipc_call(factory, u, tag, L4_IPC_NEVER);
507 }
508
509 L4_INLINE l4_msgtag_t
l4_factory_create_u(l4_cap_idx_t factory,long obj,l4_cap_idx_t target,l4_utcb_t * utcb)510 l4_factory_create_u(l4_cap_idx_t factory, long obj, l4_cap_idx_t target,
511 l4_utcb_t *utcb) L4_NOTHROW
512 {
513 l4_msgtag_t t = l4_factory_create_start_u(obj, target, utcb);
514 return l4_factory_create_commit_u(factory, t, utcb);
515 }
516
517
518 L4_INLINE l4_msgtag_t
l4_factory_create(l4_cap_idx_t factory,long obj,l4_cap_idx_t target)519 l4_factory_create(l4_cap_idx_t factory, long obj,
520 l4_cap_idx_t target) L4_NOTHROW
521 {
522 return l4_factory_create_u(factory, obj, target, l4_utcb());
523 }
524