1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * Copyright (c) 2016-2017, Linaro Limited
5 * Copyright (c) 2020-2021, Arm Limited
6 */
7
8 #ifndef __KERNEL_THREAD_H
9 #define __KERNEL_THREAD_H
10
11 #ifndef __ASSEMBLER__
12 #include <types_ext.h>
13 #include <compiler.h>
14 #include <mm/pgt_cache.h>
15 #endif
16 #include <util.h>
17 #include <kernel/thread_arch.h>
18
19 #define THREAD_FLAGS_COPY_ARGS_ON_RETURN BIT(0)
20 #define THREAD_FLAGS_FOREIGN_INTR_ENABLE BIT(1)
21 #define THREAD_FLAGS_EXIT_ON_FOREIGN_INTR BIT(2)
22 #define THREAD_FLAGS_FFA_ONLY BIT(3)
23
24 #define THREAD_ID_0 0
25 #define THREAD_ID_INVALID -1
26
27 #define THREAD_RPC_MAX_NUM_PARAMS U(4)
28
29 #ifndef __ASSEMBLER__
30
31 struct thread_specific_data {
32 TAILQ_HEAD(, ts_session) sess_stack;
33 struct ts_ctx *ctx;
34 #ifdef CFG_CORE_FFA
35 uint32_t rpc_target_info;
36 #endif
37 uint32_t abort_type;
38 uint32_t abort_descr;
39 vaddr_t abort_va;
40 unsigned int abort_core;
41 struct thread_abort_regs abort_regs;
42 #ifdef CFG_CORE_DEBUG_CHECK_STACKS
43 bool stackcheck_recursion;
44 #endif
45 unsigned int syscall_recursion;
46 #ifdef CFG_FAULT_MITIGATION
47 struct ftmn_func_arg *ftmn_arg;
48 #endif
49 };
50
51 void thread_init_canaries(void);
52 void thread_init_primary(void);
53 void thread_init_per_cpu(void);
54
55 #if defined(CFG_WITH_STACK_CANARIES)
56 void thread_update_canaries(void);
57 #else
thread_update_canaries(void)58 static inline void thread_update_canaries(void) { }
59 #endif
60
61 struct thread_core_local *thread_get_core_local(void);
62
63 /*
64 * thread_init_threads() - Initialize threads
65 * @thread_count: Number of threads to configure
66 *
67 * Initializes thread contexts. Called in thread_init_boot_thread() if
68 * virtualization is disabled. Virtualization subsystem calls it for every
69 * new guest otherwise. @thread_count must be <= CFG_NUM_THREADS, and will
70 * initialize the number of threads to @thread_count if configured with
71 * CFG_DYN_CONFIG=y, else @thread_count must equal CFG_NUM_THREADS.
72 */
73 void thread_init_threads(size_t thread_count);
74
75 vaddr_t thread_get_abt_stack(void);
76
77 /*
78 * thread_init_thread_core_local() - Initialize thread_core_local
79 * @core_count: Number of cores in the system
80 *
81 * Called by the init CPU. Sets temporary stack mode for all CPUs
82 * (curr_thread = -1 and THREAD_CLF_TMP) and sets the temporary stack limit
83 * for the init CPU. @core_count must be <= CFG_TEE_CORE_NB_CORE, and will
84 * set the number of supported cores to @core_count if configured with
85 * CFG_DYN_CONFIG=y, else @core_count must equal CFG_TEE_CORE_NB_CORE.
86 */
87 void thread_init_thread_core_local(size_t core_count);
88
89 #if defined(CFG_CORE_PAUTH)
90 void thread_init_thread_pauth_keys(void);
91 void thread_init_core_local_pauth_keys(void);
92 #else
thread_init_thread_pauth_keys(void)93 static inline void thread_init_thread_pauth_keys(void) { }
thread_init_core_local_pauth_keys(void)94 static inline void thread_init_core_local_pauth_keys(void) { }
95 #endif
96
97 /*
98 * Initializes a thread to be used during boot
99 */
100 void thread_init_boot_thread(void);
101
102 /*
103 * Clears the current thread id
104 * Only supposed to be used during initialization.
105 */
106 void thread_clr_boot_thread(void);
107
108 /*
109 * Returns current thread id.
110 */
111 short int thread_get_id(void);
112
113 /*
114 * Returns current thread id, return -1 on failure.
115 */
116 short int thread_get_id_may_fail(void);
117
118 /* Returns Thread Specific Data (TSD) pointer. */
119 struct thread_specific_data *thread_get_tsd(void);
120
121 /*
122 * Sets foreign interrupts status for current thread, must only be called
123 * from an active thread context.
124 *
125 * enable == true -> enable foreign interrupts
126 * enable == false -> disable foreign interrupts
127 */
128 void thread_set_foreign_intr(bool enable);
129
130 /*
131 * Restores the foreign interrupts status (in CPSR) for current thread, must
132 * only be called from an active thread context.
133 */
134 void thread_restore_foreign_intr(void);
135
136 /*
137 * thread_get_exceptions() - return current exception mask
138 */
139 uint32_t thread_get_exceptions(void);
140
141 /*
142 * thread_set_exceptions() - set exception mask
143 * @exceptions: exception mask to set
144 *
145 * Any previous exception mask is replaced by this exception mask, that is,
146 * old bits are cleared and replaced by these.
147 */
148 void thread_set_exceptions(uint32_t exceptions);
149
150 /*
151 * thread_mask_exceptions() - Masks (disables) specified asynchronous exceptions
152 * @exceptions exceptions to mask
153 * @returns old exception state
154 */
155 uint32_t thread_mask_exceptions(uint32_t exceptions);
156
157 /*
158 * thread_unmask_exceptions() - Unmasks asynchronous exceptions
159 * @state Old asynchronous exception state to restore (returned by
160 * thread_mask_exceptions())
161 */
162 void thread_unmask_exceptions(uint32_t state);
163
164
thread_foreign_intr_disabled(void)165 static inline bool __nostackcheck thread_foreign_intr_disabled(void)
166 {
167 return !!(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
168 }
169
170 /*
171 * thread_enter_user_mode() - Enters user mode
172 * @a0: Passed in r/x0 for user_func
173 * @a1: Passed in r/x1 for user_func
174 * @a2: Passed in r/x2 for user_func
175 * @a3: Passed in r/x3 for user_func
176 * @user_sp: Assigned sp value in user mode
177 * @user_func: Function to execute in user mode
178 * @is_32bit: True if TA should execute in Aarch32, false if Aarch64
179 * @exit_status0: Pointer to opaque exit staus 0
180 * @exit_status1: Pointer to opaque exit staus 1
181 *
182 * This functions enters user mode with the argument described above,
183 * @exit_status0 and @exit_status1 are filled in by thread_unwind_user_mode()
184 * when returning back to the caller of this function through an exception
185 * handler.
186 *
187 * @Returns what's passed in "ret" to thread_unwind_user_mode()
188 */
189 uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1,
190 unsigned long a2, unsigned long a3, unsigned long user_sp,
191 unsigned long entry_func, bool is_32bit,
192 uint32_t *exit_status0, uint32_t *exit_status1);
193
194 /*
195 * thread_unwind_user_mode() - Unwinds kernel stack from user entry
196 * @ret: Value to return from thread_enter_user_mode()
197 * @exit_status0: Exit status 0
198 * @exit_status1: Exit status 1
199 *
200 * This is the function that exception handlers can return into
201 * to resume execution in kernel mode instead of user mode.
202 *
203 * This function is closely coupled with thread_enter_user_mode() since it
204 * need to restore registers saved by thread_enter_user_mode() and when it
205 * returns make it look like thread_enter_user_mode() just returned. It is
206 * expected that the stack pointer is where thread_enter_user_mode() left
207 * it. The stack will be unwound and the function will return to where
208 * thread_enter_user_mode() was called from. Exit_status0 and exit_status1
209 * are filled in the corresponding pointers supplied to
210 * thread_enter_user_mode().
211 */
212 void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0,
213 uint32_t exit_status1);
214
215 /*
216 * Returns the start address (bottom) of the stack for the current thread,
217 * zero if there is no current thread.
218 */
219 vaddr_t thread_stack_start(void);
220
221
222 /* Returns the stack size for the current thread */
223 size_t thread_stack_size(void);
224
225 /*
226 * Returns the start (top, lowest address) and end (bottom, highest address) of
227 * the current stack (thread, temporary or abort stack).
228 * When CFG_CORE_DEBUG_CHECK_STACKS=y, the @hard parameter tells if the hard or
229 * soft limits are queried. The difference between soft and hard is that for the
230 * latter, the stack start includes some additional space to let any function
231 * overflow the soft limit and still be able to print a stack dump in this case.
232 */
233 bool get_stack_limits(vaddr_t *start, vaddr_t *end, bool hard);
234
get_stack_soft_limits(vaddr_t * start,vaddr_t * end)235 static inline bool __nostackcheck get_stack_soft_limits(vaddr_t *start,
236 vaddr_t *end)
237 {
238 return get_stack_limits(start, end, false);
239 }
240
get_stack_hard_limits(vaddr_t * start,vaddr_t * end)241 static inline bool __nostackcheck get_stack_hard_limits(vaddr_t *start,
242 vaddr_t *end)
243 {
244 return get_stack_limits(start, end, true);
245 }
246
247 bool thread_is_in_normal_mode(void);
248
249 /*
250 * Returns true if previous exeception also was in abort mode.
251 *
252 * Note: it's only valid to call this function from an abort exception
253 * handler before interrupts has been re-enabled.
254 */
255 bool thread_is_from_abort_mode(void);
256
257 /**
258 * Allocates data for payload buffers shared with a non-secure user space
259 * application. Ensure consistency with the enumeration
260 * THREAD_SHM_TYPE_APPLICATION.
261 *
262 * @size: size in bytes of payload buffer
263 *
264 * @returns mobj that describes allocated buffer or NULL on error
265 */
266 struct mobj *thread_rpc_alloc_payload(size_t size);
267
268 /**
269 * Free physical memory previously allocated with thread_rpc_alloc_payload()
270 *
271 * @mobj: mobj that describes the buffer
272 */
273 void thread_rpc_free_payload(struct mobj *mobj);
274
275 /**
276 * Allocate data for payload buffers shared with the non-secure kernel.
277 * Ensure consistency with the enumeration THREAD_SHM_TYPE_KERNEL_PRIVATE.
278 *
279 * @size: size in bytes of payload buffer
280 *
281 * @returns mobj that describes allocated buffer or NULL on error
282 */
283 struct mobj *thread_rpc_alloc_kernel_payload(size_t size);
284
285 /**
286 * Free physical memory previously allocated with
287 * thread_rpc_alloc_kernel_payload()
288 *
289 * @mobj: mobj that describes the buffer
290 */
291 void thread_rpc_free_kernel_payload(struct mobj *mobj);
292
293 struct thread_param_memref {
294 size_t offs;
295 size_t size;
296 struct mobj *mobj;
297 };
298
299 struct thread_param_value {
300 uint64_t a;
301 uint64_t b;
302 uint64_t c;
303 };
304
305 /*
306 * Note that there's some arithmetics done on the value so it's important
307 * to keep in IN, OUT, INOUT order.
308 */
309 enum thread_param_attr {
310 THREAD_PARAM_ATTR_NONE = 0,
311 THREAD_PARAM_ATTR_VALUE_IN,
312 THREAD_PARAM_ATTR_VALUE_OUT,
313 THREAD_PARAM_ATTR_VALUE_INOUT,
314 THREAD_PARAM_ATTR_MEMREF_IN,
315 THREAD_PARAM_ATTR_MEMREF_OUT,
316 THREAD_PARAM_ATTR_MEMREF_INOUT,
317 };
318
319 struct thread_param {
320 enum thread_param_attr attr;
321 union {
322 struct thread_param_memref memref;
323 struct thread_param_value value;
324 } u;
325 };
326
327 #define THREAD_PARAM_MEMREF(_direction, _mobj, _offs, _size) \
328 (struct thread_param){ \
329 .attr = THREAD_PARAM_ATTR_MEMREF_ ## _direction, .u.memref = { \
330 .mobj = (_mobj), .offs = (_offs), .size = (_size) } \
331 }
332
333 #define THREAD_PARAM_VALUE(_direction, _a, _b, _c) \
334 (struct thread_param){ \
335 .attr = THREAD_PARAM_ATTR_VALUE_ ## _direction, .u.value = { \
336 .a = (_a), .b = (_b), .c = (_c) } \
337 }
338
339 /**
340 * Does an RPC using a preallocated argument buffer
341 * @cmd: RPC cmd
342 * @num_params: number of parameters
343 * @params: RPC parameters
344 * @returns RPC return value
345 */
346 uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params,
347 struct thread_param *params);
348
349 /**
350 * Allocate data for payload buffers shared with both user space applications
351 * and the non-secure kernel. Ensure consistency with the enumeration
352 * THREAD_SHM_TYPE_GLOBAL.
353 *
354 * @size: size in bytes of payload buffer
355 *
356 * @returns mobj that describes allocated buffer or NULL on error
357 */
358 struct mobj *thread_rpc_alloc_global_payload(size_t size);
359
360 /**
361 * Free physical memory previously allocated with
362 * thread_rpc_alloc_global_payload()
363 *
364 * @mobj: mobj that describes the buffer
365 */
366 void thread_rpc_free_global_payload(struct mobj *mobj);
367
368 /*
369 * enum thread_shm_type - type of non-secure shared memory
370 * @THREAD_SHM_TYPE_APPLICATION - user space application shared memory
371 * @THREAD_SHM_TYPE_KERNEL_PRIVATE - kernel private shared memory
372 * @THREAD_SHM_TYPE_GLOBAL - user space and kernel shared memory
373 */
374 enum thread_shm_type {
375 THREAD_SHM_TYPE_APPLICATION,
376 THREAD_SHM_TYPE_KERNEL_PRIVATE,
377 THREAD_SHM_TYPE_GLOBAL,
378 };
379
380 /*
381 * enum thread_shm_cache_user - user of a cache allocation
382 * @THREAD_SHM_CACHE_USER_SOCKET - socket communication
383 * @THREAD_SHM_CACHE_USER_FS - filesystem access
384 * @THREAD_SHM_CACHE_USER_I2C - I2C communication
385 * @THREAD_SHM_CACHE_USER_RPMB - RPMB communication
386 *
387 * To ensure that each user of the shared memory cache doesn't interfere
388 * with each other a unique ID per user is used.
389 */
390 enum thread_shm_cache_user {
391 THREAD_SHM_CACHE_USER_SOCKET,
392 THREAD_SHM_CACHE_USER_FS,
393 THREAD_SHM_CACHE_USER_I2C,
394 THREAD_SHM_CACHE_USER_RPMB,
395 };
396
397 /*
398 * Returns a pointer to the cached RPC memory. Each thread and @user tuple
399 * has a unique cache. The pointer is guaranteed to point to a large enough
400 * area or to be NULL.
401 */
402 void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user,
403 enum thread_shm_type shm_type,
404 size_t size, struct mobj **mobj);
405
406 #endif /*__ASSEMBLER__*/
407
408 #endif /*__KERNEL_THREAD_H*/
409