1// vi:set ft=cpp: -*- Mode: C++ -*-
2/**
3 * \file
4 * Common thread related definitions.
5 */
6/*
7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8 *               Alexander Warg <warg@os.inf.tu-dresden.de>
9 *     economic rights: Technische Universität Dresden (Germany)
10 *
11 * This file is part of TUD:OS and distributed under the terms of the
12 * GNU General Public License 2.
13 * Please see the COPYING-GPL-2 file for details.
14 *
15 * As a special exception, you may use this file as part of a free software
16 * library without restriction.  Specifically, if other files instantiate
17 * templates or use macros or inline functions from this file, or you compile
18 * this file and link it with other files to produce an executable, this
19 * file does not by itself cause the resulting executable to be covered by
20 * the GNU General Public License.  This exception does not however
21 * invalidate any other reasons why the executable file might be covered by
22 * the GNU General Public License.
23 */
24
25#pragma once
26
27#include <l4/sys/capability>
28#include <l4/sys/thread.h>
29
30namespace L4 {
31
32/**
33 * C++ L4 kernel thread interface.
34 *
35 * The Thread class defines a thread of execution in the L4 context.
36 * Usually user-level and kernel threads are mapped 1:1 to each other.
37 * Thread kernel objects are created using a factory, see the L4::Factory API
38 * (L4::Factory::create()).
39 *
40 * Amongst other things an L4::Thread encapsulates:
41 * - CPU state
42 *   - General-purpose registers
43 *   - Program counter
44 *   - Stack pointer
45 * - FPU state
46 * - Scheduling parameters, see the L4::Scheduler API
47 * - Execution state
48 *   - Blocked, Runnable, Running
49 *
50 * Thread objects provide an API for
51 * - Thread configuration and manipulation
52 * - Thread switching.
53 *
54 * \includefile{l4/sys/thread}
55 *
56 * For the C interface see the \ref l4_thread_api API.
57 */
58class Thread :
59  public Kobject_t<Thread, Kobject, L4_PROTO_THREAD,
60                   Type_info::Demand_t<1> >
61{
62public:
63  /**
64   * Exchange basic thread registers.
65   *
66   * \param ip     New instruction pointer, use ~0UL to leave the
67   *               instruction pointer unchanged.
68   * \param sp     New stack pointer, use ~0UL to leave the stack
69   *               pointer unchanged.
70   * \param flags  Ex-regs flags, see #L4_thread_ex_regs_flags.
71   * \param utcb   UTCB to use for this operation.
72   *
73   * \return System call return tag
74   *
75   * This method allows to manipulate a thread. The basic functionality is to
76   * set the instruction pointer and the stack pointer of a thread.
77   * Additionally, this method allows also to cancel ongoing IPC operations and
78   * to force the thread to raise an artificial exception (see `flags`).
79   *
80   * The thread is started using L4::Scheduler::run_thread(). However, if at
81   * the time L4::Scheduler::run_thread() is called, the instruction pointer of
82   * the thread is invalid, a later call to ex_regs() with a valid instruction
83   * pointer might start the thread.
84   */
85  l4_msgtag_t ex_regs(l4_addr_t ip, l4_addr_t sp,
86                      l4_umword_t flags,
87                      l4_utcb_t *utcb = l4_utcb()) noexcept
88  { return l4_thread_ex_regs_u(cap(), ip, sp, flags, utcb); }
89
90  /**
91   * Exchange basic thread registers and return previous values.
92   *
93   * \param[in,out] ip     New instruction pointer, use ~0UL to leave the
94   *                       instruction pointer unchanged, return previous
95   *                       instruction pointer.
96   * \param[in,out] sp     New stack pointer, use ~0UL to leave the stack
97   *                       pointer unchanged, returns previous stack pointer.
98   * \param[in,out] flags  Ex-regs flags, see #L4_thread_ex_regs_flags, return
99   *                       previous CPU flags of the thread.
100   * \param         utcb   UTCB to use for this operation.
101   *
102   * \return System call return tag. [out] parameters are only valid if the
103   *         function returns successfully. Use l4_error() to check.
104   *
105   * This method allows to manipulate and start a thread. The basic
106   * functionality is to set the instruction pointer and the stack pointer of a
107   * thread. Additionally, this method allows also to cancel ongoing IPC
108   * operations and to force the thread to raise an artificial exception (see
109   * `flags`).
110   */
111  l4_msgtag_t ex_regs(l4_addr_t *ip, l4_addr_t *sp,
112                      l4_umword_t *flags,
113                      l4_utcb_t *utcb = l4_utcb()) noexcept
114  { return l4_thread_ex_regs_ret_u(cap(), ip, sp, flags, utcb); }
115
116
117  /**
118   * Thread attributes used for control_commit().
119   *
120   * This class is responsible for initializing various attributes of a
121   * thread in a UTCB for the control_commit() method.
122   *
123   * \note Instantiation of this class starts the preparation of the UTCB. Do
124   *       not invoke any non-Attr functions between the instantiation and the
125   *       call to `L4::Thread::control()`.
126   *
127   * \see \ref l4_thread_control_api for some more details.
128   */
129  class Attr
130  {
131  private:
132     friend class L4::Thread;
133     l4_utcb_t *_u;
134
135   public:
136     /**
137      * Create a thread-attribute object with the given UTCB.
138      *
139      * \param utcb  The UTCB to use for the later L4::Thread::control_commit()
140      *              function. Usually this is the UTCB of the calling thread.
141      */
142     explicit Attr(l4_utcb_t *utcb = l4_utcb()) noexcept : _u(utcb)
143     { l4_thread_control_start_u(utcb); }
144
145     /**
146      * Set the pager capability selector.
147      *
148      * \param pager  The capability selector that shall be used for page-fault
149      *               messages. This capability selector must be valid within
150      *               the task the thread is bound to.
151      */
152     void pager(Cap<void> const &pager) noexcept
153     { l4_thread_control_pager_u(pager.cap(), _u); }
154
155     /**
156      * Get the capability selector used for page-fault messages.
157      *
158      * \return The capability selector used to send page-fault messages. The
159      *         selector is valid in the task the thread is bound to.
160      */
161     Cap<void> pager() noexcept
162     { return Cap<void>(l4_utcb_mr_u(_u)->mr[1]); }
163
164     /**
165      * Set the exception-handler capability selector.
166      *
167      * \param exc_handler  The capability selector that shall be used for
168      *                     exception messages. This capability selector must
169      *                     be valid within the task the thread is bound to.
170      */
171     void exc_handler(Cap<void> const &exc_handler) noexcept
172     { l4_thread_control_exc_handler_u(exc_handler.cap(), _u); }
173
174     /**
175      * Get the capability selector used for exception messages.
176      *
177      * \return The capability selector used to send exception messages. The
178      *         selector is valid in the task the thread is bound to.
179      */
180     Cap<void> exc_handler() noexcept
181     { return Cap<void>(l4_utcb_mr_u(_u)->mr[2]); }
182
183     /**
184      * Bind the thread to a task.
185      *
186      * \param thread_utcb  The thread’s UTCB address within the task it shall
187      *                     be bound to. The address must be aligned
188      *                     (architecture dependent; at least word aligned) and
189      *                     it must point to at least #L4_UTCB_OFFSET bytes of
190      *                     kernel-user memory.
191      * \param task         The task the thread shall be bound to.
192      *
193      * A thread may execute code in the context of a task if and only if the
194      * thread is bound to the task. To actually start execution,
195      * L4::Thread::ex_regs() needs to be used. Execution in the context of the
196      * task means that the code has access to all the task’s resources (and
197      * only those). The executed code itself must be one of those resources. A
198      * thread can be bound at most once to a task.
199      *
200      * \note The UTCBs of different threads in the same task should not overlap
201      *       in order to prevent data corruption.
202      */
203     void bind(l4_utcb_t *thread_utcb, Cap<Task> const &task) noexcept
204     { l4_thread_control_bind_u(thread_utcb, task.cap(), _u); }
205
206     /**
207      * Set the thread to alien mode.
208      */
209     void alien(int on) noexcept
210     { l4_thread_control_alien_u(_u, on); }
211
212     /**
213      * Allow host system calls on Fiasco-UX.
214      *
215      * \pre Running on Fiasco-UX.
216      */
217     void ux_host_syscall(int on) noexcept
218     { l4_thread_control_ux_host_syscall_u(_u, on); }
219
220   };
221
222  /**
223   * Commit the given thread-attributes object.
224   *
225   * \param attr the attribute object to commit to the thread.
226   */
227  l4_msgtag_t control(Attr const &attr) noexcept
228  { return l4_thread_control_commit_u(cap(), attr._u); }
229
230  /**
231   * Switch execution to this thread.
232   *
233   * \param utcb the UTCB of the current thread.
234   *
235   * \note The current time slice is inherited to this thread.
236   */
237  l4_msgtag_t switch_to(l4_utcb_t *utcb = l4_utcb()) noexcept
238  { return l4_thread_switch_u(cap(), utcb); }
239
240  /**
241   * Get consumed time of thread in us.
242   *
243   * \param[out] us    Consumed time in µs.
244   * \param      utcb  UTCB of the current thread.
245   *
246   * \return Syscall return tag.
247   */
248  l4_msgtag_t stats_time(l4_kernel_clock_t *us,
249                         l4_utcb_t *utcb = l4_utcb()) noexcept
250  { return l4_thread_stats_time_u(cap(), us, utcb); }
251
252  /**
253   * Resume from vCPU asynchronous IPC handler, start.
254   *
255   * The asynchronous IPC handling is described at \ref l4_vcpu_api.
256   *
257   * \see l4_thread_vcpu_resume_start
258   */
259  l4_msgtag_t vcpu_resume_start(l4_utcb_t *utcb = l4_utcb()) noexcept
260  { return l4_thread_vcpu_resume_start_u(utcb); }
261
262  /**
263   * Resume from vCPU asynchronous IPC handler, commit.
264   *
265   * The asynchronous IPC handling is described at \ref l4_vcpu_api.
266   *
267   * \see l4_thread_vcpu_resume_commit
268   */
269  l4_msgtag_t vcpu_resume_commit(l4_msgtag_t tag,
270                                 l4_utcb_t *utcb = l4_utcb()) noexcept
271  { return l4_thread_vcpu_resume_commit_u(cap(), tag, utcb); }
272
273   /**
274    * Enable or disable the vCPU feature for the thread.
275    *
276    * \param vcpu_state  A virtual address pointing to a l4_vcpu_state_t or 0.
277    *                    If not 0, it must be a valid kernel-user-memory address
278    *                    (see L4::Task::add_ku_mem()).
279    * \param utcb        UTCB to use for this operation.
280    *
281    * \return Syscall return tag.
282    *
283    * This function enables the vCPU feature of `this` thread if `vcpu_state`
284    * is set to a valid kernel-user-memory address, or disables the vCPU
285    * feature if `vcpu_state` is 0. (Disable: optional, currently unsupported.)
286    *
287    * The asynchronous IPC handling is described at \ref l4_vcpu_api.
288    */
289   l4_msgtag_t vcpu_control(l4_addr_t vcpu_state, l4_utcb_t *utcb = l4_utcb())
290     noexcept
291   { return l4_thread_vcpu_control_u(cap(), vcpu_state, utcb); }
292
293   /**
294    * Enable or disable the extended vCPU feature for the thread.
295    *
296    * \param ext_vcpu_state  The virtual address where the kernel shall store
297    *                        the vCPU state in case of vCPU exits. The address
298    *                        must be a valid kernel-user-memory address (see
299    *                        L4::Task::add_ku_mem()).
300    * \param utcb            UTCB to use for this operation.
301    *
302    * \return Syscall return tag.
303    *
304    * The extended vCPU feature allows the use of hardware-virtualization
305    * features such as Intel's VT or AMD's SVM.
306    *
307    * This function enables the extended vCPU feature of `this` thread
308    * if `ext_vcpu_state` is set to a valid kernel-user-memory address, or
309    * disables the vCPU feature if `ext_vcpu_state` is 0.
310    *
311    * \note The extended vCPU mode includes the normal vCPU mode.
312    */
313   l4_msgtag_t vcpu_control_ext(l4_addr_t ext_vcpu_state,
314                                l4_utcb_t *utcb = l4_utcb()) noexcept
315   { return l4_thread_vcpu_control_ext_u(cap(), ext_vcpu_state, utcb); }
316
317  /**
318   * Register an IRQ that will trigger upon deletion events.
319   *
320   * \param irq  Capability selector for the IRQ object to be triggered.
321   * \utcb{u}
322   *
323   * \return System call return tag containing the return code.
324   *
325   * List of deletion events:
326   *   * deletion of an IPC gate bound to this thread.
327   *
328   * \see l4_thread_register_del_irq
329   */
330  l4_msgtag_t register_del_irq(Cap<Irq> irq, l4_utcb_t *u = l4_utcb()) noexcept
331  { return l4_thread_register_del_irq_u(cap(), irq.cap(), u); }
332
333  /**
334   * Class wrapping a list of rules which modify the sender label of IPC
335   * messages inbound to this thread.
336   *
337   * Use the add() function to add modification rules, and use
338   * modify_senders() to commit. Do not use the UTCB in between as it is
339   * used by add() and modify_senders().
340   */
341  class Modify_senders
342  {
343  private:
344    friend class Thread;
345    l4_utcb_t *utcb;
346    unsigned cnt;
347
348  public:
349    explicit Modify_senders(l4_utcb_t *u = l4_utcb()) noexcept
350    : utcb(u), cnt(1)
351    {
352      l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_MODIFY_SENDER_OP;
353    }
354
355    /**
356     * Add a rule.
357     *
358     * \param match_mask Bitmask of bits to match the label.
359     * \param match      Bitmask that must be equal to the label after applying
360     *                   match_mask.
361     * \param del_bits   Bits to be deleted from the label.
362     * \param add_bits   Bits to be added to the label.
363     *
364     * \return 0 on success, <0 on error
365     *
366     * In pseudo code:
367     *   if ((sender_label & match_mask) == match)
368     *     { sender_label = (sender_label & ~del_bits) | add_bits; }
369     *
370     * Only the first match is applied.
371     *
372     * \see l4_thread_modify_sender_add()
373     */
374    int add(l4_umword_t match_mask, l4_umword_t match,
375            l4_umword_t del_bits, l4_umword_t add_bits) noexcept
376    {
377      l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
378      if (cnt >= L4_UTCB_GENERIC_DATA_SIZE - 4)
379        return -L4_ENOMEM;
380      m->mr[cnt++] = match_mask;
381      m->mr[cnt++] = match;
382      m->mr[cnt++] = del_bits;
383      m->mr[cnt++] = add_bits;
384      return 0;
385    }
386  };
387
388  /**
389   * Apply sender modification rules.
390   *
391   * \param todo  Prepared sender modification rules.
392   *
393   * \return System call return tag.
394   *
395   * The modification rules are applied to all IPCs to the thread (whether
396   * directly or by IPC gate) that are already in flight, that is that the sender
397   * is already blocking on.
398   *
399   * \see l4_thread_modify_sender_commit()
400   */
401  l4_msgtag_t modify_senders(Modify_senders const &todo) noexcept
402  {
403    return l4_ipc_call(cap(), todo.utcb, l4_msgtag(L4_PROTO_THREAD, todo.cnt, 0, 0), L4_IPC_NEVER);
404  }
405};
406}
407