1 /* 2 * Copyright (c) 2021, Nordic Semiconductor ASA. All rights reserved. 3 * Copyright (c) 2023, Arm Limited. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #ifndef __EXCEPTION_INFO_H__ 9 #define __EXCEPTION_INFO_H__ 10 11 #include <stdint.h> 12 13 #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) 14 #define TRUSTZONE_PRESENT 15 #endif 16 17 #if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__) \ 18 || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) 19 #define FAULT_STATUS_PRESENT 20 #endif 21 22 /* Exception type number (subtract 16 for IRQn) */ 23 #define EXCEPTION_TYPE_HARDFAULT 3 24 #define EXCEPTION_TYPE_MEMMANAGEFAULT 4 25 #define EXCEPTION_TYPE_BUSFAULT 5 26 #define EXCEPTION_TYPE_USAGEFAULT 6 27 #define EXCEPTION_TYPE_SECUREFAULT 7 28 29 /* Store context for an exception, and print an error message with the context. 30 * 31 * @param[in] exception_type One of the EXCEPTION_TYPE_* values defined above. Any 32 * other value will result in printing "Unknown". 33 */ 34 #ifdef TFM_EXCEPTION_INFO_DUMP 35 36 struct exception_info_t { 37 uint32_t VECTACTIVE; /* Active exception number. */ 38 uint32_t EXC_RETURN; /* EXC_RETURN value in LR. */ 39 uint32_t MSP; /* (Secure) MSP. */ 40 uint32_t PSP; /* (Secure) PSP. */ 41 uint32_t *EXC_FRAME; /* Exception frame on stack. */ 42 uint32_t EXC_FRAME_COPY[8]; /* Copy of the basic exception frame. */ 43 uint32_t CALLEE_SAVED_COPY[8]; /* Copy of the callee saved registers. */ 44 uint32_t xPSR; /* Program Status Registers. */ 45 46 #ifdef FAULT_STATUS_PRESENT 47 uint32_t CFSR; /* Configurable Fault Status Register. */ 48 uint32_t HFSR; /* Hard Fault Status Register. */ 49 uint32_t BFAR; /* Bus Fault address register. */ 50 uint32_t BFARVALID; /* Whether BFAR contains a valid address. */ 51 uint32_t MMFAR; /* MemManage Fault address register. */ 52 uint32_t MMARVALID; /* Whether MMFAR contains a valid address. */ 53 #ifdef TRUSTZONE_PRESENT 54 uint32_t SFSR; /* SecureFault Status Register. */ 55 uint32_t SFAR; /* SecureFault Address Register. */ 56 uint32_t SFARVALID; /* Whether SFAR contains a valid address. */ 57 #endif 58 #endif 59 }; 60 61 /** 62 * \brief Get a pointer to the current exception_info_t context 63 * 64 * \return A pointer to the exception_info_t context or NULL if no context 65 * has been stored 66 */ 67 void tfm_exception_info_get_context(struct exception_info_t *ctx); 68 69 /* Store context for an exception, then print the info. 70 * Call EXCEPTION_INFO() instead of calling this directly. 71 */ 72 void store_and_dump_context(uint32_t MSP_in, uint32_t PSP_in, uint32_t LR_in, 73 uint32_t *callee_saved); 74 75 /* IAR Specific */ 76 #if defined(__ICCARM__) 77 #pragma required = store_and_dump_context 78 #endif 79 80 #if defined(__ARM_ARCH_8M_BASE__) || defined(__ARCM_ARCH_V6_M__) 81 #define EXCEPTION_INFO() \ 82 __ASM volatile( \ 83 "MRS R0, MSP\n" \ 84 "MRS R1, PSP\n" \ 85 "MOV R2, R11\n" \ 86 "MOV R3, R10\n" \ 87 "PUSH {R2, R3}\n" \ 88 "MOV R2, R9\n" \ 89 "MOV R3, R8\n" \ 90 "PUSH {R2, R3}\n" \ 91 "PUSH {R4-R7}\n" \ 92 "MOV R3, SP\n" \ 93 "MOV R2, LR\n" \ 94 "BL store_and_dump_context\n" \ 95 "ADD SP, #32\n" \ 96 ) 97 #elif defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \ 98 defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) 99 #define EXCEPTION_INFO() \ 100 __ASM volatile( \ 101 "MRS R0, MSP\n" \ 102 "MRS R1, PSP\n" \ 103 "PUSH {R4-R11}\n" \ 104 "MOV R3, SP\n" \ 105 "MOV R2, LR\n" \ 106 "BL store_and_dump_context\n" \ 107 "ADD SP, #32\n" \ 108 ) 109 #else 110 /* Unhandled arch, call store_and_dump_context with callee_saved = NULL */ 111 #define EXCEPTION_INFO() \ 112 __ASM volatile( \ 113 "MRS R0, MSP\n" \ 114 "MRS R1, PSP\n" \ 115 "MOV R2, LR\n" \ 116 "MOV R3, #0\n" \ 117 "BL store_and_dump_context\n" \ 118 ) 119 #endif 120 121 #else /* TFM_EXCEPTION_INFO_DUMP */ 122 #define EXCEPTION_INFO() 123 #endif /* TFM_EXCEPTION_INFO_DUMP */ 124 125 #endif /* __EXCEPTION_INFO_H__ */ 126