1 /*
2  * Copyright (c) 2017, Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_
7 #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_
8 
9 #if defined(__XT_CLANG__)
10 #include <xtensa/xtensa-types.h>
11 #endif
12 
13 #include <xtensa/corebits.h>
14 #include <xtensa/config/core-isa.h>
15 #include <xtensa/config/tie.h>
16 
17 /*
18  * Stack frame layout for a saved processor context, in memory order,
19  * high to low address:
20  *
21  * SP-0 <-- Interrupted stack pointer points here
22  *
23  * SP-4   Caller A3 spill slot \
24  * SP-8   Caller A2 spill slot |
25  * SP-12  Caller A1 spill slot + (Part of ABI standard)
26  * SP-16  Caller A0 spill slot /
27  *
28  * SP-20  Saved A3
29  * SP-24  Saved A2
30  * SP-28  Unused (not "Saved A1" because the SP is saved externally as a handle)
31  * SP-32  Saved A0
32  *
33  * SP-36  Saved PC (address to jump to following restore)
34  * SP-40  Saved/interrupted PS special register
35  *
36  * SP-44  Saved SAR special register
37  *
38  * SP-48  Saved LBEG special register (if loops enabled)
39  * SP-52  Saved LEND special register (if loops enabled)
40  * SP-56  Saved LCOUNT special register (if loops enabled)
41  *
42  * SP-60  Saved SCOMPARE special register (if S32C1I enabled)
43  *
44  * SP-64  Saved EXCCAUSE special register
45  *
46  * SP-68  Saved THREADPTR special register (if processor has thread pointer)
47  *
48  *       (The above fixed-size region is known as the "base save area" in the
49  *        code below)
50  *
51  * - 18 FPU registers (if FPU is present and CONFIG_FPU_SHARING enabled)
52  *
53  * - Saved A7 \
54  * - Saved A6 |
55  * - Saved A5 +- If not in-use by another frame
56  * - Saved A4 /
57  *
58  * - Saved A11 \
59  * - Saved A10 |
60  * - Saved A9  +- If not in-use by another frame
61  * - Saved A8  /
62  *
63  * - Saved A15 \
64  * - Saved A14 |
65  * - Saved A13 +- If not in-use by another frame
66  * - Saved A12 /
67  *
68  * - Saved intermediate stack pointer (points to low word of base save
69  *   area, i.e. the saved LCOUNT or SAR).  The pointer to this value
70  *   (i.e. the final stack pointer) is stored externally as the
71  *   "restore handle" in the thread context.
72  *
73  * Essentially, you can recover a pointer to the BSA by loading *SP.
74  * Adding the fixed BSA size to that gets you back to the
75  * original/interrupted stack pointer.
76  */
77 
78 #ifndef __ASSEMBLER__
79 
80 #include <stdint.h>
81 #include <zephyr/toolchain.h>
82 
83 /**
84  * Base Save Area (BSA) during interrupt.
85  *
86  * This saves the registers during interrupt entrance
87  * so they can be restored later.
88  *
89  * Note that only A0-A3 are saved here. High registers
90  * are saved after the BSA.
91  */
92 struct xtensa_irq_base_save_area {
93 #if XCHAL_HAVE_FP && defined(CONFIG_CPU_HAS_FPU) && defined(CONFIG_FPU_SHARING)
94 	uintptr_t fcr;
95 	uintptr_t fsr;
96 	uintptr_t fpu0;
97 	uintptr_t fpu1;
98 	uintptr_t fpu2;
99 	uintptr_t fpu3;
100 	uintptr_t fpu4;
101 	uintptr_t fpu5;
102 	uintptr_t fpu6;
103 	uintptr_t fpu7;
104 	uintptr_t fpu8;
105 	uintptr_t fpu9;
106 	uintptr_t fpu10;
107 	uintptr_t fpu11;
108 	uintptr_t fpu12;
109 	uintptr_t fpu13;
110 	uintptr_t fpu14;
111 	uintptr_t fpu15;
112 #endif
113 
114 #if defined(CONFIG_XTENSA_HIFI_SHARING)
115 
116 	/*
117 	 * Carve space for the registers used by the HiFi audio engine
118 	 * coprocessor (which is always CP1). Carve additional space to
119 	 * manage alignment at run-time as we can not yet guarantee the
120 	 * alignment of the BSA.
121 	 */
122 
123 	uint8_t  hifi[XCHAL_CP1_SA_SIZE + XCHAL_CP1_SA_ALIGN];
124 #endif
125 
126 #if XCHAL_HAVE_THREADPTR
127 	uintptr_t threadptr;
128 #endif
129 
130 #if XCHAL_HAVE_S32C1I
131 	uintptr_t scompare1;
132 #endif
133 
134 	uintptr_t exccause;
135 
136 #if XCHAL_HAVE_LOOPS
137 	uintptr_t lcount;
138 	uintptr_t lend;
139 	uintptr_t lbeg;
140 #endif
141 
142 	uintptr_t sar;
143 	uintptr_t ps;
144 	uintptr_t pc;
145 	uintptr_t a0;
146 	uintptr_t scratch;
147 	uintptr_t a2;
148 	uintptr_t a3;
149 
150 	uintptr_t caller_a0;
151 	uintptr_t caller_a1;
152 	uintptr_t caller_a2;
153 	uintptr_t caller_a3;
154 };
155 
156 typedef struct xtensa_irq_base_save_area _xtensa_irq_bsa_t;
157 
158 /**
159  * Raw interrupt stack frame.
160  *
161  * This provides a raw interrupt stack frame to make it
162  * easier to construct general purpose code in loops.
163  * Avoid using this if possible.
164  */
165 struct xtensa_irq_stack_frame_raw {
166 	_xtensa_irq_bsa_t *ptr_to_bsa;
167 
168 	struct {
169 		uintptr_t r0;
170 		uintptr_t r1;
171 		uintptr_t r2;
172 		uintptr_t r3;
173 	} blks[3];
174 };
175 
176 typedef struct xtensa_irq_stack_frame_raw _xtensa_irq_stack_frame_raw_t;
177 
178 /**
179  * Interrupt stack frame containing A0 - A15.
180  */
181 struct xtensa_irq_stack_frame_a15 {
182 	_xtensa_irq_bsa_t *ptr_to_bsa;
183 
184 	uintptr_t a12;
185 	uintptr_t a13;
186 	uintptr_t a14;
187 	uintptr_t a15;
188 
189 	uintptr_t a8;
190 	uintptr_t a9;
191 	uintptr_t a10;
192 	uintptr_t a11;
193 
194 	uintptr_t a4;
195 	uintptr_t a5;
196 	uintptr_t a6;
197 	uintptr_t a7;
198 
199 	_xtensa_irq_bsa_t bsa;
200 };
201 
202 typedef struct xtensa_irq_stack_frame_a15 _xtensa_irq_stack_frame_a15_t;
203 
204 /**
205  * Interrupt stack frame containing A0 - A11.
206  */
207 struct xtensa_irq_stack_frame_a11 {
208 	_xtensa_irq_bsa_t *ptr_to_bsa;
209 
210 	uintptr_t a8;
211 	uintptr_t a9;
212 	uintptr_t a10;
213 	uintptr_t a11;
214 
215 	uintptr_t a4;
216 	uintptr_t a5;
217 	uintptr_t a6;
218 	uintptr_t a7;
219 
220 	_xtensa_irq_bsa_t bsa;
221 };
222 
223 typedef struct xtensa_irq_stack_frame_a11 _xtensa_irq_stack_frame_a11_t;
224 
225 /**
226  * Interrupt stack frame containing A0 - A7.
227  */
228 struct xtensa_irq_stack_frame_a7 {
229 	_xtensa_irq_bsa_t *ptr_to_bsa;
230 
231 	uintptr_t a4;
232 	uintptr_t a5;
233 	uintptr_t a6;
234 	uintptr_t a7;
235 
236 	_xtensa_irq_bsa_t bsa;
237 };
238 
239 typedef struct xtensa_irq_stack_frame_a7 _xtensa_irq_stack_frame_a7_t;
240 
241 /**
242  * Interrupt stack frame containing A0 - A3.
243  */
244 struct xtensa_irq_stack_frame_a3 {
245 	_xtensa_irq_bsa_t *ptr_to_bsa;
246 
247 	_xtensa_irq_bsa_t bsa;
248 };
249 
250 typedef struct xtensa_irq_stack_frame_a3 _xtensa_irq_stack_frame_a3_t;
251 
252 #endif /* __ASSEMBLER__ */
253 
254 #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ */
255