]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/thread.h
25f2b0fc063c02e1e28da96988e0368ce0588d34
[l4.git] / l4 / pkg / l4sys / include / thread.h
1 /**
2  * \file
3  * \brief Common thread 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
27 #include <l4/sys/types.h>
28 #include <l4/sys/utcb.h>
29 #include <l4/sys/ipc.h>
30
31 /**
32  * \defgroup l4_thread_api Thread
33  * \ingroup  l4_kernel_object_api
34  * \brief Thread object.
35  *
36  * <c>\#include <l4/sys/thread.h></c>
37  *
38  * The thread class defines a thread of execution in the L4 context.
39  * Usually user-level and kernel threads are mapped 1:1 to each other.
40  * Thread kernel object are created using a Factory, see \ref l4_factory_api
41  * (l4_factory_create_thread()).
42  *
43  * An L4 thread encapsulates:
44  * - CPU state
45  *   - General-purpose registers
46  *   - Program counter
47  *   - Stack pointer
48  * - FPU state
49  * - Scheduling parameters
50  *   - CPU-set
51  *   - Priority (0-255)
52  *   - Time slice length
53  * - Execution state
54  *   - Blocked, Runnable, Running
55  *
56  * Thread objects provide an API for
57  * - Thread configuration and manipulation
58  * - Thread switching.
59  *
60  * The thread control functions are used to control various aspects of a
61  * thread. See l4_thread_control_start() for more information.
62  */
63
64
65 /**
66  * \brief Exchange basic thread registers.
67  * \ingroup l4_thread_api
68  *
69  * \param thread Thread to manipulate
70  * \param ip     New instruction pointer, use ~0UL to leave the
71  *               instruction pointer unchanged
72  * \param sp     New stack pointer, use ~0UL to leave the stack
73  *               pointer unchanged
74  * \param flags  Ex-regs flags, see #L4_thread_ex_regs_flags
75  *
76  * \return System call return tag
77  *
78  * This method allows to manipulate and start a thread. The basic
79  * functionality is to set the instruction pointer and the stack pointer of a
80  * thread. Additionally, this method allows also to cancel ongoing IPC
81  * operations and to force the thread to raise an artificial exception (see \a
82  * flags).
83  *
84  */
85 L4_INLINE l4_msgtag_t
86 l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
87                   l4_umword_t flags) L4_NOTHROW;
88
89 /**
90  * \internal
91  * \ingroup l4_thread_api
92  */
93 L4_INLINE l4_msgtag_t
94 l4_thread_ex_regs_u(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
95                     l4_umword_t flags, l4_utcb_t *utcb) L4_NOTHROW;
96
97 /**
98  * \brief Exchange basic thread registers and return previous values.
99  * \ingroup l4_thread_api
100  *
101  * \param  thread Thread to manipulate
102  * \retval ip     New instruction pointer, use ~0UL to leave the
103  *                instruction pointer unchanged, return previous instruction
104  *                pointer
105  * \retval sp     New stack pointer, use ~0UL to leave the stack
106  *                pointer unchanged, returns previous stack pointer
107  * \retval flags  Ex-regs flags, see #L4_thread_ex_regs_flags, return
108  *                previous CPU flags of the thread.
109  *
110  * \return System call return tag
111  *
112  * This method allows to manipulate and start a thread. The basic
113  * functionality is to set the instruction pointer and the stack pointer of a
114  * thread. Additionally, this method allows also to cancel ongoing IPC
115  * operations and to force the thread to raise an artificial exception (see \a
116  * flags).
117  *
118  * Returned values are valid only if function returns successfully.
119  */
120 L4_INLINE l4_msgtag_t
121 l4_thread_ex_regs_ret(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
122                       l4_umword_t *flags) L4_NOTHROW;
123
124 /**
125  * \internal
126  * \ingroup l4_thread_api
127  */
128 L4_INLINE l4_msgtag_t
129 l4_thread_ex_regs_ret_u(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
130                         l4_umword_t *flags, l4_utcb_t *utcb) L4_NOTHROW;
131
132
133
134 /**
135  * \defgroup l4_thread_control_api Thread control
136  * \ingroup l4_thread_api
137  *
138  * \brief API for Thread Control method.
139  *
140  *
141  * The thread control API provides access to almost any parameter of a thread
142  * object. The API is based on a single invocation of the thread object.
143  * However, because of the huge amount of parameters, the API provides a set
144  * of functions to set specific parameters of a thread and a commit function
145  * to commit the thread control call (see l4_thread_control_commit()).
146  *
147  * A thread control operation must always start with l4_thread_control_start()
148  * and be committed with l4_thread_control_commit().  All other thread control
149  * parameter setter functions must be called between these two functions.
150  *
151  * An example for a sequence of thread control API calls can be found below.
152  *
153  *  l4_utcb_t *u = l4_utcb(); <br>
154  *  \link l4_thread_control_start() l4_thread_control_start(u)\endlink; <br>
155  *  \link l4_thread_control_pager() l4_thread_control_pager(u, pager_cap)\endlink; <br>
156  *  \link l4_thread_control_bind() l4_thread_control_bind (u, thread_utcb, task)\endlink; <br>
157  *  \link l4_thread_control_commit() l4_thread_control_commit(u, thread_cap)\endlink; <br>
158  *
159  */
160
161 /**
162  * \brief Start a thread control API sequence.
163  * \ingroup l4_thread_control_api
164  *
165  * This function starts a sequence of thread control API functions.
166  * After this functions any of following functions may be called in any order.
167  * - l4_thread_control_pager()
168  * - l4_thread_control_exc_handler()
169  * - l4_thread_control_scheduler()
170  * - l4_thread_control_bind()
171  * - l4_thread_control_alien()
172  * - l4_thread_control_ux_host_syscall() (Fiasco-UX only)
173  *
174  * To commit the changes to the thread l4_thread_control_commit() must be
175  * called in the end.
176  *
177  * \note The thread control API calls store the parameters for the thread in
178  *       the UTCB of the caller, this means between l4_thread_control_start()
179  *       and l4_thread_control_commit() no functions that modify the UTCB
180  *       contents must be called.
181  */
182 L4_INLINE void
183 l4_thread_control_start(void) L4_NOTHROW;
184
185 /**
186  * \internal
187  * \ingroup l4_thread_control_api
188  */
189 L4_INLINE void
190 l4_thread_control_start_u(l4_utcb_t *utcb) L4_NOTHROW;
191
192 /**
193  * \brief Set the pager.
194  * \ingroup l4_thread_control_api
195  *
196  * \param pager     Capability selector invoked to send a page-fault IPC.
197  *
198  * \note The pager capability selector is interpreted in the task the thread
199  *       is bound to (executes in).
200  */
201 L4_INLINE void
202 l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW;
203
204 /**
205  * \internal
206  * \ingroup l4_thread_control_api
207  */
208 L4_INLINE void
209 l4_thread_control_pager_u(l4_cap_idx_t pager, l4_utcb_t *utcb) L4_NOTHROW;
210
211 /**
212  * \brief Set the exception handler.
213  * \ingroup l4_thread_control_api
214  *
215  * \param exc_handler  Capability selector invoked to send an exception IPC.
216  *
217  * \note The exception-handler capability selector is interpreted in the task
218  *       the thread is bound to (executes in).
219  */
220 L4_INLINE void
221 l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW;
222
223 /**
224  * \internal
225  * \ingroup l4_thread_control_api
226  */
227 L4_INLINE void
228 l4_thread_control_exc_handler_u(l4_cap_idx_t exc_handler,
229                                 l4_utcb_t *utcb) L4_NOTHROW;
230
231 /**
232  * \brief Set the scheduler.
233  * \ingroup l4_thread_control_api
234  *
235  * \param scheduler Capability selector invoked to send a scheduling IPC.
236  *
237  * \note The scheduler capability selector is interpreted in the task the
238  *       thread is bound to (executes in).
239  */
240 L4_INLINE void
241 l4_thread_control_scheduler(l4_cap_idx_t scheduler) L4_NOTHROW;
242
243 /**
244  * \internal
245  * \ingroup l4_thread_control_api
246  */
247 L4_INLINE void
248 l4_thread_control_scheduler_u(l4_cap_idx_t scheduler, l4_utcb_t *utcb) L4_NOTHROW;
249
250 /**
251  * \brief Bind the thread to a task.
252  * \ingroup l4_thread_control_api
253  *
254  * \param thread_utcb The address of the UTCB in the target task.
255  * \param task        The target task of the thread.
256  *
257  * Binding a thread to a task has the effect that the thread
258  * afterwards executes code within that task and has access to the
259  * resources visible within that task.
260  *
261  * \note There should not be more than one thread use a UTCB to prevent
262  *       data corruption.
263  *
264  */
265 L4_INLINE void
266 l4_thread_control_bind(l4_utcb_t *thread_utcb,
267                        l4_cap_idx_t task) L4_NOTHROW;
268
269 /**
270  * \internal
271  * \ingroup l4_thread_control_api
272  */
273 L4_INLINE void
274 l4_thread_control_bind_u(l4_utcb_t *thread_utcb,
275                          l4_cap_idx_t task, l4_utcb_t *utcb) L4_NOTHROW;
276
277 /**
278  * \brief Enable alien mode.
279  * \ingroup l4_thread_control_api
280  * \param   on    Boolean value defining the state of the feature.
281  *
282  * Alien mode means the thread is not allowed to invoke L4 kernel objects
283  * directly and it is also not allowed to allocate FPU state. All those
284  * operations result in an exception IPC that gets sent through the pager
285  * capability. The responsible pager can then selectively allow an object
286  * invocation or allocate FPU state for the thread.
287  *
288  * This feature can be used to attach a debugger to a thread and trace all
289  * object invocations.
290  */
291 L4_INLINE void
292 l4_thread_control_alien(int on) L4_NOTHROW;
293
294 /**
295  * \internal
296  * \ingroup l4_thread_control_api
297  */
298 L4_INLINE void
299 l4_thread_control_alien_u(l4_utcb_t *utcb, int on) L4_NOTHROW;
300
301 /**
302  * \brief Enable pass through of native host (Linux) system calls.
303  * \ingroup l4_thread_control_api
304  * \param   on    Boolean value defining the state of the feature.
305  *
306  * \pre Running on Fiasco-UX
307  *
308  * This enables the thread to do host system calls. This feature is only
309  * available in Fiasco-UX and ignored in other environments.
310  */
311 L4_INLINE void
312 l4_thread_control_ux_host_syscall(int on) L4_NOTHROW;
313
314 /**
315  * \internal
316  * \ingroup l4_thread_control_api
317  */
318 L4_INLINE void
319 l4_thread_control_ux_host_syscall_u(l4_utcb_t *utcb, int on) L4_NOTHROW;
320
321
322
323 /**
324  * \brief Commit the thread control parameters.
325  * \ingroup l4_thread_control_api
326  *
327  * \param thread  Capability selector of target thread to commit to.
328  * \return system call return tag
329  */
330 L4_INLINE l4_msgtag_t
331 l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW;
332
333 /**
334  * \internal
335  * \ingroup l4_thread_control_api
336  */
337 L4_INLINE l4_msgtag_t
338 l4_thread_control_commit_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW;
339
340 /**
341  * \brief Yield current time slice.
342  * \ingroup l4_thread_api
343  *
344  * \return system call return tag
345  */
346 L4_INLINE l4_msgtag_t
347 l4_thread_yield(void) L4_NOTHROW;
348
349 /**
350  * \brief Switch to another thread (and donate the remaining time slice).
351  * \ingroup l4_thread_api
352  *
353  * \param to_thread   The thread to switch to.
354  *
355  * \return system call return tag
356  */
357 L4_INLINE l4_msgtag_t
358 l4_thread_switch(l4_cap_idx_t to_thread) L4_NOTHROW;
359
360 /**
361  * \internal
362  * \ingroup l4_thread_api
363  */
364 L4_INLINE l4_msgtag_t
365 l4_thread_switch_u(l4_cap_idx_t to_thread, l4_utcb_t *utcb) L4_NOTHROW;
366
367
368
369 /**
370  * \brief Get consumed timed of thread in µs.
371  * \ingroup l4_thread_api
372  * \param thread Thread to get the consumed time from.
373  *
374  * The consumed time is returned as l4_kernel_clock_t at UTCB message
375  * register 0.
376  */
377 L4_INLINE l4_msgtag_t
378 l4_thread_stats_time(l4_cap_idx_t thread) L4_NOTHROW;
379
380 /**
381  * \internal
382  * \ingroup l4_thread_api
383  */
384 L4_INLINE l4_msgtag_t
385 l4_thread_stats_time_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW;
386
387
388 /**
389  * \brief vCPU return from event handler.
390  * \ingroup l4_thread_api
391  *
392  * \return Message tag to be used for l4_sndfpage_add() and
393  *         l4_thread_vcpu_commit()
394  *
395  * The vCPU resume functionality is split in multiple functions to allow the
396  * specification of additional send-flex-pages using l4_sndfpage_add().
397  */
398 L4_INLINE l4_msgtag_t
399 l4_thread_vcpu_resume_start(void) L4_NOTHROW;
400
401 /**
402  * \internal
403  * \ingroup l4_thread_api
404  */
405 L4_INLINE l4_msgtag_t
406 l4_thread_vcpu_resume_start_u(l4_utcb_t *utcb) L4_NOTHROW;
407
408 /**
409  * \brief Commit vCPU resume.
410  * \ingroup l4_thread_api
411  *
412  * \param thread    Thread to be resumed, using the invalid cap can be used
413  *                  for the current thread.
414  * \param tag       Tag to use, returned by l4_thread_vcpu_resume_start()
415  *
416  * \return System call result message tag.
417  *
418  * To resume into another address space the capability to the target task
419  * must be set in the vCPU-state (\see l4_vcpu_state_t). The task needs
420  * to be set only once, consecutive resumes to the same address space should
421  * use an invalid capability. The kernel resets the field to
422  * #L4_INVALID_CAP. To release a task use a different task or use an invalid
423  * capability with the #L4_SYSF_REPLY flag set.
424  */
425 L4_INLINE l4_msgtag_t
426 l4_thread_vcpu_resume_commit(l4_cap_idx_t thread,
427                              l4_msgtag_t tag) L4_NOTHROW;
428
429 /**
430  * \internal
431  * \ingroup l4_thread_api
432  */
433 L4_INLINE l4_msgtag_t
434 l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread,
435                                l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW;
436
437
438 /**
439  * \brief Enable or disable the vCPU feature for the thread.
440  * \ingroup l4_thread_api
441  *
442  * \param thread The thread for which the vCPU feature shall be enabled or
443  *               disabled.
444  * \param vcpu_state The virtual address where the kernel shall store the vCPU
445  *                   state in case of vCPU exits. The address must be a valid
446  *                   kernel-user-memory address.
447  * \return Systemcall result message tag.
448  *
449  * This function enables the vCPU feature of the \a thread if \a vcpu_state
450  * is set to a valid kernel-user-memory address, or disables the vCPU feature
451  * if \a vcpu_state is 0.
452  *
453  */
454 L4_INLINE l4_msgtag_t
455 l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW;
456
457 /**
458  * \internal
459  * \ingroup l4_thread_api
460  */
461 L4_INLINE l4_msgtag_t
462 l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state,
463                          l4_utcb_t *utcb) L4_NOTHROW;
464
465 /**
466  * \brief Enable or disable the extended vCPU feature for the thread.
467  * \ingroup l4_thread_api
468  *
469  * \param thread The thread for which the extended vCPU feature shall be
470  *               enabled or disabled.
471  * \param vcpu_state The virtual address where the kernel shall store the vCPU
472  *                   state in case of vCPU exits. The address must be a valid
473  *                   kernel-user-memory address.
474  * \return Systemcall result message tag.
475  *
476  * The extended vCPU feature allows the use of hardware-virtualization
477  * features such as Intel's VT os AMD's SVM.
478  *
479  * This function enables the extended vCPU feature of the \a thread
480  * if \a vcpu_state is set to a valid kernel-user-memory address, or disables
481  * the vCPU feature if \a vcpu_state is 0.
482  *
483  */
484 L4_INLINE l4_msgtag_t
485 l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW;
486
487 /**
488  * \internal
489  * \ingroup l4_thread_api
490  */
491 L4_INLINE l4_msgtag_t
492 l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state,
493                              l4_utcb_t *utcb) L4_NOTHROW;
494
495
496 /**
497  * \brief Register an IRQ that will trigger upon deletion events.
498  * \ingroup l4_thread_api
499  *
500  * \param thread    Thread to register IRQ for.
501  * \param irq       Irq to register.
502  *
503  * \return System call result message tag.
504  */
505 L4_INLINE l4_msgtag_t
506 l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW;
507
508 /**
509  * \internal
510  * \ingroup l4_thread_api
511  */
512 L4_INLINE l4_msgtag_t
513 l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq,
514                              l4_utcb_t *utcb) L4_NOTHROW;
515
516 /**
517  * \brief Start a thread sender modifiction sequence.
518  * \ingroup l4_thread_api
519  *
520  * Add modification rules with l4_thread_modify_sender_add() and commit with
521  * l4_thread_modify_sender_commit(). Do not touch the UTCB between
522  * l4_thread_modify_sender_start() and l4_thread_modify_sender_commit().
523  *
524  * \see l4_thread_modify_sender_add
525  * \see l4_thread_modify_sender_commit
526  */
527 L4_INLINE l4_msgtag_t
528 l4_thread_modify_sender_start(void) L4_NOTHROW;
529
530 /**
531  * \internal
532  * \ingroup l4_thread_api
533  */
534 L4_INLINE l4_msgtag_t
535 l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW;
536
537 /**
538  * \brief Add a modification pattern to a sender modification sequence.
539  * \ingroup l4_thread_api
540  *
541  * \param tag        Tag received from l4_thread_modify_sender_start() or
542  *                   previous l4_thread_modify_sender_add() calls from
543  *                   the same sequence.
544  * \param match_mask Bitmask of bits to match the label.
545  * \param match      Bitmask that must be equal to the label after applying
546  *                   match_mask.
547  * \param del_bits   Bits to be deleted from the label.
548  * \param add_bits   Bits to be added to the label.
549  *
550  * \return 0 on sucess, <0 on error
551  *
552  * In pseudo code:
553  *   if ((sender_label & match_mask) == match)
554  *     { label = (label & ~del_bits) | add_bits; }
555  *
556  * Only the first match is applied.
557  *
558  * \see l4_thread_modify_sender_start
559  * \see l4_thread_modify_sender_commit
560  */
561 L4_INLINE int
562 l4_thread_modify_sender_add(l4_umword_t match_mask,
563                             l4_umword_t match,
564                             l4_umword_t del_bits,
565                             l4_umword_t add_bits,
566                             l4_msgtag_t *tag) L4_NOTHROW;
567
568 /**
569  * \internal
570  * \ingroup l4_thread_api
571  */
572 L4_INLINE int
573 l4_thread_modify_sender_add_u(l4_umword_t match_mask,
574                               l4_umword_t match,
575                               l4_umword_t del_bits,
576                               l4_umword_t add_bits,
577                               l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW;
578
579 /**
580  * \brief Apply (commit) a sender modification sequence.
581  * \ingroup l4_thread_api
582  *
583  * \see l4_thread_modify_sender_start
584  * \see l4_thread_modify_sender_add
585  */
586 L4_INLINE l4_msgtag_t
587 l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW;
588
589 /**
590  * \internal
591  * \ingroup l4_thread_api
592  */
593 L4_INLINE l4_msgtag_t
594 l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag,
595                                  l4_utcb_t *u) L4_NOTHROW;
596
597 /**
598  * \brief Operations on thread objects.
599  * \ingroup l4_thread_api
600  * \hideinitializer
601  * \internal
602  */
603 enum L4_thread_ops
604 {
605   L4_THREAD_CONTROL_OP            = 0UL,    /**< Control operation */
606   L4_THREAD_EX_REGS_OP            = 1UL,    /**< Exchange registers operation */
607   L4_THREAD_SWITCH_OP             = 2UL,    /**< Do a thread switch */
608   L4_THREAD_STATS_OP              = 3UL,    /**< Thread statistics */
609   L4_THREAD_VCPU_RESUME_OP        = 4UL,    /**< VCPU resume */
610   L4_THREAD_REGISTER_DELETE_IRQ   = 5UL,    /**< Register an IPC-gate deletion IRQ */
611   L4_THREAD_MODIFY_SENDER         = 6UL,    /**< Modify all senders IDs that match the given pattern */
612   L4_THREAD_VCPU_CONTROL          = 7UL,    /**< Enable / disable VCPU feature */
613   L4_THREAD_VCPU_CONTROL_EXT      = L4_THREAD_VCPU_CONTROL | 0x10000,
614   L4_THREAD_GDT_X86_OP            = 0x10UL, /**< Gdt */
615   L4_THREAD_OPCODE_MASK           = 0xffff, /**< Mask for opcodes */
616 };
617
618 /**
619  * \brief Flags for the thread control operation.
620  * \ingroup l4_thread_api
621  * \hideinitializer
622  * \internal
623  *
624  * Values for the enabled flags need to be given in their appropriate field
625  * in the UTCB,
626  * \see l4_thread_control
627  */
628 enum L4_thread_control_flags
629 {
630   /** The pager will be given. */
631   L4_THREAD_CONTROL_SET_PAGER       = 0x0010000,
632   /** The scheduler will be given. */
633   L4_THREAD_CONTROL_SET_SCHEDULER   = 0x0020000,
634   /** The task to bind the thread to will be given. */
635   L4_THREAD_CONTROL_BIND_TASK       = 0x0200000,
636   /** Alien state of the thread is set. */
637   L4_THREAD_CONTROL_ALIEN           = 0x0400000,
638   /** Fiasco-UX only: pass-through of host system calls is set. */
639   L4_THREAD_CONTROL_UX_NATIVE       = 0x0800000,
640   /** The exception handler of the thread will be given. */
641   L4_THREAD_CONTROL_SET_EXC_HANDLER = 0x1000000,
642 };
643
644 /**
645  * \brief Indices for the values in the message register for thread control.
646  * \ingroup l4_thread_api
647  * \hideinitializer
648  * \internal
649  *
650  * The values indicate the index in the message registers during
651  * thread-control operation.
652  */
653 enum L4_thread_control_mr_indices
654 {
655   L4_THREAD_CONTROL_MR_IDX_FLAGS       = 0, /**< \see #L4_thread_control_flags. */
656   L4_THREAD_CONTROL_MR_IDX_PAGER       = 1, /**< Index for pager cap */
657   L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER = 2, /**< Index for exception handler */
658   L4_THREAD_CONTROL_MR_IDX_SCHEDULER   = 3, /**< Index for scheduler */
659   L4_THREAD_CONTROL_MR_IDX_FLAG_VALS   = 4, /**< Index for feature values */
660   L4_THREAD_CONTROL_MR_IDX_BIND_UTCB   = 5, /**< Index for UTCB address for bind */
661   L4_THREAD_CONTROL_MR_IDX_BIND_TASK   = 6, /**< Index for task flex-page for bind */
662 };
663
664 /**
665  * \brief Flags for the thread ex-regs operation.
666  * \ingroup l4_thread_api
667  * \hideinitializer
668  */
669 enum L4_thread_ex_regs_flags
670 {
671   L4_THREAD_EX_REGS_CANCEL            = 0x10000UL, /**< Cancel ongoing IPC in the thread. */
672   L4_THREAD_EX_REGS_TRIGGER_EXCEPTION = 0x20000UL, /**< Trigger artificial exception in thread. */
673 };
674
675
676 /* IMPLEMENTATION -----------------------------------------------------------*/
677
678 #include <l4/sys/ipc.h>
679 #include <l4/sys/types.h>
680
681 L4_INLINE l4_msgtag_t
682 l4_thread_ex_regs_u(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
683                     l4_umword_t flags, l4_utcb_t *utcb) L4_NOTHROW
684 {
685   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
686   v->mr[0] = L4_THREAD_EX_REGS_OP | flags;
687   v->mr[1] = ip;
688   v->mr[2] = sp;
689   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 3, 0, 0), L4_IPC_NEVER);
690 }
691
692 L4_INLINE l4_msgtag_t
693 l4_thread_ex_regs_ret_u(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
694                         l4_umword_t *flags, l4_utcb_t *utcb) L4_NOTHROW
695 {
696   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
697   l4_msgtag_t ret = l4_thread_ex_regs_u(thread, *ip, *sp, *flags, utcb);
698   if (l4_error_u(ret, utcb))
699     return ret;
700
701   *flags = v->mr[0];
702   *ip    = v->mr[1];
703   *sp    = v->mr[2];
704   return ret;
705 }
706
707 L4_INLINE void
708 l4_thread_control_start_u(l4_utcb_t *utcb) L4_NOTHROW
709 {
710   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
711   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] = L4_THREAD_CONTROL_OP;
712 }
713
714 L4_INLINE void
715 l4_thread_control_pager_u(l4_cap_idx_t pager, l4_utcb_t *utcb) L4_NOTHROW
716 {
717   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
718   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_SET_PAGER;
719   v->mr[L4_THREAD_CONTROL_MR_IDX_PAGER]  = pager;
720 }
721
722 L4_INLINE void
723 l4_thread_control_exc_handler_u(l4_cap_idx_t exc_handler,
724                                 l4_utcb_t *utcb) L4_NOTHROW
725 {
726   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
727   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]       |= L4_THREAD_CONTROL_SET_EXC_HANDLER;
728   v->mr[L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER]  = exc_handler;
729 }
730
731 L4_INLINE void
732 l4_thread_control_scheduler_u(l4_cap_idx_t scheduler, l4_utcb_t *utcb) L4_NOTHROW
733 {
734   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
735   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_SET_SCHEDULER;
736   v->mr[L4_THREAD_CONTROL_MR_IDX_SCHEDULER]  = scheduler;
737 }
738
739 L4_INLINE void
740 l4_thread_control_bind_u(l4_utcb_t *thread_utcb, l4_cap_idx_t task,
741                          l4_utcb_t *utcb) L4_NOTHROW
742 {
743   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
744   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]         |= L4_THREAD_CONTROL_BIND_TASK;
745   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_UTCB]      = (l4_addr_t)thread_utcb;
746   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK]      = L4_ITEM_MAP;
747   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK + 1]  = l4_obj_fpage(task, 0, L4_FPAGE_RWX).raw;
748 }
749
750 L4_INLINE void
751 l4_thread_control_alien_u(l4_utcb_t *utcb, int on) L4_NOTHROW
752 {
753   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
754   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_ALIEN;
755   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_ALIEN : 0;
756 }
757
758 L4_INLINE void
759 l4_thread_control_ux_host_syscall_u(l4_utcb_t *utcb, int on) L4_NOTHROW
760 {
761   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
762   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_UX_NATIVE;
763   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_UX_NATIVE : 0;
764 }
765
766 L4_INLINE l4_msgtag_t
767 l4_thread_control_commit_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
768 {
769   int items = 0;
770   if (l4_utcb_mr_u(utcb)->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] & L4_THREAD_CONTROL_BIND_TASK)
771     items = 1;
772   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 6, items, 0), L4_IPC_NEVER);
773 }
774
775
776 L4_INLINE l4_msgtag_t
777 l4_thread_yield(void) L4_NOTHROW
778 {
779   l4_ipc_receive(L4_INVALID_CAP, NULL, L4_IPC_BOTH_TIMEOUT_0);
780   return l4_msgtag(0, 0, 0, 0);
781 }
782
783 /* Preliminary, to be changed */
784 L4_INLINE l4_msgtag_t
785 l4_thread_switch_u(l4_cap_idx_t to_thread, l4_utcb_t *utcb) L4_NOTHROW
786 {
787   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
788   v->mr[0] = L4_THREAD_SWITCH_OP;
789   return l4_ipc_call(to_thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER);
790 }
791
792
793 L4_INLINE l4_msgtag_t
794 l4_thread_stats_time_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
795 {
796   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
797   v->mr[0] = L4_THREAD_STATS_OP;
798   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER);
799 }
800
801 L4_INLINE l4_msgtag_t
802 l4_thread_vcpu_resume_start_u(l4_utcb_t *utcb) L4_NOTHROW
803 {
804   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
805   v->mr[0] = L4_THREAD_VCPU_RESUME_OP;
806   return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0);
807 }
808
809 L4_INLINE l4_msgtag_t
810 l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread,
811                                l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
812 {
813   return l4_ipc_call(thread, utcb, tag, L4_IPC_NEVER);
814 }
815
816 L4_INLINE l4_msgtag_t
817 l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
818                     l4_umword_t flags) L4_NOTHROW
819 {
820   return l4_thread_ex_regs_u(thread, ip, sp, flags, l4_utcb());
821 }
822
823 L4_INLINE l4_msgtag_t
824 l4_thread_ex_regs_ret(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
825                       l4_umword_t *flags) L4_NOTHROW
826 {
827   return l4_thread_ex_regs_ret_u(thread, ip, sp, flags, l4_utcb());
828 }
829
830 L4_INLINE void
831 l4_thread_control_start(void) L4_NOTHROW
832 {
833   l4_thread_control_start_u(l4_utcb());
834 }
835
836 L4_INLINE void
837 l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW
838 {
839   l4_thread_control_pager_u(pager, l4_utcb());
840 }
841
842 L4_INLINE void
843 l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW
844 {
845   l4_thread_control_exc_handler_u(exc_handler, l4_utcb());
846 }
847
848 L4_INLINE void
849 l4_thread_control_scheduler(l4_cap_idx_t scheduler) L4_NOTHROW
850 {
851   l4_thread_control_scheduler_u(scheduler, l4_utcb());
852 }
853
854
855 L4_INLINE void
856 l4_thread_control_bind(l4_utcb_t *thread_utcb, l4_cap_idx_t task) L4_NOTHROW
857 {
858   l4_thread_control_bind_u(thread_utcb, task, l4_utcb());
859 }
860
861 L4_INLINE void
862 l4_thread_control_alien(int on) L4_NOTHROW
863 {
864   l4_thread_control_alien_u(l4_utcb(), on);
865 }
866
867 L4_INLINE void
868 l4_thread_control_ux_host_syscall(int on) L4_NOTHROW
869 {
870   l4_thread_control_ux_host_syscall_u(l4_utcb(), on);
871 }
872
873 L4_INLINE l4_msgtag_t
874 l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW
875 {
876   return l4_thread_control_commit_u(thread, l4_utcb());
877 }
878
879
880
881
882 L4_INLINE l4_msgtag_t
883 l4_thread_switch(l4_cap_idx_t to_thread) L4_NOTHROW
884 {
885   return l4_thread_switch_u(to_thread, l4_utcb());
886 }
887
888
889
890
891 L4_INLINE l4_msgtag_t
892 l4_thread_stats_time(l4_cap_idx_t thread) L4_NOTHROW
893 {
894   return l4_thread_stats_time_u(thread, l4_utcb());
895 }
896
897 L4_INLINE l4_msgtag_t
898 l4_thread_vcpu_resume_start(void) L4_NOTHROW
899 {
900   return l4_thread_vcpu_resume_start_u(l4_utcb());
901 }
902
903 L4_INLINE l4_msgtag_t
904 l4_thread_vcpu_resume_commit(l4_cap_idx_t thread,
905                              l4_msgtag_t tag) L4_NOTHROW
906 {
907   return l4_thread_vcpu_resume_commit_u(thread, tag, l4_utcb());
908 }
909
910
911 L4_INLINE l4_msgtag_t
912 l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq,
913                              l4_utcb_t *u) L4_NOTHROW
914 {
915   l4_msg_regs_t *m = l4_utcb_mr_u(u);
916   m->mr[0] = L4_THREAD_REGISTER_DELETE_IRQ;
917   m->mr[1] = l4_map_obj_control(0,0);
918   m->mr[2] = l4_obj_fpage(irq, 0, L4_CAP_FPAGE_RWS).raw;
919   return l4_ipc_call(thread, u, l4_msgtag(L4_PROTO_THREAD, 1, 1, 0), L4_IPC_NEVER);
920
921 }
922
923 L4_INLINE l4_msgtag_t
924 l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW
925 {
926   return l4_thread_register_del_irq_u(thread, irq, l4_utcb());
927 }
928
929
930 L4_INLINE l4_msgtag_t
931 l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state,
932                          l4_utcb_t *utcb) L4_NOTHROW
933 {
934   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
935   v->mr[0] = L4_THREAD_VCPU_CONTROL;
936   v->mr[1] = vcpu_state;
937   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER);
938 }
939
940 L4_INLINE l4_msgtag_t
941 l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW
942 { return l4_thread_vcpu_control_u(thread, vcpu_state, l4_utcb()); }
943
944
945 L4_INLINE l4_msgtag_t
946 l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state,
947                              l4_utcb_t *utcb) L4_NOTHROW
948 {
949   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
950   v->mr[0] = L4_THREAD_VCPU_CONTROL_EXT;
951   v->mr[1] = ext_vcpu_state;
952   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER);
953 }
954
955 L4_INLINE l4_msgtag_t
956 l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW
957 { return l4_thread_vcpu_control_ext_u(thread, ext_vcpu_state, l4_utcb()); }
958
959 L4_INLINE l4_msgtag_t
960 l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW
961 {
962   l4_msg_regs_t *m = l4_utcb_mr_u(u);
963   m->mr[0] = L4_THREAD_MODIFY_SENDER;
964   return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0);
965 }
966
967 L4_INLINE int
968 l4_thread_modify_sender_add_u(l4_umword_t match_mask,
969                               l4_umword_t match,
970                               l4_umword_t del_bits,
971                               l4_umword_t add_bits,
972                               l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW
973 {
974   l4_msg_regs_t *m = l4_utcb_mr_u(u);
975   unsigned w = l4_msgtag_words(*tag);
976   if (w >= L4_UTCB_GENERIC_DATA_SIZE - 4)
977     return -L4_ENOMEM;
978
979   m->mr[w]   = match_mask;
980   m->mr[w+1] = match;
981   m->mr[w+2] = del_bits;
982   m->mr[w+3] = add_bits;
983
984   *tag = l4_msgtag(l4_msgtag_label(*tag), w + 4, 0, 0);
985
986   return 0;
987 }
988
989 L4_INLINE l4_msgtag_t
990 l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag,
991                                  l4_utcb_t *u) L4_NOTHROW
992 {
993   return l4_ipc_call(thread, u, tag, L4_IPC_NEVER);
994 }
995
996 L4_INLINE l4_msgtag_t
997 l4_thread_modify_sender_start(void) L4_NOTHROW
998 {
999   return l4_thread_modify_sender_start_u(l4_utcb());
1000 }
1001
1002 L4_INLINE int
1003 l4_thread_modify_sender_add(l4_umword_t match_mask,
1004                             l4_umword_t match,
1005                             l4_umword_t del_bits,
1006                             l4_umword_t add_bits,
1007                             l4_msgtag_t *tag) L4_NOTHROW
1008 {
1009   return l4_thread_modify_sender_add_u(match_mask, match,
1010                                        del_bits, add_bits, tag, l4_utcb());
1011 }
1012
1013 L4_INLINE l4_msgtag_t
1014 l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW
1015 {
1016   return l4_thread_modify_sender_commit_u(thread, tag, l4_utcb());
1017 }