]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/thread.h
14955daaef1d5c6249bedb921a9d83cd2a3b8062
[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. In extended vCPU mode and when
417  * the virtual interrupts are cleared, the return code 1 flags an incoming
418  * IPC message, whereas 0 indicates a VM exit.
419  *
420  * To resume into another address space the capability to the target task
421  * must be set in the vCPU-state (\see l4_vcpu_state_t). The task needs
422  * to be set only once, consecutive resumes to the same address space should
423  * use an invalid capability. The kernel resets the field to
424  * #L4_INVALID_CAP. To release a task use a different task or use an invalid
425  * capability with the #L4_SYSF_REPLY flag set.
426  */
427 L4_INLINE l4_msgtag_t
428 l4_thread_vcpu_resume_commit(l4_cap_idx_t thread,
429                              l4_msgtag_t tag) L4_NOTHROW;
430
431 /**
432  * \internal
433  * \ingroup l4_thread_api
434  */
435 L4_INLINE l4_msgtag_t
436 l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread,
437                                l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW;
438
439
440 /**
441  * \brief Enable or disable the vCPU feature for the thread.
442  * \ingroup l4_thread_api
443  *
444  * \param thread The thread for which the vCPU feature shall be enabled or
445  *               disabled.
446  * \param vcpu_state The virtual address where the kernel shall store the vCPU
447  *                   state in case of vCPU exits. The address must be a valid
448  *                   kernel-user-memory address.
449  * \return Systemcall result message tag.
450  *
451  * This function enables the vCPU feature of the \a thread if \a vcpu_state
452  * is set to a valid kernel-user-memory address, or disables the vCPU feature
453  * if \a vcpu_state is 0.
454  *
455  */
456 L4_INLINE l4_msgtag_t
457 l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW;
458
459 /**
460  * \internal
461  * \ingroup l4_thread_api
462  */
463 L4_INLINE l4_msgtag_t
464 l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state,
465                          l4_utcb_t *utcb) L4_NOTHROW;
466
467 /**
468  * \brief Enable or disable the extended vCPU feature for the thread.
469  * \ingroup l4_thread_api
470  *
471  * \param thread The thread for which the extended vCPU feature shall be
472  *               enabled or disabled.
473  * \param vcpu_state The virtual address where the kernel shall store the vCPU
474  *                   state in case of vCPU exits. The address must be a valid
475  *                   kernel-user-memory address.
476  * \return Systemcall result message tag.
477  *
478  * The extended vCPU feature allows the use of hardware-virtualization
479  * features such as Intel's VT os AMD's SVM.
480  *
481  * This function enables the extended vCPU feature of the \a thread
482  * if \a vcpu_state is set to a valid kernel-user-memory address, or disables
483  * the vCPU feature if \a vcpu_state is 0.
484  *
485  */
486 L4_INLINE l4_msgtag_t
487 l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW;
488
489 /**
490  * \internal
491  * \ingroup l4_thread_api
492  */
493 L4_INLINE l4_msgtag_t
494 l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state,
495                              l4_utcb_t *utcb) L4_NOTHROW;
496
497
498 /**
499  * \brief Register an IRQ that will trigger upon deletion events.
500  * \ingroup l4_thread_api
501  *
502  * \param thread    Thread to register IRQ for.
503  * \param irq       Irq to register.
504  *
505  * \return System call result message tag.
506  */
507 L4_INLINE l4_msgtag_t
508 l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW;
509
510 /**
511  * \internal
512  * \ingroup l4_thread_api
513  */
514 L4_INLINE l4_msgtag_t
515 l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq,
516                              l4_utcb_t *utcb) L4_NOTHROW;
517
518 /**
519  * \brief Start a thread sender modifiction sequence.
520  * \ingroup l4_thread_api
521  *
522  * Add modification rules with l4_thread_modify_sender_add() and commit with
523  * l4_thread_modify_sender_commit(). Do not touch the UTCB between
524  * l4_thread_modify_sender_start() and l4_thread_modify_sender_commit().
525  *
526  * \see l4_thread_modify_sender_add
527  * \see l4_thread_modify_sender_commit
528  */
529 L4_INLINE l4_msgtag_t
530 l4_thread_modify_sender_start(void) L4_NOTHROW;
531
532 /**
533  * \internal
534  * \ingroup l4_thread_api
535  */
536 L4_INLINE l4_msgtag_t
537 l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW;
538
539 /**
540  * \brief Add a modification pattern to a sender modification sequence.
541  * \ingroup l4_thread_api
542  *
543  * \param tag        Tag received from l4_thread_modify_sender_start() or
544  *                   previous l4_thread_modify_sender_add() calls from
545  *                   the same sequence.
546  * \param match_mask Bitmask of bits to match the label.
547  * \param match      Bitmask that must be equal to the label after applying
548  *                   match_mask.
549  * \param del_bits   Bits to be deleted from the label.
550  * \param add_bits   Bits to be added to the label.
551  *
552  * \return 0 on sucess, <0 on error
553  *
554  * In pseudo code:
555  *   if ((sender_label & match_mask) == match)
556  *     { label = (label & ~del_bits) | add_bits; }
557  *
558  * Only the first match is applied.
559  *
560  * \see l4_thread_modify_sender_start
561  * \see l4_thread_modify_sender_commit
562  */
563 L4_INLINE int
564 l4_thread_modify_sender_add(l4_umword_t match_mask,
565                             l4_umword_t match,
566                             l4_umword_t del_bits,
567                             l4_umword_t add_bits,
568                             l4_msgtag_t *tag) L4_NOTHROW;
569
570 /**
571  * \internal
572  * \ingroup l4_thread_api
573  */
574 L4_INLINE int
575 l4_thread_modify_sender_add_u(l4_umword_t match_mask,
576                               l4_umword_t match,
577                               l4_umword_t del_bits,
578                               l4_umword_t add_bits,
579                               l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW;
580
581 /**
582  * \brief Apply (commit) a sender modification sequence.
583  * \ingroup l4_thread_api
584  *
585  * \see l4_thread_modify_sender_start
586  * \see l4_thread_modify_sender_add
587  */
588 L4_INLINE l4_msgtag_t
589 l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW;
590
591 /**
592  * \internal
593  * \ingroup l4_thread_api
594  */
595 L4_INLINE l4_msgtag_t
596 l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag,
597                                  l4_utcb_t *u) L4_NOTHROW;
598
599 /**
600  * \brief Operations on thread objects.
601  * \ingroup l4_thread_api
602  * \hideinitializer
603  * \internal
604  */
605 enum L4_thread_ops
606 {
607   L4_THREAD_CONTROL_OP            = 0UL,    /**< Control operation */
608   L4_THREAD_EX_REGS_OP            = 1UL,    /**< Exchange registers operation */
609   L4_THREAD_SWITCH_OP             = 2UL,    /**< Do a thread switch */
610   L4_THREAD_STATS_OP              = 3UL,    /**< Thread statistics */
611   L4_THREAD_VCPU_RESUME_OP        = 4UL,    /**< VCPU resume */
612   L4_THREAD_REGISTER_DELETE_IRQ   = 5UL,    /**< Register an IPC-gate deletion IRQ */
613   L4_THREAD_MODIFY_SENDER         = 6UL,    /**< Modify all senders IDs that match the given pattern */
614   L4_THREAD_VCPU_CONTROL          = 7UL,    /**< Enable / disable VCPU feature */
615   L4_THREAD_VCPU_CONTROL_EXT      = L4_THREAD_VCPU_CONTROL | 0x10000,
616   L4_THREAD_GDT_X86_OP            = 0x10UL, /**< Gdt */
617   L4_THREAD_OPCODE_MASK           = 0xffff, /**< Mask for opcodes */
618 };
619
620 /**
621  * \brief Flags for the thread control operation.
622  * \ingroup l4_thread_api
623  * \hideinitializer
624  * \internal
625  *
626  * Values for the enabled flags need to be given in their appropriate field
627  * in the UTCB,
628  * \see l4_thread_control
629  */
630 enum L4_thread_control_flags
631 {
632   /** The pager will be given. */
633   L4_THREAD_CONTROL_SET_PAGER       = 0x0010000,
634   /** The scheduler will be given. */
635   L4_THREAD_CONTROL_SET_SCHEDULER   = 0x0020000,
636   /** The task to bind the thread to will be given. */
637   L4_THREAD_CONTROL_BIND_TASK       = 0x0200000,
638   /** Alien state of the thread is set. */
639   L4_THREAD_CONTROL_ALIEN           = 0x0400000,
640   /** Fiasco-UX only: pass-through of host system calls is set. */
641   L4_THREAD_CONTROL_UX_NATIVE       = 0x0800000,
642   /** The exception handler of the thread will be given. */
643   L4_THREAD_CONTROL_SET_EXC_HANDLER = 0x1000000,
644 };
645
646 /**
647  * \brief Indices for the values in the message register for thread control.
648  * \ingroup l4_thread_api
649  * \hideinitializer
650  * \internal
651  *
652  * The values indicate the index in the message registers during
653  * thread-control operation.
654  */
655 enum L4_thread_control_mr_indices
656 {
657   L4_THREAD_CONTROL_MR_IDX_FLAGS       = 0, /**< \see #L4_thread_control_flags. */
658   L4_THREAD_CONTROL_MR_IDX_PAGER       = 1, /**< Index for pager cap */
659   L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER = 2, /**< Index for exception handler */
660   L4_THREAD_CONTROL_MR_IDX_SCHEDULER   = 3, /**< Index for scheduler */
661   L4_THREAD_CONTROL_MR_IDX_FLAG_VALS   = 4, /**< Index for feature values */
662   L4_THREAD_CONTROL_MR_IDX_BIND_UTCB   = 5, /**< Index for UTCB address for bind */
663   L4_THREAD_CONTROL_MR_IDX_BIND_TASK   = 6, /**< Index for task flex-page for bind */
664 };
665
666 /**
667  * \brief Flags for the thread ex-regs operation.
668  * \ingroup l4_thread_api
669  * \hideinitializer
670  */
671 enum L4_thread_ex_regs_flags
672 {
673   L4_THREAD_EX_REGS_CANCEL            = 0x10000UL, /**< Cancel ongoing IPC in the thread. */
674   L4_THREAD_EX_REGS_TRIGGER_EXCEPTION = 0x20000UL, /**< Trigger artificial exception in thread. */
675 };
676
677
678 /* IMPLEMENTATION -----------------------------------------------------------*/
679
680 #include <l4/sys/ipc.h>
681 #include <l4/sys/types.h>
682
683 L4_INLINE l4_msgtag_t
684 l4_thread_ex_regs_u(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
685                     l4_umword_t flags, l4_utcb_t *utcb) L4_NOTHROW
686 {
687   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
688   v->mr[0] = L4_THREAD_EX_REGS_OP | flags;
689   v->mr[1] = ip;
690   v->mr[2] = sp;
691   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 3, 0, 0), L4_IPC_NEVER);
692 }
693
694 L4_INLINE l4_msgtag_t
695 l4_thread_ex_regs_ret_u(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
696                         l4_umword_t *flags, l4_utcb_t *utcb) L4_NOTHROW
697 {
698   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
699   l4_msgtag_t ret = l4_thread_ex_regs_u(thread, *ip, *sp, *flags, utcb);
700   if (l4_error_u(ret, utcb))
701     return ret;
702
703   *flags = v->mr[0];
704   *ip    = v->mr[1];
705   *sp    = v->mr[2];
706   return ret;
707 }
708
709 L4_INLINE void
710 l4_thread_control_start_u(l4_utcb_t *utcb) L4_NOTHROW
711 {
712   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
713   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] = L4_THREAD_CONTROL_OP;
714 }
715
716 L4_INLINE void
717 l4_thread_control_pager_u(l4_cap_idx_t pager, l4_utcb_t *utcb) L4_NOTHROW
718 {
719   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
720   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_SET_PAGER;
721   v->mr[L4_THREAD_CONTROL_MR_IDX_PAGER]  = pager;
722 }
723
724 L4_INLINE void
725 l4_thread_control_exc_handler_u(l4_cap_idx_t exc_handler,
726                                 l4_utcb_t *utcb) L4_NOTHROW
727 {
728   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
729   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]       |= L4_THREAD_CONTROL_SET_EXC_HANDLER;
730   v->mr[L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER]  = exc_handler;
731 }
732
733 L4_INLINE void
734 l4_thread_control_scheduler_u(l4_cap_idx_t scheduler, l4_utcb_t *utcb) L4_NOTHROW
735 {
736   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
737   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_SET_SCHEDULER;
738   v->mr[L4_THREAD_CONTROL_MR_IDX_SCHEDULER]  = scheduler;
739 }
740
741 L4_INLINE void
742 l4_thread_control_bind_u(l4_utcb_t *thread_utcb, l4_cap_idx_t task,
743                          l4_utcb_t *utcb) L4_NOTHROW
744 {
745   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
746   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]         |= L4_THREAD_CONTROL_BIND_TASK;
747   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_UTCB]      = (l4_addr_t)thread_utcb;
748   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK]      = L4_ITEM_MAP;
749   v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK + 1]  = l4_obj_fpage(task, 0, L4_FPAGE_RWX).raw;
750 }
751
752 L4_INLINE void
753 l4_thread_control_alien_u(l4_utcb_t *utcb, int on) L4_NOTHROW
754 {
755   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
756   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_ALIEN;
757   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_ALIEN : 0;
758 }
759
760 L4_INLINE void
761 l4_thread_control_ux_host_syscall_u(l4_utcb_t *utcb, int on) L4_NOTHROW
762 {
763   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
764   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS]     |= L4_THREAD_CONTROL_UX_NATIVE;
765   v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_UX_NATIVE : 0;
766 }
767
768 L4_INLINE l4_msgtag_t
769 l4_thread_control_commit_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
770 {
771   int items = 0;
772   if (l4_utcb_mr_u(utcb)->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] & L4_THREAD_CONTROL_BIND_TASK)
773     items = 1;
774   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 6, items, 0), L4_IPC_NEVER);
775 }
776
777
778 L4_INLINE l4_msgtag_t
779 l4_thread_yield(void) L4_NOTHROW
780 {
781   l4_ipc_receive(L4_INVALID_CAP, NULL, L4_IPC_BOTH_TIMEOUT_0);
782   return l4_msgtag(0, 0, 0, 0);
783 }
784
785 /* Preliminary, to be changed */
786 L4_INLINE l4_msgtag_t
787 l4_thread_switch_u(l4_cap_idx_t to_thread, l4_utcb_t *utcb) L4_NOTHROW
788 {
789   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
790   v->mr[0] = L4_THREAD_SWITCH_OP;
791   return l4_ipc_call(to_thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER);
792 }
793
794
795 L4_INLINE l4_msgtag_t
796 l4_thread_stats_time_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW
797 {
798   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
799   v->mr[0] = L4_THREAD_STATS_OP;
800   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER);
801 }
802
803 L4_INLINE l4_msgtag_t
804 l4_thread_vcpu_resume_start_u(l4_utcb_t *utcb) L4_NOTHROW
805 {
806   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
807   v->mr[0] = L4_THREAD_VCPU_RESUME_OP;
808   return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0);
809 }
810
811 L4_INLINE l4_msgtag_t
812 l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread,
813                                l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
814 {
815   return l4_ipc_call(thread, utcb, tag, L4_IPC_NEVER);
816 }
817
818 L4_INLINE l4_msgtag_t
819 l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp,
820                     l4_umword_t flags) L4_NOTHROW
821 {
822   return l4_thread_ex_regs_u(thread, ip, sp, flags, l4_utcb());
823 }
824
825 L4_INLINE l4_msgtag_t
826 l4_thread_ex_regs_ret(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp,
827                       l4_umword_t *flags) L4_NOTHROW
828 {
829   return l4_thread_ex_regs_ret_u(thread, ip, sp, flags, l4_utcb());
830 }
831
832 L4_INLINE void
833 l4_thread_control_start(void) L4_NOTHROW
834 {
835   l4_thread_control_start_u(l4_utcb());
836 }
837
838 L4_INLINE void
839 l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW
840 {
841   l4_thread_control_pager_u(pager, l4_utcb());
842 }
843
844 L4_INLINE void
845 l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW
846 {
847   l4_thread_control_exc_handler_u(exc_handler, l4_utcb());
848 }
849
850 L4_INLINE void
851 l4_thread_control_scheduler(l4_cap_idx_t scheduler) L4_NOTHROW
852 {
853   l4_thread_control_scheduler_u(scheduler, l4_utcb());
854 }
855
856
857 L4_INLINE void
858 l4_thread_control_bind(l4_utcb_t *thread_utcb, l4_cap_idx_t task) L4_NOTHROW
859 {
860   l4_thread_control_bind_u(thread_utcb, task, l4_utcb());
861 }
862
863 L4_INLINE void
864 l4_thread_control_alien(int on) L4_NOTHROW
865 {
866   l4_thread_control_alien_u(l4_utcb(), on);
867 }
868
869 L4_INLINE void
870 l4_thread_control_ux_host_syscall(int on) L4_NOTHROW
871 {
872   l4_thread_control_ux_host_syscall_u(l4_utcb(), on);
873 }
874
875 L4_INLINE l4_msgtag_t
876 l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW
877 {
878   return l4_thread_control_commit_u(thread, l4_utcb());
879 }
880
881
882
883
884 L4_INLINE l4_msgtag_t
885 l4_thread_switch(l4_cap_idx_t to_thread) L4_NOTHROW
886 {
887   return l4_thread_switch_u(to_thread, l4_utcb());
888 }
889
890
891
892
893 L4_INLINE l4_msgtag_t
894 l4_thread_stats_time(l4_cap_idx_t thread) L4_NOTHROW
895 {
896   return l4_thread_stats_time_u(thread, l4_utcb());
897 }
898
899 L4_INLINE l4_msgtag_t
900 l4_thread_vcpu_resume_start(void) L4_NOTHROW
901 {
902   return l4_thread_vcpu_resume_start_u(l4_utcb());
903 }
904
905 L4_INLINE l4_msgtag_t
906 l4_thread_vcpu_resume_commit(l4_cap_idx_t thread,
907                              l4_msgtag_t tag) L4_NOTHROW
908 {
909   return l4_thread_vcpu_resume_commit_u(thread, tag, l4_utcb());
910 }
911
912
913 L4_INLINE l4_msgtag_t
914 l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq,
915                              l4_utcb_t *u) L4_NOTHROW
916 {
917   l4_msg_regs_t *m = l4_utcb_mr_u(u);
918   m->mr[0] = L4_THREAD_REGISTER_DELETE_IRQ;
919   m->mr[1] = l4_map_obj_control(0,0);
920   m->mr[2] = l4_obj_fpage(irq, 0, L4_CAP_FPAGE_RWS).raw;
921   return l4_ipc_call(thread, u, l4_msgtag(L4_PROTO_THREAD, 1, 1, 0), L4_IPC_NEVER);
922
923 }
924
925 L4_INLINE l4_msgtag_t
926 l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW
927 {
928   return l4_thread_register_del_irq_u(thread, irq, l4_utcb());
929 }
930
931
932 L4_INLINE l4_msgtag_t
933 l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state,
934                          l4_utcb_t *utcb) L4_NOTHROW
935 {
936   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
937   v->mr[0] = L4_THREAD_VCPU_CONTROL;
938   v->mr[1] = vcpu_state;
939   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER);
940 }
941
942 L4_INLINE l4_msgtag_t
943 l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW
944 { return l4_thread_vcpu_control_u(thread, vcpu_state, l4_utcb()); }
945
946
947 L4_INLINE l4_msgtag_t
948 l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state,
949                              l4_utcb_t *utcb) L4_NOTHROW
950 {
951   l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
952   v->mr[0] = L4_THREAD_VCPU_CONTROL_EXT;
953   v->mr[1] = ext_vcpu_state;
954   return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER);
955 }
956
957 L4_INLINE l4_msgtag_t
958 l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW
959 { return l4_thread_vcpu_control_ext_u(thread, ext_vcpu_state, l4_utcb()); }
960
961 L4_INLINE l4_msgtag_t
962 l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW
963 {
964   l4_msg_regs_t *m = l4_utcb_mr_u(u);
965   m->mr[0] = L4_THREAD_MODIFY_SENDER;
966   return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0);
967 }
968
969 L4_INLINE int
970 l4_thread_modify_sender_add_u(l4_umword_t match_mask,
971                               l4_umword_t match,
972                               l4_umword_t del_bits,
973                               l4_umword_t add_bits,
974                               l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW
975 {
976   l4_msg_regs_t *m = l4_utcb_mr_u(u);
977   unsigned w = l4_msgtag_words(*tag);
978   if (w >= L4_UTCB_GENERIC_DATA_SIZE - 4)
979     return -L4_ENOMEM;
980
981   m->mr[w]   = match_mask;
982   m->mr[w+1] = match;
983   m->mr[w+2] = del_bits;
984   m->mr[w+3] = add_bits;
985
986   *tag = l4_msgtag(l4_msgtag_label(*tag), w + 4, 0, 0);
987
988   return 0;
989 }
990
991 L4_INLINE l4_msgtag_t
992 l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag,
993                                  l4_utcb_t *u) L4_NOTHROW
994 {
995   return l4_ipc_call(thread, u, tag, L4_IPC_NEVER);
996 }
997
998 L4_INLINE l4_msgtag_t
999 l4_thread_modify_sender_start(void) L4_NOTHROW
1000 {
1001   return l4_thread_modify_sender_start_u(l4_utcb());
1002 }
1003
1004 L4_INLINE int
1005 l4_thread_modify_sender_add(l4_umword_t match_mask,
1006                             l4_umword_t match,
1007                             l4_umword_t del_bits,
1008                             l4_umword_t add_bits,
1009                             l4_msgtag_t *tag) L4_NOTHROW
1010 {
1011   return l4_thread_modify_sender_add_u(match_mask, match,
1012                                        del_bits, add_bits, tag, l4_utcb());
1013 }
1014
1015 L4_INLINE l4_msgtag_t
1016 l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW
1017 {
1018   return l4_thread_modify_sender_commit_u(thread, tag, l4_utcb());
1019 }