1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * Copyright (c) 2020, Linaro Limited 5 */ 6 7 #include <kernel/panic.h> 8 #include <kernel/pseudo_ta.h> 9 #include <kernel/tee_ta_manager.h> 10 #include <kernel/thread.h> 11 #include <kernel/ts_manager.h> 12 #include <kernel/user_mode_ctx.h> 13 #include <mm/core_mmu.h> 14 #include <mm/vm.h> 15 16 static void update_current_ctx(struct thread_specific_data *tsd) 17 { 18 struct ts_ctx *ctx = NULL; 19 struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); 20 21 if (s) { 22 if (is_pseudo_ta_ctx(s->ctx)) 23 s = TAILQ_NEXT(s, link_tsd); 24 25 if (s) 26 ctx = s->ctx; 27 } 28 29 if (tsd->ctx != ctx) 30 vm_set_ctx(ctx); 31 /* 32 * If current context is of user mode, then it has to be active too. 33 */ 34 if (is_user_mode_ctx(ctx) != core_mmu_user_mapping_is_active()) 35 panic("unexpected active mapping"); 36 } 37 38 static void *swap_fbuf(struct ts_session *s __maybe_unused, 39 void *fbuf __maybe_unused) 40 { 41 void *ret = NULL; 42 43 #if defined(CFG_FTRACE_SUPPORT) 44 ret = s->fbuf; 45 s->fbuf = fbuf; 46 #endif 47 48 return ret; 49 } 50 51 void ts_push_current_session(struct ts_session *s) 52 { 53 struct thread_specific_data *tsd = thread_get_tsd(); 54 uint32_t state = 0; 55 void *fbuf = NULL; 56 57 /* 58 * If ftrace is enabled we may access the session list and the fbuf 59 * field in the current (first) session when processing a foreign 60 * interrupt when saving the state of the thread. Mask foreign 61 * interrupts temporarily to make sure that we present a consistent 62 * state. 63 * 64 * We disable the fbuf temporarily while switching mapped TS to 65 * since this isn't an atomic operation, that is, the mappings are 66 * replaced entry by entry so it's not clear what is mapped during 67 * the call to update_current_ctx(). 68 */ 69 70 if (IS_ENABLED(CFG_FTRACE_SUPPORT)) { 71 state = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 72 fbuf = swap_fbuf(s, NULL); 73 } 74 75 TAILQ_INSERT_HEAD(&tsd->sess_stack, s, link_tsd); 76 77 if (IS_ENABLED(CFG_FTRACE_SUPPORT)) 78 thread_unmask_exceptions(state); 79 80 update_current_ctx(tsd); 81 82 if (IS_ENABLED(CFG_FTRACE_SUPPORT) && fbuf) { 83 state = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 84 swap_fbuf(s, fbuf); 85 thread_unmask_exceptions(state); 86 } 87 } 88 89 struct ts_session *ts_pop_current_session(void) 90 { 91 struct thread_specific_data *tsd = thread_get_tsd(); 92 struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); 93 struct ts_session *s2 = NULL; 94 uint32_t state = 0; 95 void *fbuf = NULL; 96 97 if (!s) 98 return NULL; 99 100 /* See comment in ts_push_current_session() above for ftrace support */ 101 102 if (IS_ENABLED(CFG_FTRACE_SUPPORT)) { 103 s2 = TAILQ_NEXT(s, link_tsd); 104 if (s2) 105 fbuf = swap_fbuf(s2, NULL); 106 state = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 107 } 108 109 TAILQ_REMOVE(&tsd->sess_stack, s, link_tsd); 110 111 if (IS_ENABLED(CFG_FTRACE_SUPPORT)) 112 thread_unmask_exceptions(state); 113 114 update_current_ctx(tsd); 115 116 if (IS_ENABLED(CFG_FTRACE_SUPPORT) && fbuf) { 117 state = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); 118 swap_fbuf(s2, fbuf); 119 thread_unmask_exceptions(state); 120 } 121 122 return s; 123 } 124 125 struct ts_session *ts_get_calling_session(void) 126 { 127 return TAILQ_NEXT(ts_get_current_session(), link_tsd); 128 } 129 130 struct ts_session *ts_get_current_session_may_fail(void) 131 { 132 return TAILQ_FIRST(&thread_get_tsd()->sess_stack); 133 } 134 135 struct ts_session *ts_get_current_session(void) 136 { 137 struct ts_session *s = ts_get_current_session_may_fail(); 138 139 if (!s) 140 panic(); 141 return s; 142 } 143