1/* SPDX-License-Identifier: BSD-2-Clause */ 2/* 3 * Copyright 2023 NXP 4 * Copyright (c) 2023 Andes Technology Corporation 5 */ 6 7#include <asm.S> 8#include <generated/asm-defines.h> 9#include <keep.h> 10#include <kernel/thread.h> 11#include <kernel/thread_private.h> 12#include <riscv.h> 13#include <riscv_macros.S> 14#include <sbi.h> 15#include <tee/optee_abi.h> 16#include <tee/teeabi_opteed.h> 17#include <tee/teeabi_opteed_macros.h> 18 19/* 20 * Implement based on the transport method used to communicate between 21 * untrusted domain and trusted domain. It could be an SBI/ECALL-based to 22 * a security monitor running in M-Mode and panic or messaging-based across 23 * domains where we return to a messaging callback which parses and handles 24 * messages. 25 * 26 * void thread_return_to_udomain(unsigned long arg0, unsigned long arg1, 27 * unsigned long arg2, unsigned long arg3, 28 * unsigned long arg4, unsigned long arg5); 29 */ 30FUNC thread_return_to_udomain , : 31 /* Caller should provide arguments in a0~a5 */ 32#if defined(CFG_RISCV_WITH_M_MODE_SM) 33 li a7, SBI_EXT_TEE /* extension ID */ 34 li a6, 0 /* function ID (unused) */ 35 ecall 36#else 37 /* Other protocol */ 38#endif 39 /* ABI to REE should not return */ 40 panic_at_abi_return 41END_FUNC thread_return_to_udomain 42 43FUNC thread_std_abi_entry , : 44 jal __thread_std_abi_entry 45 46 /* Save return value */ 47 mv s0, a0 48 49 /* Mask all maskable exceptions before switching to temporary stack */ 50 csrw CSR_XIE, x0 51 52 /* Switch to temporary stack */ 53 jal thread_get_tmp_sp 54 mv sp, a0 55 56 /* 57 * We are returning from thread_alloc_and_run() 58 * set thread state as free 59 */ 60 jal thread_state_free 61 62 /* Restore __thread_std_abi_entry() return value */ 63 mv a1, s0 64 li a2, 0 65 li a3, 0 66 li a4, 0 67 li a5, 0 68 li a0, TEEABI_OPTEED_RETURN_CALL_DONE 69 70 /* Return to untrusted domain */ 71 jal thread_return_to_udomain 72END_FUNC thread_std_abi_entry 73 74/* 75 * void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], 76 * unsigned long status); 77 */ 78FUNC thread_rpc_xstatus , : 79 /* Use stack for temporary storage */ 80 addi sp, sp, -REGOFF(8) 81 82 /* Read xSTATUS */ 83 csrr a2, CSR_XSTATUS 84 85 /* Mask all maskable exceptions before switching to temporary stack */ 86 csrw CSR_XIE, x0 87 88 /* Save return address xSTATUS and pointer to rv */ 89 STR a0, REGOFF(0)(sp) 90 STR a1, REGOFF(1)(sp) 91 STR s0, REGOFF(2)(sp) 92 STR ra, REGOFF(3)(sp) 93 STR a2, REGOFF(4)(sp) 94#ifdef CFG_UNWIND 95 addi s0, sp, REGOFF(8) 96#endif 97 98 /* Save thread state */ 99 jal thread_get_ctx_regs 100 LDR ra, REGOFF(3)(sp) 101 /* Save ra, sp, gp, tp, and s0~s11 */ 102 store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP 103 store_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 104 store_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 105 106 /* Get to tmp stack */ 107 jal thread_get_tmp_sp 108 109 /* Get pointer to rv */ 110 LDR s1, REGOFF(0)(sp) 111 112 /* xSTATUS to restore */ 113 LDR a1, REGOFF(1)(sp) 114 /* Switch to tmp stack */ 115 mv sp, a0 116 117 /* Early load rv[] into s2-s4 */ 118 lw s2, 0(s1) 119 lw s3, 4(s1) 120 lw s4, 8(s1) 121 122 li a0, THREAD_FLAGS_COPY_ARGS_ON_RETURN 123 la a2, .thread_rpc_return 124 jal thread_state_suspend 125 126 mv a4, a0 /* thread index */ 127 mv a1, s2 /* rv[0] */ 128 mv a2, s3 /* rv[1] */ 129 mv a3, s4 /* rv[2] */ 130 li a5, 0 131 li a0, TEEABI_OPTEED_RETURN_CALL_DONE 132 133 /* Return to untrusted domain */ 134 jal thread_return_to_udomain 135.thread_rpc_return: 136 /* 137 * Jumps here from thread_resume() above when RPC has returned. 138 * At this point has the stack pointer been restored to the value 139 * stored in THREAD_CTX above. 140 */ 141 142 /* Get pointer to rv[] */ 143 LDR a4, REGOFF(0)(sp) 144 145 /* Store a0-a3 into rv[] */ 146 sw a0, 0(a4) 147 sw a1, 4(a4) 148 sw a2, 8(a4) 149 sw a3, 12(a4) 150 151 /* Pop saved XSTATUS from stack */ 152 LDR s0, REGOFF(4)(sp) 153 csrw CSR_XSTATUS, s0 154 155 /* Pop s0 from stack */ 156 LDR s0, REGOFF(2)(sp) 157 158 addi sp, sp, REGOFF(8) 159 ret 160END_FUNC thread_rpc_xstatus 161DECLARE_KEEP_PAGER thread_rpc_xstatus 162 163LOCAL_FUNC vector_std_abi_entry, : , .identity_map 164 jal thread_handle_std_abi 165 /* 166 * Normally thread_handle_std_abi() should return via 167 * thread_exit(), thread_rpc(), but if thread_handle_std_abi() 168 * hasn't switched stack (error detected) it will do a normal "C" 169 * return. 170 */ 171 /* Restore thread_handle_std_abi() return value */ 172 mv a1, a0 173 li a2, 0 174 li a3, 0 175 li a4, 0 176 li a5, 0 177 li a0, TEEABI_OPTEED_RETURN_CALL_DONE 178 179 /* Return to untrusted domain */ 180 j thread_return_to_udomain 181END_FUNC vector_std_abi_entry 182 183LOCAL_FUNC vector_fast_abi_entry , : , .identity_map 184 addi sp, sp, -THREAD_ABI_ARGS_SIZE 185 store_xregs sp, THREAD_ABI_ARGS_A0, REG_A0, REG_A7 186 mv a0, sp 187 jal thread_handle_fast_abi 188 load_xregs sp, THREAD_ABI_ARGS_A0, REG_A1, REG_A7 189 addi sp, sp, THREAD_ABI_ARGS_SIZE 190 191 li a0, TEEABI_OPTEED_RETURN_CALL_DONE 192 /* Return to untrusted domain */ 193 j thread_return_to_udomain 194END_FUNC vector_fast_abi_entry 195 196LOCAL_FUNC vector_fiq_entry , : , .identity_map 197 /* Secure Monitor received a FIQ and passed control to us. */ 198 jal interrupt_main_handler 199 200 li a0, TEEABI_OPTEED_RETURN_FIQ_DONE 201 li a1, 0 202 li a2, 0 203 li a3, 0 204 li a4, 0 205 li a5, 0 206 207 /* Return to untrusted domain */ 208 j thread_return_to_udomain 209END_FUNC vector_fiq_entry 210 211/* 212 * Vector table supplied to M-mode secure monitor (e.g., openSBI) at 213 * initialization. 214 * 215 * Note that M-mode secure monitor depends on the layout of this vector table, 216 * any change in layout has to be synced with M-mode secure monitor. 217 */ 218FUNC thread_vector_table , : , .identity_map, , nobti 219 .option push 220 .option norvc 221 j vector_std_abi_entry 222 j vector_fast_abi_entry 223 j . 224 j . 225 j . 226 j . 227 j vector_fiq_entry 228 j . 229 j . 230 .option pop 231END_FUNC thread_vector_table 232DECLARE_KEEP_PAGER thread_vector_table 233