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