1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014-2022, Linaro Limited 4 * Copyright (c) 2020, Arm Limited 5 */ 6 7 #include <kernel/abort.h> 8 #include <kernel/scall.h> 9 #include <kernel/thread.h> 10 #include <kernel/trace_ta.h> 11 #include <kernel/user_ta.h> 12 #include <mm/vm.h> 13 #include <types_ext.h> 14 15 #define TA32_CONTEXT_MAX_SIZE (14 * sizeof(uint32_t)) 16 #define TA64_CONTEXT_MAX_SIZE (2 * sizeof(uint64_t)) 17 18 #ifdef CFG_UNWIND 19 #ifdef ARM32 20 /* Get register values pushed onto the stack by _utee_panic() */ 21 static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, 22 uint32_t *pushed) 23 { 24 tsd->abort_regs = (struct thread_abort_regs){ 25 .elr = pushed[0], 26 .r0 = pushed[1], 27 .r1 = pushed[2], 28 .r2 = pushed[3], 29 .r3 = pushed[4], 30 .r4 = pushed[5], 31 .r5 = pushed[6], 32 .r6 = pushed[7], 33 .r7 = pushed[8], 34 .r8 = pushed[9], 35 .r9 = pushed[10], 36 .r10 = pushed[11], 37 .r11 = pushed[12], 38 .usr_sp = (uint32_t)pushed, 39 .usr_lr = pushed[13], 40 .spsr = read_spsr(), 41 }; 42 } 43 44 void scall_save_panic_stack(struct thread_scall_regs *regs) 45 { 46 struct thread_specific_data *tsd = thread_get_tsd(); 47 struct ts_session *s = ts_get_current_session(); 48 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 49 50 tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; 51 tsd->abort_descr = 0; 52 tsd->abort_va = 0; 53 54 if (vm_check_access_rights(&utc->uctx, 55 TEE_MEMORY_ACCESS_READ | 56 TEE_MEMORY_ACCESS_WRITE, 57 (uaddr_t)regs->r1, TA32_CONTEXT_MAX_SIZE)) { 58 TAMSG_RAW(""); 59 TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, 60 (uaddr_t)regs->r1); 61 return; 62 } 63 64 save_panic_regs_a32_ta(tsd, (uint32_t *)regs->r1); 65 } 66 #endif /*ARM32*/ 67 68 #ifdef ARM64 69 /* Get register values pushed onto the stack by _utee_panic() (32-bit TA) */ 70 static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, 71 uint32_t *pushed) 72 { 73 tsd->abort_regs = (struct thread_abort_regs){ 74 .elr = pushed[0], 75 .x0 = pushed[1], 76 .x1 = pushed[2], 77 .x2 = pushed[3], 78 .x3 = pushed[4], 79 .x4 = pushed[5], 80 .x5 = pushed[6], 81 .x6 = pushed[7], 82 .x7 = pushed[8], 83 .x8 = pushed[9], 84 .x9 = pushed[10], 85 .x10 = pushed[11], 86 .x11 = pushed[12], 87 .x13 = (uint64_t)pushed, 88 .x14 = pushed[13], 89 .spsr = (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), 90 }; 91 } 92 93 /* Get register values pushed onto the stack by _utee_panic() (64-bit TA) */ 94 static void save_panic_regs_a64_ta(struct thread_specific_data *tsd, 95 uint64_t *pushed) 96 { 97 tsd->abort_regs = (struct thread_abort_regs){ 98 .x29 = pushed[0], 99 .elr = pushed[1], 100 .spsr = (SPSR_64_MODE_EL0 << SPSR_64_MODE_EL_SHIFT), 101 }; 102 } 103 104 void scall_save_panic_stack(struct thread_scall_regs *regs) 105 { 106 struct thread_specific_data *tsd = thread_get_tsd(); 107 struct ts_session *s = ts_get_current_session(); 108 struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); 109 110 if (vm_check_access_rights(&utc->uctx, 111 TEE_MEMORY_ACCESS_READ | 112 TEE_MEMORY_ACCESS_WRITE, 113 (uaddr_t)regs->x1, 114 utc->uctx.is_32bit ? 115 TA32_CONTEXT_MAX_SIZE : 116 TA64_CONTEXT_MAX_SIZE)) { 117 TAMSG_RAW(""); 118 TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, 119 (uaddr_t)regs->x1); 120 return; 121 } 122 123 tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; 124 tsd->abort_descr = 0; 125 tsd->abort_va = 0; 126 127 if (utc->uctx.is_32bit) 128 save_panic_regs_a32_ta(tsd, (uint32_t *)regs->x1); 129 else 130 save_panic_regs_a64_ta(tsd, (uint64_t *)regs->x1); 131 } 132 #endif /*ARM64*/ 133 134 #else /* CFG_UNWIND */ 135 void scall_save_panic_stack(struct thread_scall_regs *regs __unused) 136 { 137 struct thread_specific_data *tsd = thread_get_tsd(); 138 139 tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; 140 } 141 #endif /* CFG_UNWIND */ 142