1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <types.h> 10#include <api/failures.h> 11#include <object/structures.h> 12 13#include <machine/registerset.h> 14#include <object/cnode.h> 15 16#ifdef CONFIG_DEBUG_BUILD 17/* Maximum length of the tcb name, including null terminator */ 18#define TCB_NAME_LENGTH (BIT(seL4_TCBBits-1) - (tcbCNodeEntries * sizeof(cte_t)) - sizeof(debug_tcb_t)) 19compile_assert(tcb_name_fits, TCB_NAME_LENGTH > 0) 20#endif 21 22struct tcb_queue { 23 tcb_t *head; 24 tcb_t *end; 25}; 26typedef struct tcb_queue tcb_queue_t; 27 28static inline unsigned int setMR(tcb_t *receiver, word_t *receiveIPCBuffer, 29 unsigned int offset, word_t reg) 30{ 31 if (offset >= n_msgRegisters) { 32 if (receiveIPCBuffer) { 33 receiveIPCBuffer[offset + 1] = reg; 34 return offset + 1; 35 } else { 36 return n_msgRegisters; 37 } 38 } else { 39 setRegister(receiver, msgRegisters[offset], reg); 40 return offset + 1; 41 } 42} 43 44void tcbSchedEnqueue(tcb_t *tcb); 45void tcbSchedAppend(tcb_t *tcb); 46void tcbSchedDequeue(tcb_t *tcb); 47 48#ifdef CONFIG_DEBUG_BUILD 49void tcbDebugAppend(tcb_t *tcb); 50void tcbDebugRemove(tcb_t *tcb); 51#endif 52#ifdef CONFIG_KERNEL_MCS 53void tcbReleaseRemove(tcb_t *tcb); 54void tcbReleaseEnqueue(tcb_t *tcb); 55tcb_t *tcbReleaseDequeue(void); 56#endif 57 58#ifdef ENABLE_SMP_SUPPORT 59void remoteQueueUpdate(tcb_t *tcb); 60void remoteTCBStall(tcb_t *tcb); 61 62#define SCHED_ENQUEUE(_t) do { \ 63 tcbSchedEnqueue(_t); \ 64 remoteQueueUpdate(_t); \ 65} while (0) 66 67#define SCHED_APPEND(_t) do { \ 68 tcbSchedAppend(_t); \ 69 remoteQueueUpdate(_t); \ 70} while (0) 71 72#else 73#define SCHED_ENQUEUE(_t) tcbSchedEnqueue(_t) 74#define SCHED_APPEND(_t) tcbSchedAppend(_t) 75#endif /* ENABLE_SMP_SUPPORT */ 76 77#define SCHED_ENQUEUE_CURRENT_TCB tcbSchedEnqueue(NODE_STATE(ksCurThread)) 78#define SCHED_APPEND_CURRENT_TCB tcbSchedAppend(NODE_STATE(ksCurThread)) 79 80#ifdef CONFIG_KERNEL_MCS 81/* Add TCB into the priority ordered endpoint queue */ 82static inline tcb_queue_t tcbEPAppend(tcb_t *tcb, tcb_queue_t queue) 83{ 84 /* start at the back of the queue as FIFO is the common case */ 85 tcb_t *before = queue.end; 86 tcb_t *after = NULL; 87 88 /* find a place to put the tcb */ 89 while (unlikely(before != NULL && tcb->tcbPriority > before->tcbPriority)) { 90 after = before; 91 before = after->tcbEPPrev; 92 } 93 94 if (unlikely(before == NULL)) { 95 /* insert at head */ 96 queue.head = tcb; 97 } else { 98 before->tcbEPNext = tcb; 99 } 100 101 if (likely(after == NULL)) { 102 /* insert at tail */ 103 queue.end = tcb; 104 } else { 105 after->tcbEPPrev = tcb; 106 } 107 108 tcb->tcbEPNext = after; 109 tcb->tcbEPPrev = before; 110 111 return queue; 112} 113 114tcb_queue_t tcbEPDequeue(tcb_t *tcb, tcb_queue_t queue); 115 116#else 117tcb_queue_t tcbEPAppend(tcb_t *tcb, tcb_queue_t queue); 118tcb_queue_t tcbEPDequeue(tcb_t *tcb, tcb_queue_t queue); 119 120void setupCallerCap(tcb_t *sender, tcb_t *receiver, bool_t canGrant); 121void deleteCallerCap(tcb_t *receiver); 122#endif 123 124word_t copyMRs(tcb_t *sender, word_t *sendBuf, tcb_t *receiver, 125 word_t *recvBuf, word_t n); 126exception_t decodeTCBInvocation(word_t invLabel, word_t length, cap_t cap, 127 cte_t *slot, extra_caps_t excaps, bool_t call, 128 word_t *buffer); 129exception_t decodeCopyRegisters(cap_t cap, word_t length, 130 extra_caps_t excaps, word_t *buffer); 131exception_t decodeReadRegisters(cap_t cap, word_t length, bool_t call, 132 word_t *buffer); 133exception_t decodeWriteRegisters(cap_t cap, word_t length, word_t *buffer); 134exception_t decodeTCBConfigure(cap_t cap, word_t length, 135 cte_t *slot, extra_caps_t rootCaps, word_t *buffer); 136exception_t decodeSetPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer); 137exception_t decodeSetMCPriority(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer); 138#ifdef CONFIG_KERNEL_MCS 139exception_t decodeSetSchedParams(cap_t cap, word_t length, cte_t *slot, extra_caps_t excaps, word_t *buffer); 140#else 141exception_t decodeSetSchedParams(cap_t cap, word_t length, extra_caps_t excaps, word_t *buffer); 142#endif 143exception_t decodeSetIPCBuffer(cap_t cap, word_t length, 144 cte_t *slot, extra_caps_t excaps, word_t *buffer); 145exception_t decodeSetSpace(cap_t cap, word_t length, 146 cte_t *slot, extra_caps_t excaps, word_t *buffer); 147exception_t decodeDomainInvocation(word_t invLabel, word_t length, 148 extra_caps_t excaps, word_t *buffer); 149exception_t decodeBindNotification(cap_t cap, extra_caps_t excaps); 150exception_t decodeUnbindNotification(cap_t cap); 151#ifdef CONFIG_KERNEL_MCS 152exception_t decodeSetTimeoutEndpoint(cap_t cap, cte_t *slot, extra_caps_t excaps); 153#endif 154 155 156#ifdef CONFIG_KERNEL_MCS 157enum thread_control_caps_flag { 158 thread_control_caps_update_ipc_buffer = 0x1, 159 thread_control_caps_update_space = 0x2, 160 thread_control_caps_update_fault = 0x4, 161 thread_control_caps_update_timeout = 0x8, 162}; 163 164enum thread_control_sched_flag { 165 thread_control_sched_update_priority = 0x1, 166 thread_control_sched_update_mcp = 0x2, 167 thread_control_sched_update_sc = 0x4, 168 thread_control_sched_update_fault = 0x8, 169}; 170#else 171enum thread_control_flag { 172 thread_control_update_priority = 0x1, 173 thread_control_update_ipc_buffer = 0x2, 174 thread_control_update_space = 0x4, 175 thread_control_update_mcp = 0x8, 176#ifdef CONFIG_KERNEL_MCS 177 thread_control_update_sc = 0x10, 178 thread_control_update_fault = 0x20, 179 thread_control_update_timeout = 0x40, 180#endif 181}; 182#endif 183 184typedef word_t thread_control_flag_t; 185 186exception_t invokeTCB_Suspend(tcb_t *thread); 187exception_t invokeTCB_Resume(tcb_t *thread); 188#ifdef CONFIG_KERNEL_MCS 189exception_t invokeTCB_ThreadControlCaps(tcb_t *target, cte_t *slot, 190 cap_t fh_newCap, cte_t *fh_srcSlot, 191 cap_t th_newCap, cte_t *th_srcSlot, 192 cap_t cRoot_newCap, cte_t *cRoot_srcSlot, 193 cap_t vRoot_newCap, cte_t *vRoot_srcSlot, 194 word_t bufferAddr, cap_t bufferCap, 195 cte_t *bufferSrcSlot, 196 thread_control_flag_t updateFlags); 197exception_t invokeTCB_ThreadControlSched(tcb_t *target, cte_t *slot, 198 cap_t fh_newCap, cte_t *fh_srcSlot, 199 prio_t mcp, prio_t priority, 200 sched_context_t *sc, 201 thread_control_flag_t updateFlags); 202#else 203exception_t invokeTCB_ThreadControl(tcb_t *target, cte_t *slot, cptr_t faultep, 204 prio_t mcp, prio_t priority, cap_t cRoot_newCap, 205 cte_t *cRoot_srcSlot, cap_t vRoot_newCap, 206 cte_t *vRoot_srcSlot, word_t bufferAddr, 207 cap_t bufferCap, cte_t *bufferSrcSlot, 208 thread_control_flag_t updateFlags); 209#endif 210exception_t invokeTCB_CopyRegisters(tcb_t *dest, tcb_t *src, 211 bool_t suspendSource, bool_t resumeTarget, 212 bool_t transferFrame, bool_t transferInteger, 213 word_t transferArch); 214exception_t invokeTCB_ReadRegisters(tcb_t *src, bool_t suspendSource, 215 word_t n, word_t arch, bool_t call); 216exception_t invokeTCB_WriteRegisters(tcb_t *dest, bool_t resumeTarget, 217 word_t n, word_t arch, word_t *buffer); 218exception_t invokeTCB_NotificationControl(tcb_t *tcb, notification_t *ntfnPtr); 219 220cptr_t PURE getExtraCPtr(word_t *bufferPtr, word_t i); 221void setExtraBadge(word_t *bufferPtr, word_t badge, word_t i); 222 223exception_t lookupExtraCaps(tcb_t *thread, word_t *bufferPtr, seL4_MessageInfo_t info); 224word_t setMRs_syscall_error(tcb_t *thread, word_t *receiveIPCBuffer); 225word_t CONST Arch_decodeTransfer(word_t flags); 226exception_t CONST Arch_performTransfer(word_t arch, tcb_t *tcb_src, 227 tcb_t *tcb_dest); 228 229#ifdef ENABLE_SMP_SUPPORT 230void Arch_migrateTCB(tcb_t *thread); 231#endif /* ENABLE_SMP_SUPPORT */ 232 233#ifdef CONFIG_DEBUG_BUILD 234void setThreadName(tcb_t *thread, const char *name); 235#endif /* CONFIG_DEBUG_BUILD */ 236 237