1 /*
2  * Copyright (c) 2013-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief ARM AArch32 public exception handling
10  *
11  * ARM AArch32-specific kernel exception handling interface. Included by
12  * arm/arch.h.
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_
16 #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_
17 
18 #if defined(CONFIG_CPU_CORTEX_M)
19 #include <zephyr/devicetree.h>
20 
21 #include <zephyr/arch/arm/aarch32/cortex_m/nvic.h>
22 
23 /* for assembler, only works with constants */
24 #define Z_EXC_PRIO(pri) (((pri) << (8 - NUM_IRQ_PRIO_BITS)) & 0xff)
25 
26 /*
27  * In architecture variants with non-programmable fault exceptions
28  * (e.g. Cortex-M Baseline variants), hardware ensures processor faults
29  * are given the highest interrupt priority level. SVCalls are assigned
30  * the highest configurable priority level (level 0); note, however, that
31  * this interrupt level may be shared with HW interrupts.
32  *
33  * In Cortex variants with programmable fault exception priorities we
34  * assign the highest interrupt priority level (level 0) to processor faults
35  * with configurable priority.
36  * The highest priority level may be shared with either Zero-Latency IRQs (if
37  * support for the feature is enabled) or with SVCall priority level.
38  * Regular HW IRQs are always assigned priority levels lower than the priority
39  * levels for SVCalls, Zero-Latency IRQs and processor faults.
40  *
41  * PendSV IRQ (which is used in Cortex-M variants to implement thread
42  * context-switching) is assigned the lowest IRQ priority level.
43  */
44 #if defined(CONFIG_CPU_CORTEX_M_HAS_PROGRAMMABLE_FAULT_PRIOS)
45 #define _EXCEPTION_RESERVED_PRIO 1
46 #else
47 #define _EXCEPTION_RESERVED_PRIO 0
48 #endif
49 
50 #define _EXC_FAULT_PRIO 0
51 #define _EXC_ZERO_LATENCY_IRQS_PRIO 0
52 #define _EXC_SVC_PRIO COND_CODE_1(CONFIG_ZERO_LATENCY_IRQS,		\
53 				  (CONFIG_ZERO_LATENCY_LEVELS), (0))
54 #define _IRQ_PRIO_OFFSET (_EXCEPTION_RESERVED_PRIO + _EXC_SVC_PRIO)
55 #define IRQ_PRIO_LOWEST (BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET) - 1)
56 
57 #define _EXC_IRQ_DEFAULT_PRIO Z_EXC_PRIO(_IRQ_PRIO_OFFSET)
58 
59 /* Use lowest possible priority level for PendSV */
60 #define _EXC_PENDSV_PRIO 0xff
61 #define _EXC_PENDSV_PRIO_MASK Z_EXC_PRIO(_EXC_PENDSV_PRIO)
62 #endif /* CONFIG_CPU_CORTEX_M */
63 
64 #ifdef _ASMLANGUAGE
65 GTEXT(z_arm_exc_exit);
66 #else
67 #include <zephyr/types.h>
68 
69 #ifdef __cplusplus
70 extern "C" {
71 #endif
72 
73 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
74 struct __fpu_sf {
75 	float s[16];
76 	uint32_t fpscr;
77 	uint32_t undefined;
78 };
79 #endif
80 
81 /* Additional register state that is not stacked by hardware on exception
82  * entry.
83  *
84  * These fields are ONLY valid in the ESF copy passed into z_arm_fatal_error().
85  * When information for a member is unavailable, the field is set to zero.
86  */
87 #if defined(CONFIG_EXTRA_EXCEPTION_INFO)
88 struct __extra_esf_info {
89 	_callee_saved_t *callee;
90 	uint32_t msp;
91 	uint32_t exc_return;
92 };
93 #endif /* CONFIG_EXTRA_EXCEPTION_INFO */
94 
95 #if defined(CONFIG_CPU_CORTEX_M)
96 
97 struct __esf {
98 	struct __basic_sf {
99 		sys_define_gpr_with_alias(a1, r0);
100 		sys_define_gpr_with_alias(a2, r1);
101 		sys_define_gpr_with_alias(a3, r2);
102 		sys_define_gpr_with_alias(a4, r3);
103 		sys_define_gpr_with_alias(ip, r12);
104 		sys_define_gpr_with_alias(lr, r14);
105 		sys_define_gpr_with_alias(pc, r15);
106 		uint32_t xpsr;
107 	} basic;
108 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
109 	struct __fpu_sf fpu;
110 #endif
111 #if defined(CONFIG_EXTRA_EXCEPTION_INFO)
112 	struct __extra_esf_info extra_info;
113 #endif
114 };
115 
116 #else
117 
118 struct __esf {
119 #if defined(CONFIG_EXTRA_EXCEPTION_INFO)
120 	struct __extra_esf_info extra_info;
121 #endif
122 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
123 	struct __fpu_sf fpu;
124 #endif
125 	struct __basic_sf {
126 		sys_define_gpr_with_alias(a1, r0);
127 		sys_define_gpr_with_alias(a2, r1);
128 		sys_define_gpr_with_alias(a3, r2);
129 		sys_define_gpr_with_alias(a4, r3);
130 		sys_define_gpr_with_alias(ip, r12);
131 		sys_define_gpr_with_alias(lr, r14);
132 		sys_define_gpr_with_alias(pc, r15);
133 		uint32_t xpsr;
134 	} basic;
135 };
136 
137 #endif
138 
139 extern uint32_t z_arm_coredump_fault_sp;
140 
141 typedef struct __esf z_arch_esf_t;
142 
143 #ifdef CONFIG_CPU_CORTEX_M
144 extern void z_arm_exc_exit(void);
145 #else
146 extern void z_arm_exc_exit(bool fatal);
147 #endif
148 
149 #ifdef __cplusplus
150 }
151 #endif
152 
153 #endif /* _ASMLANGUAGE */
154 
155 #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ */
156