1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * 15 * Provides basic thread configuration/starting/cleanup functions. 16 * 17 * Any other operations (start, stop, resume) should use the seL4 API directly on 18 * sel4utils_thread_t->tcb.cptr. 19 * 20 */ 21#pragma once 22 23#include <autoconf.h> 24#include <sel4utils/gen_config.h> 25 26#include <sel4/sel4.h> 27#include <stdbool.h> 28#include <vka/vka.h> 29 30#include <vspace/vspace.h> 31#include <sel4utils/thread_config.h> 32 33#ifdef CONFIG_DEBUG_BUILD 34#define NAME_THREAD(_tcbcap, _name) seL4_DebugNameThread(_tcbcap, _name); 35#else 36#define NAME_THREAD(_tcbcap, _name) 37#endif 38 39typedef struct sel4utils_thread { 40 vka_object_t tcb; 41 vka_object_t sched_context; 42 void *stack_top; 43 void *initial_stack_pointer; 44 size_t stack_size; 45 seL4_CPtr ipc_buffer; 46 seL4_Word ipc_buffer_addr; 47 bool own_sc; 48 bool own_reply; 49 vka_object_t reply; 50} sel4utils_thread_t; 51 52typedef struct sel4utils_checkpoint { 53 /* checkpointed stack */ 54 void *stack; 55 seL4_UserContext regs; 56 sel4utils_thread_t *thread; 57 /* stack pointer this checkpoint preserves */ 58 uintptr_t sp; 59} sel4utils_checkpoint_t; 60 61typedef void (*sel4utils_thread_entry_fn)(void *arg0, void *arg1, void *ipc_buf); 62 63/** 64 * Configure a thread, allocating any resources required. The thread will start at priority 0. 65 * 66 * If CONFIG_RT is enabled, the thread will not have a scheduling context, so it will not be able to run. 67 * 68 * @param vka initialised vka to allocate objects with 69 * @param parent vspace structure of the thread calling this function, used for temporary mappings 70 * @param alloc initialised vspace structure to allocate virtual memory with 71 * @param fault_endpoint endpoint to set as the threads fault endpoint. Can be 0. 72 * @param cspace the root of the cspace to start the thread in 73 * @param cspace_root_data data for cspace access 74 * @param res an uninitialised sel4utils_thread_t data structure that will be initialised 75 * after this operation. 76 * 77 * @return 0 on success, -1 on failure. Use CONFIG_DEBUG to see error messages. 78 */ 79int sel4utils_configure_thread(vka_t *vka, vspace_t *parent, vspace_t *alloc, seL4_CPtr fault_endpoint, 80 seL4_CNode cspace, seL4_Word cspace_root_data, 81 sel4utils_thread_t *res); 82 83/** 84 * As per sel4utils_configure_thread, but using a config struct. 85 */ 86int sel4utils_configure_thread_config(vka_t *vka, vspace_t *parent, vspace_t *alloc, 87 sel4utils_thread_config_t config, sel4utils_thread_t *res); 88 89/** 90 * Start a thread, allocating any resources required. 91 * The third argument to the thread (in r2 for arm, on stack for ia32) will be the 92 * address of the ipc buffer. 93 * 94 * @param thread thread data structure that has been initialised with sel4utils_configure_thread 95 * @param entry_point the address that the thread will start at 96 * 97 * NOTE: In order for the on-stack argument passing to work for ia32, 98 * entry points must be functions. 99 * 100 * ie. jumping to this start symbol will work: 101 * 102 * void _start(int argc, char **argv) { 103 * int ret = main(argc, argv); 104 * exit(ret); 105 * } 106 * 107 * 108 * However, jumping to a start symbol like this: 109 * 110 * _start: 111 * call main 112 * 113 * will NOT work, as call pushes an extra value (the return value) 114 * onto the stack. If you really require an assembler stub, it should 115 * decrement the stack value to account for this. 116 * 117 * ie. 118 * 119 * _start: 120 * popl %eax 121 * call main 122 * 123 * This does not apply for arm, as arguments are passed in registers. 124 * 125 * 126 * @param arg0 a pointer to the arguments for this thread. User decides the protocol. 127 * @param arg1 another pointer. User decides the protocol. Note that there are two args here 128 * to easily support C standard: int main(int argc, char **argv). 129 * @param resume 1 to start the thread immediately, 0 otherwise. 130 * 131 * @return 0 on success, -1 on failure. 132 */ 133int sel4utils_start_thread(sel4utils_thread_t *thread, sel4utils_thread_entry_fn entry_point, 134 void *arg0, void *arg1, int resume); 135 136/** 137 * Release any resources used by this thread. The thread data structure will not be usable 138 * until sel4utils_thread_configure is called again. 139 * 140 * @param vka the vka interface that this thread was initialised with 141 * @param alloc the allocation interface that this thread was initialised with 142 * @param thread the thread structure that was returned when the thread started 143 */ 144void sel4utils_clean_up_thread(vka_t *vka, vspace_t *alloc, sel4utils_thread_t *thread); 145 146/** 147 * Checkpoint a thread at its current state, storing its current register set and stack. 148 * 149 * Note that the heap state is not saved, so threads intending to use this functionality 150 * should not mutate the heap or other state beyond the checkpoint, unless extra functionality 151 * is included to roll these back. 152 * 153 * This should not be called on a currently running thread, and is designed to be called on 154 * threads which are known to be blocked on an seL4_Recv, for checkpointing passive threads on 155 * the mcs kernel (threads without scheduling contexts). The checkpoint is set up that such a 156 * thread can be restarted successfully at the instruction which enters the kernel, with 157 * register state set up specifically for that. 158 * 159 * @param thread the thread to checkpoint 160 * @param checkpoint pointer to uninitialised checkpoint struct 161 * @param suspend true if the thread should be suspended 162 * 163 * @return 0 on success. 164 */ 165int sel4utils_checkpoint_thread(sel4utils_thread_t *thread, sel4utils_checkpoint_t *checkpoint, bool suspend); 166 167/** 168 * Rollback a thread to a previous checkpoint, restoring its register set and stack. 169 * 170 * This is not atomic and callers should make sure the target thread is stopped or that the 171 * caller is higher priority such that the target is not switched to by the kernel mid-restore. 172 * 173 * @param checkpoint the previously saved checkpoint to restore. 174 * @param free true if this checkpoint should free all memory allocated, i.e if the checkpoint 175 * will not be used again. 176 * @param resume true if the thread should be resumed immediately. 177 * 178 * @return 0 on success. 179 */ 180int sel4utils_checkpoint_restore(sel4utils_checkpoint_t *checkpoint, bool free, bool resume); 181 182/** 183 * Clean up a previously allocated checkpoint. 184 */ 185void sel4utils_free_checkpoint(sel4utils_checkpoint_t *checkpoint); 186 187/** 188 * Start a fault handling thread that will print the name of the thread that faulted 189 * as well as debugging information. The thread will start at priority 0. 190 * 191 * If CONFIG_RT it be passive (not have a scheulding context) and will run on the SC of the faulter. 192 * 193 * @param fault_endpoint the fault_endpoint to wait on 194 * @param vka allocator 195 * @param vspace vspace (this library must be mapped into that vspace). 196 * @param cspace the cspace that the fault_endpoint is in 197 * @param data the cspace_data for that cspace (with correct guard) 198 * @param name the name of the thread to print if it faults 199 * @param thread the thread data structure to populate 200 * 201 * @return 0 on success. 202 */ 203int sel4utils_start_fault_handler(seL4_CPtr fault_endpoint, vka_t *vka, vspace_t *vspace, 204 seL4_CPtr cspace, seL4_Word data, char *name, sel4utils_thread_t *res); 205 206/** 207 * Pretty print a fault message. 208 * 209 * @param tag the message info tag delivered by the fault. 210 * @param name thread name 211 */ 212void sel4utils_print_fault_message(seL4_MessageInfo_t tag, const char *name); 213 214/* Set the affinity of a thread, which will cause migration if the thread 215 * is running on a different core. 216 * 217 * On master, only use sched_params_set_core to set the core then call this function. 218 * 219 * If CONFIG_KERNEL_MCS is set, the sched params must be fully populated or the scheduling 220 * context will be empty when it changes core as scheduling parameters of scheduling 221 * contexts are not maintained across migrations. 222 */ 223int sel4utils_set_sched_affinity(sel4utils_thread_t *thread, sched_params_t params); 224 225static inline seL4_TCB sel4utils_get_tcb(sel4utils_thread_t *thread) 226{ 227 return thread->tcb.cptr; 228} 229 230static inline int sel4utils_suspend_thread(sel4utils_thread_t *thread) 231{ 232 return seL4_TCB_Suspend(thread->tcb.cptr); 233} 234 235