1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2023 Andes Technology Corporation 4 * Copyright 2022-2023 NXP 5 * Copyright (c) 2014-2022, Linaro Limited 6 * Copyright (c) 2020, Arm Limited 7 */ 8 9 #include <kernel/abort.h> 10 #include <kernel/scall.h> 11 #include <kernel/thread.h> 12 #include <kernel/trace_ta.h> 13 #include <kernel/user_access.h> 14 #include <kernel/user_ta.h> 15 #include <mm/vm.h> 16 #include <riscv.h> 17 #include <types_ext.h> 18 19 #define TA_CONTEXT_MAX_SIZE (RISCV_XLEN_BYTES * 32) 20 21 #ifdef CFG_UNWIND 22 23 /* Get register values pushed onto the stack by _utee_panic() */ 24 static void save_panic_regs_rv_ta(struct thread_specific_data *tsd, 25 unsigned long *pushed) 26 { 27 TEE_Result res = TEE_SUCCESS; 28 unsigned long s0 = 0; 29 unsigned long epc = 0; 30 #if defined(RV32) 31 unsigned long *stack_s0 = &pushed[2]; 32 unsigned long *stack_epc = &pushed[3]; 33 #elif defined(RV64) 34 unsigned long *stack_s0 = &pushed[0]; 35 unsigned long *stack_epc = &pushed[1]; 36 #endif 37 38 res = GET_USER_SCALAR(s0, stack_s0); 39 if (res) 40 s0 = 0; 41 42 res = GET_USER_SCALAR(epc, stack_epc); 43 if (res) 44 epc = 0; 45 46 tsd->abort_regs = (struct thread_abort_regs){ 47 .sp = (unsigned long)pushed, 48 .s0 = s0, 49 .epc = epc, 50 }; 51 } 52 53 void scall_save_panic_stack(struct thread_scall_regs *regs) 54 { 55 struct thread_specific_data *tsd = thread_get_tsd(); 56 struct ts_session *s = ts_get_current_session(); 57 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 58 59 if (vm_check_access_rights(&utc->uctx, 60 TEE_MEMORY_ACCESS_READ | 61 TEE_MEMORY_ACCESS_WRITE, 62 (uaddr_t)regs->a1, 63 TA_CONTEXT_MAX_SIZE)) { 64 TAMSG_RAW(""); 65 TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, 66 (uaddr_t)regs->a1); 67 return; 68 } 69 70 tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; 71 tsd->abort_descr = 0; 72 tsd->abort_va = 0; 73 74 save_panic_regs_rv_ta(tsd, (unsigned long *)regs->a1); 75 } 76 77 #else /* CFG_UNWIND */ 78 void scall_save_panic_stack(struct thread_scall_regs *regs __unused) 79 { 80 struct thread_specific_data *tsd = thread_get_tsd(); 81 82 tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; 83 } 84 #endif /* CFG_UNWIND */ 85