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