1 /* 2 * Copyright (c) 2015, Linaro Limited 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <kernel/abort.h> 29 #include <kernel/misc.h> 30 #include <kernel/tee_ta_manager.h> 31 #include <kernel/panic.h> 32 #include <mm/core_mmu.h> 33 #include <mm/tee_pager.h> 34 #include <trace.h> 35 #include <arm.h> 36 37 enum tee_pager_fault_type { 38 TEE_PAGER_FAULT_TYPE_USER_TA_PANIC, 39 TEE_PAGER_FAULT_TYPE_PAGEABLE, 40 TEE_PAGER_FAULT_TYPE_IGNORE, 41 }; 42 43 static __unused const char *abort_type_to_str(uint32_t abort_type) 44 { 45 if (abort_type == THREAD_ABORT_DATA) 46 return "data"; 47 if (abort_type == THREAD_ABORT_PREFETCH) 48 return "prefetch"; 49 return "undef"; 50 } 51 52 static __unused void tee_pager_print_detailed_abort( 53 struct tee_pager_abort_info *ai __unused, 54 const char *ctx __unused) 55 { 56 EMSG_RAW("\n"); 57 EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "\n", 58 ctx, abort_type_to_str(ai->abort_type), ai->va); 59 #ifdef ARM32 60 EMSG_RAW(" fsr 0x%08x ttbr0 0x%08x ttbr1 0x%08x cidr 0x%X\n", 61 ai->fault_descr, read_ttbr0(), read_ttbr1(), 62 read_contextidr()); 63 EMSG_RAW(" cpu #%zu cpsr 0x%08x\n", 64 get_core_pos(), ai->regs->spsr); 65 EMSG_RAW(" r0 0x%08x r4 0x%08x r8 0x%08x r12 0x%08x\n", 66 ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip); 67 EMSG_RAW(" r1 0x%08x r5 0x%08x r9 0x%08x sp 0x%08x\n", 68 ai->regs->r1, ai->regs->r5, ai->regs->r9, 69 read_mode_sp(ai->regs->spsr & CPSR_MODE_MASK)); 70 EMSG_RAW(" r2 0x%08x r6 0x%08x r10 0x%08x lr 0x%08x\n", 71 ai->regs->r2, ai->regs->r6, ai->regs->r10, 72 read_mode_lr(ai->regs->spsr & CPSR_MODE_MASK)); 73 EMSG_RAW(" r3 0x%08x r7 0x%08x r11 0x%08x pc 0x%08x\n", 74 ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc); 75 #endif /*ARM32*/ 76 #ifdef ARM64 77 EMSG_RAW(" esr 0x%08x ttbr0 0x%08" PRIx64 " ttbr1 0x%08" PRIx64 " cidr 0x%X\n", 78 ai->fault_descr, read_ttbr0_el1(), read_ttbr1_el1(), 79 read_contextidr_el1()); 80 EMSG_RAW(" cpu #%zu cpsr 0x%08x\n", 81 get_core_pos(), (uint32_t)ai->regs->spsr); 82 EMSG_RAW("x0 %016" PRIx64 " x1 %016" PRIx64, 83 ai->regs->x0, ai->regs->x1); 84 EMSG_RAW("x2 %016" PRIx64 " x3 %016" PRIx64, 85 ai->regs->x2, ai->regs->x3); 86 EMSG_RAW("x4 %016" PRIx64 " x5 %016" PRIx64, 87 ai->regs->x4, ai->regs->x5); 88 EMSG_RAW("x6 %016" PRIx64 " x7 %016" PRIx64, 89 ai->regs->x6, ai->regs->x7); 90 EMSG_RAW("x8 %016" PRIx64 " x9 %016" PRIx64, 91 ai->regs->x8, ai->regs->x9); 92 EMSG_RAW("x10 %016" PRIx64 " x11 %016" PRIx64, 93 ai->regs->x10, ai->regs->x11); 94 EMSG_RAW("x12 %016" PRIx64 " x13 %016" PRIx64, 95 ai->regs->x12, ai->regs->x13); 96 EMSG_RAW("x14 %016" PRIx64 " x15 %016" PRIx64, 97 ai->regs->x14, ai->regs->x15); 98 EMSG_RAW("x16 %016" PRIx64 " x17 %016" PRIx64, 99 ai->regs->x16, ai->regs->x17); 100 EMSG_RAW("x18 %016" PRIx64 " x19 %016" PRIx64, 101 ai->regs->x18, ai->regs->x19); 102 EMSG_RAW("x20 %016" PRIx64 " x21 %016" PRIx64, 103 ai->regs->x20, ai->regs->x21); 104 EMSG_RAW("x22 %016" PRIx64 " x23 %016" PRIx64, 105 ai->regs->x22, ai->regs->x23); 106 EMSG_RAW("x24 %016" PRIx64 " x25 %016" PRIx64, 107 ai->regs->x24, ai->regs->x25); 108 EMSG_RAW("x26 %016" PRIx64 " x27 %016" PRIx64, 109 ai->regs->x26, ai->regs->x27); 110 EMSG_RAW("x28 %016" PRIx64 " x29 %016" PRIx64, 111 ai->regs->x28, ai->regs->x29); 112 EMSG_RAW("x30 %016" PRIx64 " elr %016" PRIx64, 113 ai->regs->x30, ai->regs->elr); 114 EMSG_RAW("sp_el0 %016" PRIx64, ai->regs->sp_el0); 115 #endif /*ARM64*/ 116 } 117 118 static void tee_pager_print_user_abort(struct tee_pager_abort_info *ai __unused) 119 { 120 #ifdef CFG_TEE_CORE_TA_TRACE 121 tee_pager_print_detailed_abort(ai, "user TA"); 122 tee_ta_dump_current(); 123 #endif 124 } 125 126 void tee_pager_print_abort(struct tee_pager_abort_info *ai __unused) 127 { 128 #if (TRACE_LEVEL >= TRACE_INFO) 129 tee_pager_print_detailed_abort(ai, "core"); 130 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/ 131 } 132 133 134 135 void tee_pager_print_error_abort(struct tee_pager_abort_info *ai __unused) 136 { 137 #if (TRACE_LEVEL >= TRACE_INFO) 138 /* full verbose log at DEBUG level */ 139 tee_pager_print_detailed_abort(ai, "core"); 140 #else 141 #ifdef ARM32 142 EMSG("%s-abort at 0x%" PRIxVA "\n" 143 "FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X\n" 144 "CPUID 0x%x CPSR 0x%x (read from SPSR)", 145 abort_type_to_str(ai->abort_type), 146 ai->va, ai->fault_descr, ai->pc, read_ttbr0(), read_contextidr(), 147 read_mpidr(), read_spsr()); 148 #endif /*ARM32*/ 149 #ifdef ARM64 150 EMSG("%s-abort at 0x%" PRIxVA "\n" 151 "ESR 0x%x PC 0x%x TTBR0 0x%" PRIx64 " CONTEXIDR 0x%X\n" 152 "CPUID 0x%" PRIx64 " CPSR 0x%x (read from SPSR)", 153 abort_type_to_str(ai->abort_type), 154 ai->va, ai->fault_descr, ai->pc, read_ttbr0_el1(), 155 read_contextidr_el1(), 156 read_mpidr_el1(), (uint32_t)ai->regs->spsr); 157 #endif /*ARM64*/ 158 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/ 159 } 160 161 #ifdef ARM32 162 static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs, 163 struct tee_pager_abort_info *ai) 164 { 165 switch (abort_type) { 166 case THREAD_ABORT_DATA: 167 ai->fault_descr = read_dfsr(); 168 ai->va = read_dfar(); 169 break; 170 case THREAD_ABORT_PREFETCH: 171 ai->fault_descr = read_ifsr(); 172 ai->va = read_ifar(); 173 break; 174 default: 175 ai->fault_descr = 0; 176 ai->va = regs->elr; 177 break; 178 } 179 ai->abort_type = abort_type; 180 ai->pc = regs->elr; 181 ai->regs = regs; 182 } 183 #endif /*ARM32*/ 184 185 #ifdef ARM64 186 static void set_abort_info(uint32_t abort_type __unused, 187 struct thread_abort_regs *regs, struct tee_pager_abort_info *ai) 188 { 189 ai->fault_descr = read_esr_el1(); 190 switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { 191 case ESR_EC_IABT_EL0: 192 case ESR_EC_IABT_EL1: 193 ai->abort_type = THREAD_ABORT_PREFETCH; 194 ai->va = read_far_el1(); 195 break; 196 case ESR_EC_DABT_EL0: 197 case ESR_EC_DABT_EL1: 198 case ESR_EC_SP_ALIGN: 199 ai->abort_type = THREAD_ABORT_DATA; 200 ai->va = read_far_el1(); 201 break; 202 default: 203 ai->abort_type = THREAD_ABORT_UNDEF; 204 ai->va = regs->elr; 205 } 206 ai->pc = regs->elr; 207 ai->regs = regs; 208 } 209 #endif /*ARM64*/ 210 211 #ifdef ARM32 212 static void handle_user_ta_panic(struct tee_pager_abort_info *ai) 213 { 214 /* 215 * It was a user exception, stop user execution and return 216 * to TEE Core. 217 */ 218 ai->regs->r0 = TEE_ERROR_TARGET_DEAD; 219 ai->regs->r1 = true; 220 ai->regs->r2 = 0xdeadbeef; 221 ai->regs->elr = (uint32_t)thread_unwind_user_mode; 222 ai->regs->spsr = read_cpsr(); 223 ai->regs->spsr &= ~CPSR_MODE_MASK; 224 ai->regs->spsr |= CPSR_MODE_SVC; 225 ai->regs->spsr &= ~CPSR_FIA; 226 ai->regs->spsr |= read_spsr() & CPSR_FIA; 227 /* Select Thumb or ARM mode */ 228 if (ai->regs->elr & 1) 229 ai->regs->spsr |= CPSR_T; 230 else 231 ai->regs->spsr &= ~CPSR_T; 232 } 233 #endif /*ARM32*/ 234 235 #ifdef ARM64 236 static void handle_user_ta_panic(struct tee_pager_abort_info *ai) 237 { 238 uint32_t daif; 239 240 /* 241 * It was a user exception, stop user execution and return 242 * to TEE Core. 243 */ 244 ai->regs->x0 = TEE_ERROR_TARGET_DEAD; 245 ai->regs->x1 = true; 246 ai->regs->x2 = 0xdeadbeef; 247 ai->regs->elr = (vaddr_t)thread_unwind_user_mode; 248 ai->regs->sp_el0 = thread_get_saved_thread_sp(); 249 250 daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK; 251 /* XXX what about DAIF_D? */ 252 ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif); 253 } 254 #endif /*ARM64*/ 255 256 #ifdef ARM32 257 /* Returns true if the exception originated from user mode */ 258 static bool tee_pager_is_user_exception(struct tee_pager_abort_info *ai) 259 { 260 return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR; 261 } 262 #endif /*ARM32*/ 263 264 #ifdef ARM64 265 /* Returns true if the exception originated from user mode */ 266 static bool tee_pager_is_user_exception(struct tee_pager_abort_info *ai) 267 { 268 uint32_t spsr = ai->regs->spsr; 269 270 if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT)) 271 return true; 272 if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) == 273 SPSR_64_MODE_EL0) 274 return true; 275 return false; 276 } 277 #endif /*ARM64*/ 278 279 #ifdef ARM32 280 /* Returns true if the exception originated from abort mode */ 281 static bool tee_pager_is_abort_in_abort_handler(struct tee_pager_abort_info *ai) 282 { 283 return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_ABT; 284 } 285 #endif /*ARM32*/ 286 287 #ifdef ARM64 288 /* Returns true if the exception originated from abort mode */ 289 static bool tee_pager_is_abort_in_abort_handler( 290 struct tee_pager_abort_info *ai __unused) 291 { 292 return false; 293 } 294 #endif /*ARM64*/ 295 296 297 298 static enum tee_pager_fault_type tee_pager_get_fault_type( 299 struct tee_pager_abort_info *ai) 300 { 301 if (tee_pager_is_user_exception(ai)) { 302 tee_pager_print_user_abort(ai); 303 DMSG("[TEE_PAGER] abort in User mode (TA will panic)"); 304 return TEE_PAGER_FAULT_TYPE_USER_TA_PANIC; 305 } 306 307 if (tee_pager_is_abort_in_abort_handler(ai)) { 308 tee_pager_print_error_abort(ai); 309 EMSG("[PAGER] abort in abort handler (trap CPU)"); 310 panic(); 311 } 312 313 if (ai->abort_type == THREAD_ABORT_UNDEF) { 314 tee_pager_print_error_abort(ai); 315 EMSG("[TEE_PAGER] undefined abort (trap CPU)"); 316 panic(); 317 } 318 319 switch (core_mmu_get_fault_type(ai->fault_descr)) { 320 case CORE_MMU_FAULT_ALIGNMENT: 321 tee_pager_print_error_abort(ai); 322 EMSG("[TEE_PAGER] alignement fault! (trap CPU)"); 323 panic(); 324 break; 325 326 case CORE_MMU_FAULT_ACCESS_BIT: 327 tee_pager_print_error_abort(ai); 328 EMSG("[TEE_PAGER] access bit fault! (trap CPU)"); 329 panic(); 330 break; 331 332 case CORE_MMU_FAULT_DEBUG_EVENT: 333 tee_pager_print_abort(ai); 334 DMSG("[TEE_PAGER] Ignoring debug event!"); 335 return TEE_PAGER_FAULT_TYPE_IGNORE; 336 337 case CORE_MMU_FAULT_TRANSLATION: 338 case CORE_MMU_FAULT_WRITE_PERMISSION: 339 case CORE_MMU_FAULT_READ_PERMISSION: 340 return TEE_PAGER_FAULT_TYPE_PAGEABLE; 341 342 case CORE_MMU_FAULT_ASYNC_EXTERNAL: 343 tee_pager_print_abort(ai); 344 DMSG("[TEE_PAGER] Ignoring async external abort!"); 345 return TEE_PAGER_FAULT_TYPE_IGNORE; 346 347 case CORE_MMU_FAULT_OTHER: 348 default: 349 tee_pager_print_abort(ai); 350 DMSG("[TEE_PAGER] Unhandled fault!"); 351 return TEE_PAGER_FAULT_TYPE_IGNORE; 352 } 353 } 354 355 void tee_pager_abort_handler(uint32_t abort_type, 356 struct thread_abort_regs *regs) 357 { 358 struct tee_pager_abort_info ai; 359 360 set_abort_info(abort_type, regs, &ai); 361 362 switch (tee_pager_get_fault_type(&ai)) { 363 case TEE_PAGER_FAULT_TYPE_IGNORE: 364 break; 365 case TEE_PAGER_FAULT_TYPE_USER_TA_PANIC: 366 handle_user_ta_panic(&ai); 367 break; 368 case TEE_PAGER_FAULT_TYPE_PAGEABLE: 369 default: 370 tee_pager_handle_fault(&ai); 371 break; 372 } 373 } 374 375 376