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#pragma once 14/** 15 * 16 * Builder functions for thread configs 17 * 18 */ 19 20#include <autoconf.h> 21#include <sel4utils/gen_config.h> 22#include <sel4/types.h> 23#include <simple/simple.h> 24#include <sel4utils/api.h> 25 26/* Threads and processes use this struct as both need scheduling config parameters */ 27typedef struct sched_params { 28 /* seL4 priority for the thread to be scheduled with. */ 29 uint8_t priority; 30 /* seL4 maximum controlled priority for the thread. */ 31 uint8_t mcp; 32 /* TCB to derive MCP from when setting priority/mcp (in future API) */ 33 seL4_CPtr auth; 34 /* true if sel4utils should create an sc */ 35 bool create_sc; 36 /* sel4 sched control cap for creating sc */ 37 seL4_CPtr sched_ctrl; 38 /* scheduling parameters */ 39 uint64_t period; 40 uint64_t budget; 41 seL4_Word extra_refills; 42 seL4_Word badge; 43 /* otherwise use this provided sc */ 44 seL4_CPtr sched_context; 45 /* affinity for this tcb. Must set sched_ctrl if CONFIG_RT */ 46 seL4_Word core; 47} sched_params_t; 48 49typedef struct sel4utils_thread_config { 50 /* fault_endpoint endpoint to set as the threads fault endpoint. Can be seL4_CapNull. */ 51 seL4_CPtr fault_endpoint; 52 /* root of the cspace to start the thread in */ 53 seL4_CNode cspace; 54 /* data for cspace access */ 55 seL4_Word cspace_root_data; 56 /* use a custom stack size? */ 57 bool custom_stack_size; 58 /* custom stack size in 4k pages for this thread */ 59 seL4_Word stack_size; 60 /* true if this thread should have no ipc buffer */ 61 bool no_ipc_buffer; 62 /* scheduling parameters */ 63 sched_params_t sched_params; 64 /* true if sel4utils should create a reply */ 65 bool create_reply; 66 /* otherwise provide one */ 67 seL4_CPtr reply; 68} sel4utils_thread_config_t; 69 70static inline sched_params_t sched_params_periodic(sched_params_t params, simple_t *simple, seL4_Word core, 71 uint64_t period_us, 72 uint64_t budget_us, seL4_Word extra_refills, seL4_Word badge) 73{ 74 if (!config_set(CONFIG_KERNEL_MCS)) { 75 ZF_LOGW("Setting sched params on non-RT kernel will have no effect"); 76 } 77 params.sched_ctrl = simple_get_sched_ctrl(simple, core); 78 params.period = period_us; 79 params.budget = budget_us; 80 params.extra_refills = extra_refills; 81 params.badge = badge; 82 params.create_sc = true; 83 return params; 84} 85 86static inline sched_params_t sched_params_round_robin(sched_params_t params, simple_t *simple, seL4_Word core, 87 uint64_t timeslice_us) 88{ 89 return sched_params_periodic(params, simple, core, timeslice_us, timeslice_us, 0, 0); 90} 91 92static inline sched_params_t sched_params_core(sched_params_t params, seL4_Word core) 93{ 94 if (!config_set(CONFIG_KERNEL_MCS)) { 95 ZF_LOGW("Setting core on RT kernel will have no effect - sched ctrl required"); 96 } 97 params.core = core; 98 return params; 99} 100 101static inline sel4utils_thread_config_t thread_config_create_reply(sel4utils_thread_config_t config) 102{ 103 config.create_reply = true; 104 return config; 105} 106 107static inline sel4utils_thread_config_t thread_config_reply(sel4utils_thread_config_t config, seL4_CPtr reply) 108{ 109 config.create_reply = false; 110 config.reply = reply; 111 return config; 112} 113 114static inline sel4utils_thread_config_t thread_config_sched_context(sel4utils_thread_config_t config, 115 seL4_CPtr sched_context) 116{ 117 config.sched_params.create_sc = false; 118 config.sched_params.sched_context = sched_context; 119 return config; 120} 121 122static inline sel4utils_thread_config_t thread_config_cspace(sel4utils_thread_config_t config, seL4_CPtr cspace_root, 123 seL4_Word cspace_root_data) 124{ 125 config.cspace = cspace_root; 126 config.cspace_root_data = cspace_root_data; 127 return config; 128} 129 130static inline sel4utils_thread_config_t thread_config_auth(sel4utils_thread_config_t config, seL4_CPtr tcb) 131{ 132 config.sched_params.auth = tcb; 133 return config; 134} 135 136static inline sel4utils_thread_config_t thread_config_new(simple_t *simple) 137{ 138 sel4utils_thread_config_t config = {0}; 139 seL4_Word data = api_make_guard_skip_word(seL4_WordBits - simple_get_cnode_size_bits(simple)); 140 config = thread_config_auth(config, simple_get_tcb(simple)); 141 return thread_config_cspace(config, simple_get_cnode(simple), data); 142} 143 144static inline sel4utils_thread_config_t thread_config_priority(sel4utils_thread_config_t config, uint8_t priority) 145{ 146 config.sched_params.priority = priority; 147 return config; 148} 149 150static inline sel4utils_thread_config_t thread_config_mcp(sel4utils_thread_config_t config, uint8_t mcp) 151{ 152 config.sched_params.mcp = mcp; 153 return config; 154} 155 156static inline sel4utils_thread_config_t thread_config_stack_size(sel4utils_thread_config_t config, seL4_Word size) 157{ 158 config.stack_size = size; 159 config.custom_stack_size = true; 160 return config; 161} 162 163static inline sel4utils_thread_config_t thread_config_no_ipc_buffer(sel4utils_thread_config_t config) 164{ 165 config.no_ipc_buffer = true; 166 return config; 167} 168 169static inline sel4utils_thread_config_t thread_config_fault_endpoint(sel4utils_thread_config_t config, 170 seL4_CPtr fault_ep) 171{ 172 config.fault_endpoint = fault_ep; 173 return config; 174} 175 176static inline sel4utils_thread_config_t thread_config_default(simple_t *simple, seL4_CPtr cnode, seL4_Word data, 177 seL4_CPtr fault_ep, uint8_t prio) 178{ 179 sel4utils_thread_config_t config = thread_config_new(simple); 180 config = thread_config_cspace(config, cnode, data); 181 config = thread_config_fault_endpoint(config, fault_ep); 182 config = thread_config_priority(config, prio); 183 if (config_set(CONFIG_KERNEL_MCS)) { 184 uint64_t timeslice = CONFIG_BOOT_THREAD_TIME_SLICE; 185 config.sched_params = sched_params_round_robin(config.sched_params, simple, 0, timeslice * US_IN_MS); 186 } 187 config = thread_config_create_reply(config); 188 return config; 189} 190