TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 1 | /* |
Anna Lyons | 9214341 | 2017-06-05 08:29:55 +1000 | [diff] [blame] | 2 | * Copyright 2017, Data61 |
| 3 | * Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| 4 | * ABN 41 687 119 230. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | * |
Anna Lyons | 9214341 | 2017-06-05 08:29:55 +1000 | [diff] [blame] | 10 | * @TAG(DATA61_BSD) |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | */ |
Anna Lyons | 135c651 | 2017-09-28 12:16:03 +1000 | [diff] [blame] | 21 | #pragma once |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 22 | |
| 23 | #include <autoconf.h> |
Yu Hou | e23dc54 | 2019-05-20 15:29:15 +1000 | [diff] [blame] | 24 | #include <sel4utils/gen_config.h> |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 25 | |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 26 | #include <sel4/sel4.h> |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 27 | #include <stdbool.h> |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 28 | #include <vka/vka.h> |
| 29 | |
| 30 | #include <vspace/vspace.h> |
Anna Lyons | e378dbc | 2017-07-10 16:07:09 +1000 | [diff] [blame] | 31 | #include <sel4utils/thread_config.h> |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 32 | |
Kofi Doku Atuah | d67465c | 2016-09-26 01:27:35 +1000 | [diff] [blame] | 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 | |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 39 | typedef struct sel4utils_thread { |
| 40 | vka_object_t tcb; |
Anna Lyons | e8088af | 2017-08-10 11:41:46 +1000 | [diff] [blame] | 41 | vka_object_t sched_context; |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 42 | void *stack_top; |
Alexander Wharton | 132a7a5 | 2016-09-21 14:24:44 +1000 | [diff] [blame] | 43 | void *initial_stack_pointer; |
Anna Lyons | 8e73b44 | 2016-07-06 11:28:14 +1000 | [diff] [blame] | 44 | size_t stack_size; |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 45 | seL4_CPtr ipc_buffer; |
| 46 | seL4_Word ipc_buffer_addr; |
Anna Lyons | e8088af | 2017-08-10 11:41:46 +1000 | [diff] [blame] | 47 | bool own_sc; |
Anna Lyons | ba1db81 | 2017-08-10 12:30:15 +1000 | [diff] [blame] | 48 | bool own_reply; |
| 49 | vka_object_t reply; |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 50 | } sel4utils_thread_t; |
| 51 | |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 52 | typedef struct sel4utils_checkpoint { |
Anna Lyons | dbec951 | 2018-08-28 13:32:41 +1000 | [diff] [blame] | 53 | /* checkpointed stack */ |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 54 | void *stack; |
| 55 | seL4_UserContext regs; |
| 56 | sel4utils_thread_t *thread; |
Anna Lyons | e76b359 | 2018-08-28 17:01:55 +1000 | [diff] [blame] | 57 | /* stack pointer this checkpoint preserves */ |
| 58 | uintptr_t sp; |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 59 | } sel4utils_checkpoint_t; |
| 60 | |
Stephen Sherratt | 857ffba | 2017-03-16 13:39:29 +1100 | [diff] [blame] | 61 | typedef void (*sel4utils_thread_entry_fn)(void *arg0, void *arg1, void *ipc_buf); |
| 62 | |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 63 | /** |
Anna Lyons | e378dbc | 2017-07-10 16:07:09 +1000 | [diff] [blame] | 64 | * Configure a thread, allocating any resources required. The thread will start at priority 0. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 65 | * |
Anna Lyons | e8088af | 2017-08-10 11:41:46 +1000 | [diff] [blame] | 66 | * If CONFIG_RT is enabled, the thread will not have a scheduling context, so it will not be able to run. |
| 67 | * |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 68 | * @param vka initialised vka to allocate objects with |
Adrian Danis | c5f81c1 | 2014-08-28 11:10:33 +1000 | [diff] [blame] | 69 | * @param parent vspace structure of the thread calling this function, used for temporary mappings |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | */ |
Adrian Danis | c5f81c1 | 2014-08-28 11:10:33 +1000 | [diff] [blame] | 79 | int sel4utils_configure_thread(vka_t *vka, vspace_t *parent, vspace_t *alloc, seL4_CPtr fault_endpoint, |
Adrian Danis | 08f9b7c | 2017-10-05 15:48:18 +1100 | [diff] [blame] | 80 | seL4_CNode cspace, seL4_Word cspace_root_data, |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 81 | sel4utils_thread_t *res); |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 82 | |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 83 | /** |
Anna Lyons | 1b987fc | 2014-10-14 11:22:03 +1100 | [diff] [blame] | 84 | * As per sel4utils_configure_thread, but using a config struct. |
| 85 | */ |
| 86 | int sel4utils_configure_thread_config(vka_t *vka, vspace_t *parent, vspace_t *alloc, |
| 87 | sel4utils_thread_config_t config, sel4utils_thread_t *res); |
| 88 | |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 96 | * |
| 97 | * NOTE: In order for the on-stack argument passing to work for ia32, |
| 98 | * entry points must be functions. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | * } |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 106 | * |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | */ |
Stephen Sherratt | 4aad820 | 2017-03-16 13:44:09 +1100 | [diff] [blame] | 133 | int sel4utils_start_thread(sel4utils_thread_t *thread, sel4utils_thread_entry_fn entry_point, |
| 134 | void *arg0, void *arg1, int resume); |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | */ |
| 144 | void sel4utils_clean_up_thread(vka_t *vka, vspace_t *alloc, sel4utils_thread_t *thread); |
| 145 | |
| 146 | /** |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 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 | * |
Anna Lyons | e76b359 | 2018-08-28 17:01:55 +1000 | [diff] [blame] | 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. |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 158 | * |
| 159 | * @param thread the thread to checkpoint |
| 160 | * @param checkpoint pointer to uninitialised checkpoint struct |
Anna Lyons | 0016dfc | 2017-07-14 09:40:34 +1000 | [diff] [blame] | 161 | * @param suspend true if the thread should be suspended |
| 162 | * |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 163 | * @return 0 on success. |
| 164 | */ |
| 165 | int sel4utils_checkpoint_thread(sel4utils_thread_t *thread, sel4utils_checkpoint_t *checkpoint, bool suspend); |
| 166 | |
| 167 | /** |
Anna Lyons | 0016dfc | 2017-07-14 09:40:34 +1000 | [diff] [blame] | 168 | * Rollback a thread to a previous checkpoint, restoring its register set and stack. |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 169 | * |
Anna Lyons | 0016dfc | 2017-07-14 09:40:34 +1000 | [diff] [blame] | 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. |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 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. |
Anna Lyons | 0016dfc | 2017-07-14 09:40:34 +1000 | [diff] [blame] | 176 | * @param resume true if the thread should be resumed immediately. |
Anna Lyons | 41ca0a6 | 2015-10-23 13:59:45 +1100 | [diff] [blame] | 177 | * |
| 178 | * @return 0 on success. |
| 179 | */ |
| 180 | int sel4utils_checkpoint_restore(sel4utils_checkpoint_t *checkpoint, bool free, bool resume); |
| 181 | |
| 182 | /** |
| 183 | * Clean up a previously allocated checkpoint. |
| 184 | */ |
| 185 | void sel4utils_free_checkpoint(sel4utils_checkpoint_t *checkpoint); |
| 186 | |
| 187 | /** |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 188 | * Start a fault handling thread that will print the name of the thread that faulted |
Anna Lyons | e378dbc | 2017-07-10 16:07:09 +1000 | [diff] [blame] | 189 | * as well as debugging information. The thread will start at priority 0. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 190 | * |
Anna Lyons | e8088af | 2017-08-10 11:41:46 +1000 | [diff] [blame] | 191 | * If CONFIG_RT it be passive (not have a scheulding context) and will run on the SC of the faulter. |
| 192 | * |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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). |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 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 | */ |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 203 | int sel4utils_start_fault_handler(seL4_CPtr fault_endpoint, vka_t *vka, vspace_t *vspace, |
Adrian Danis | 08f9b7c | 2017-10-05 15:48:18 +1100 | [diff] [blame] | 204 | seL4_CPtr cspace, seL4_Word data, char *name, sel4utils_thread_t *res); |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 205 | |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 206 | /** |
Matthew Fernandez | a8cfaf5 | 2015-03-19 09:46:57 +1100 | [diff] [blame] | 207 | * Pretty print a fault message. |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 208 | * |
| 209 | * @param tag the message info tag delivered by the fault. |
Anna Lyons | 3ec60c8 | 2014-10-16 09:37:48 +1100 | [diff] [blame] | 210 | * @param name thread name |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 211 | */ |
Adrian Danis | 889675f | 2015-01-13 11:36:17 +1100 | [diff] [blame] | 212 | void sel4utils_print_fault_message(seL4_MessageInfo_t tag, const char *name); |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 213 | |
Anna Lyons | 8ba9fcd | 2017-12-20 12:20:05 +1100 | [diff] [blame] | 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 | * |
Kent McLeod | 38a475d | 2019-08-21 16:41:58 +1000 | [diff] [blame^] | 219 | * If CONFIG_KERNEL_MCS is set, the sched params must be fully populated or the scheduling |
Anna Lyons | 8ba9fcd | 2017-12-20 12:20:05 +1100 | [diff] [blame] | 220 | * context will be empty when it changes core as scheduling parameters of scheduling |
| 221 | * contexts are not maintained across migrations. |
| 222 | */ |
| 223 | int sel4utils_set_sched_affinity(sel4utils_thread_t *thread, sched_params_t params); |
| 224 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 225 | static inline seL4_TCB sel4utils_get_tcb(sel4utils_thread_t *thread) |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 226 | { |
| 227 | return thread->tcb.cptr; |
| 228 | } |
| 229 | |
Yu Hou | e9a9ff4 | 2019-07-18 17:26:01 +1000 | [diff] [blame] | 230 | static inline int sel4utils_suspend_thread(sel4utils_thread_t *thread) |
TrustworthySystems | b85c30b | 2014-07-22 14:11:33 +1000 | [diff] [blame] | 231 | { |
| 232 | return seL4_TCB_Suspend(thread->tcb.cptr); |
| 233 | } |
| 234 | |