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