1 /*
2  * FreeRTOS Kernel V11.0.1
3  * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
4  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
5  *
6  * SPDX-License-Identifier: MIT
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of
9  * this software and associated documentation files (the "Software"), to deal in
10  * the Software without restriction, including without limitation the rights to
11  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12  * the Software, and to permit persons to whom the Software is furnished to do so,
13  * subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in all
16  * copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * https://www.FreeRTOS.org
26  * https://github.com/FreeRTOS
27  *
28  */
29 
30 /*
31  * XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
32  *
33  * This header contains definitions and macros for use primarily by Xtensa
34  * RTOS assembly coded source files. It includes and uses the Xtensa hardware
35  * abstraction layer (HAL) to deal with config specifics. It may also be
36  * included in C source files.
37  *
38  * !! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
39  *
40  * NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
41  */
42 
43 #ifndef XTENSA_CONTEXT_H
44 #define XTENSA_CONTEXT_H
45 
46 #ifdef __ASSEMBLER__
47     #include    <xtensa/coreasm.h>
48 #endif
49 
50 #include    <xtensa/config/tie.h>
51 #include    <xtensa/corebits.h>
52 #include    <xtensa/config/system.h>
53 
54 
55 /* Align a value up to nearest n-byte boundary, where n is a power of 2. */
56 #define ALIGNUP( n, val )    ( ( ( val ) + ( n ) - 1 ) & -( n ) )
57 
58 
59 /*
60  * -------------------------------------------------------------------------------
61  * Macros that help define structures for both C and assembler.
62  * -------------------------------------------------------------------------------
63  */
64 #if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
65 
66     #define STRUCT_BEGIN    .pushsection.text; .struct 0
67     #define STRUCT_FIELD( ctype, size, asname, name )        asname :.space size
68     #define STRUCT_AFIELD( ctype, size, asname, name, n )    asname :.space( size ) *( n )
69     #define STRUCT_END( sname )                              sname ## Size:; .popsection
70 
71 #else
72 
73     #define STRUCT_BEGIN    typedef struct {
74     #define STRUCT_FIELD( ctype, size, asname, name )        ctype name;
75     #define STRUCT_AFIELD( ctype, size, asname, name, n )    ctype name[ n ];
76     #define STRUCT_END( sname ) \
77 }                               \
78     sname;
79 
80 #endif //_ASMLANGUAGE || __ASSEMBLER__
81 
82 
83 /*
84  * -------------------------------------------------------------------------------
85  * INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
86  *
87  * A stack frame of this structure is allocated for any interrupt or exception.
88  * It goes on the current stack. If the RTOS has a system stack for handling
89  * interrupts, every thread stack must allow space for just one interrupt stack
90  * frame, then nested interrupt stack frames go on the system stack.
91  *
92  * The frame includes basic registers (explicit) and "extra" registers introduced
93  * by user TIE or the use of the MAC16 option in the user's Xtensa config.
94  * The frame size is minimized by omitting regs not applicable to user's config.
95  *
96  * For Windowed ABI, this stack frame includes the interruptee's base save area,
97  * another base save area to manage gcc nested functions, and a little temporary
98  * space to help manage the spilling of the register windows.
99  * -------------------------------------------------------------------------------
100  */
101 
102 STRUCT_BEGIN STRUCT_FIELD( long,
103                            4,
104                            XT_STK_EXIT,
105                            exit )      /* exit point for dispatch */
106 STRUCT_FIELD( long, 4, XT_STK_PC, pc ) /* return PC */
107 STRUCT_FIELD( long, 4, XT_STK_PS, ps ) /* return PS */
108 STRUCT_FIELD( long, 4, XT_STK_A0, a0 )
109 STRUCT_FIELD( long, 4, XT_STK_A1, a1 ) /* stack pointer before interrupt */
110 STRUCT_FIELD( long, 4, XT_STK_A2, a2 )
111 STRUCT_FIELD( long, 4, XT_STK_A3, a3 )
112 STRUCT_FIELD( long, 4, XT_STK_A4, a4 )
113 STRUCT_FIELD( long, 4, XT_STK_A5, a5 )
114 STRUCT_FIELD( long, 4, XT_STK_A6, a6 )
115 STRUCT_FIELD( long, 4, XT_STK_A7, a7 )
116 STRUCT_FIELD( long, 4, XT_STK_A8, a8 )
117 STRUCT_FIELD( long, 4, XT_STK_A9, a9 )
118 STRUCT_FIELD( long, 4, XT_STK_A10, a10 )
119 STRUCT_FIELD( long, 4, XT_STK_A11, a11 )
120 STRUCT_FIELD( long, 4, XT_STK_A12, a12 )
121 STRUCT_FIELD( long, 4, XT_STK_A13, a13 )
122 STRUCT_FIELD( long, 4, XT_STK_A14, a14 )
123 STRUCT_FIELD( long, 4, XT_STK_A15, a15 )
124 STRUCT_FIELD( long, 4, XT_STK_SAR, sar )
125 STRUCT_FIELD( long, 4, XT_STK_EXCCAUSE, exccause )
126 STRUCT_FIELD( long, 4, XT_STK_EXCVADDR, excvaddr )
127 #if XCHAL_HAVE_LOOPS
128     STRUCT_FIELD( long, 4, XT_STK_LBEG, lbeg )
129     STRUCT_FIELD( long, 4, XT_STK_LEND, lend )
130     STRUCT_FIELD( long, 4, XT_STK_LCOUNT, lcount )
131 #endif
132 #ifndef __XTENSA_CALL0_ABI__
133 /* Temporary space for saving stuff during window spill */
134     STRUCT_FIELD( long, 4, XT_STK_TMP0, tmp0 )
135     STRUCT_FIELD( long, 4, XT_STK_TMP1, tmp1 )
136     STRUCT_FIELD( long, 4, XT_STK_TMP2, tmp2 )
137 #endif
138 #ifdef XT_USE_SWPRI
139 /* Storage for virtual priority mask */
140     STRUCT_FIELD( long, 4, XT_STK_VPRI, vpri )
141 #endif
142 #ifdef XT_USE_OVLY
143 /* Storage for overlay state */
144     STRUCT_FIELD( long, 4, XT_STK_OVLY, ovly )
145 #endif
146 STRUCT_END( XtExcFrame )
147 
148 #if defined( _ASMLANGUAGE ) || defined( __ASSEMBLER__ )
149 #define XT_STK_NEXT1    XtExcFrameSize
150 #else
151 #define XT_STK_NEXT1    sizeof( XtExcFrame )
152 #endif
153 
154 /* Allocate extra storage if needed */
155 #if XCHAL_EXTRA_SA_SIZE != 0
156 
157     #if XCHAL_EXTRA_SA_ALIGN <= 16
158 #define XT_STK_EXTRA    ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 )
159     #else
160 /* If need more alignment than stack, add space for dynamic alignment */
161 #define XT_STK_EXTRA    ( ALIGNUP( XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1 ) + XCHAL_EXTRA_SA_ALIGN )
162     #endif
163 #define XT_STK_NEXT2    ( XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE )
164 
165 #else
166 
167 #define XT_STK_NEXT2    XT_STK_NEXT1
168 
169 #endif /* if XCHAL_EXTRA_SA_SIZE != 0 */
170 
171 /*
172  * -------------------------------------------------------------------------------
173  * This is the frame size. Add space for 4 registers (interruptee's base save
174  * area) and some space for gcc nested functions if any.
175  * -------------------------------------------------------------------------------
176  */
177 #define XT_STK_FRMSZ    ( ALIGNUP( 0x10, XT_STK_NEXT2 ) + 0x20 )
178 
179 
180 /*
181  * -------------------------------------------------------------------------------
182  * SOLICITED STACK FRAME FOR A THREAD
183  *
184  * A stack frame of this structure is allocated whenever a thread enters the
185  * RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
186  * It goes on the current thread's stack.
187  *
188  * The solicited frame only includes registers that are required to be preserved
189  * by the callee according to the compiler's ABI conventions, some space to save
190  * the return address for returning to the caller, and the caller's PS register.
191  *
192  * For Windowed ABI, this stack frame includes the caller's base save area.
193  *
194  * Note on XT_SOL_EXIT field:
195  *    It is necessary to distinguish a solicited from an interrupt stack frame.
196  *    This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
197  *    always at the same offset (0). It can be written with a code (usually 0)
198  *    to distinguish a solicted frame from an interrupt frame. An RTOS port may
199  *    opt to ignore this field if it has another way of distinguishing frames.
200  * -------------------------------------------------------------------------------
201  */
202 
203 STRUCT_BEGIN
204 #ifdef __XTENSA_CALL0_ABI__
205     STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit )
206     STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
207     STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
208     STRUCT_FIELD( long, 4, XT_SOL_NEXT, next )
209     STRUCT_FIELD( long, 4, XT_SOL_A12, a12 ) /* should be on 16-byte alignment */
210     STRUCT_FIELD( long, 4, XT_SOL_A13, a13 )
211     STRUCT_FIELD( long, 4, XT_SOL_A14, a14 )
212     STRUCT_FIELD( long, 4, XT_SOL_A15, a15 )
213 #else
214     STRUCT_FIELD( long, 4, XT_SOL_EXIT, exit )
215     STRUCT_FIELD( long, 4, XT_SOL_PC, pc )
216     STRUCT_FIELD( long, 4, XT_SOL_PS, ps )
217     STRUCT_FIELD( long, 4, XT_SOL_NEXT, next )
218     STRUCT_FIELD( long, 4, XT_SOL_A0, a0 ) /* should be on 16-byte alignment */
219     STRUCT_FIELD( long, 4, XT_SOL_A1, a1 )
220     STRUCT_FIELD( long, 4, XT_SOL_A2, a2 )
221     STRUCT_FIELD( long, 4, XT_SOL_A3, a3 )
222 #endif /* ifdef __XTENSA_CALL0_ABI__ */
223 STRUCT_END( XtSolFrame )
224 
225 /* Size of solicited stack frame */
226 #define XT_SOL_FRMSZ    ALIGNUP( 0x10, XtSolFrameSize )
227 
228 
229 /*
230  * -------------------------------------------------------------------------------
231  * CO-PROCESSOR STATE SAVE AREA FOR A THREAD
232  *
233  * The RTOS must provide an area per thread to save the state of co-processors
234  * when that thread does not have control. Co-processors are context-switched
235  * lazily (on demand) only when a new thread uses a co-processor instruction,
236  * otherwise a thread retains ownership of the co-processor even when it loses
237  * control of the processor. An Xtensa co-processor exception is triggered when
238  * any co-processor instruction is executed by a thread that is not the owner,
239  * and the context switch of that co-processor is then peformed by the handler.
240  * Ownership represents which thread's state is currently in the co-processor.
241  *
242  * Co-processors may not be used by interrupt or exception handlers. If an
243  * co-processor instruction is executed by an interrupt or exception handler,
244  * the co-processor exception handler will trigger a kernel panic and freeze.
245  * This restriction is introduced to reduce the overhead of saving and restoring
246  * co-processor state (which can be quite large) and in particular remove that
247  * overhead from interrupt handlers.
248  *
249  * The co-processor state save area may be in any convenient per-thread location
250  * such as in the thread control block or above the thread stack area. It need
251  * not be in the interrupt stack frame since interrupts don't use co-processors.
252  *
253  * Along with the save area for each co-processor, two bitmasks with flags per
254  * co-processor (laid out as in the CPENABLE reg) help manage context-switching
255  * co-processors as efficiently as possible:
256  *
257  * XT_CPENABLE
258  *  The contents of a non-running thread's CPENABLE register.
259  *  It represents the co-processors owned (and whose state is still needed)
260  *  by the thread. When a thread is preempted, its CPENABLE is saved here.
261  *  When a thread solicits a context-swtich, its CPENABLE is cleared - the
262  *  compiler has saved the (caller-saved) co-proc state if it needs to.
263  *  When a non-running thread loses ownership of a CP, its bit is cleared.
264  *  When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
265  *  Avoids co-processor exceptions when no change of ownership is needed.
266  *
267  * XT_CPSTORED
268  *  A bitmask with the same layout as CPENABLE, a bit per co-processor.
269  *  Indicates whether the state of each co-processor is saved in the state
270  *  save area. When a thread enters the kernel, only the state of co-procs
271  *  still enabled in CPENABLE is saved. When the co-processor exception
272  *  handler assigns ownership of a co-processor to a thread, it restores
273  *  the saved state only if this bit is set, and clears this bit.
274  *
275  * XT_CP_CS_ST
276  *  A bitmask with the same layout as CPENABLE, a bit per co-processor.
277  *  Indicates whether callee-saved state is saved in the state save area.
278  *  Callee-saved state is saved by itself on a solicited context switch,
279  *  and restored when needed by the coprocessor exception handler.
280  *  Unsolicited switches will cause the entire coprocessor to be saved
281  *  when necessary.
282  *
283  * XT_CP_ASA
284  *  Pointer to the aligned save area.  Allows it to be aligned more than
285  *  the overall save area (which might only be stack-aligned or TCB-aligned).
286  *  Especially relevant for Xtensa cores configured with a very large data
287  *  path that requires alignment greater than 16 bytes (ABI stack alignment).
288  * -------------------------------------------------------------------------------
289  */
290 
291 #if XCHAL_CP_NUM > 0
292 
293 /*  Offsets of each coprocessor save area within the 'aligned save area':  */
294 #define XT_CP0_SA        0
295 #define XT_CP1_SA        ALIGNUP( XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE )
296 #define XT_CP2_SA        ALIGNUP( XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE )
297 #define XT_CP3_SA        ALIGNUP( XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE )
298 #define XT_CP4_SA        ALIGNUP( XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE )
299 #define XT_CP5_SA        ALIGNUP( XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE )
300 #define XT_CP6_SA        ALIGNUP( XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE )
301 #define XT_CP7_SA        ALIGNUP( XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE )
302 #define XT_CP_SA_SIZE    ALIGNUP( 16, XT_CP7_SA + XCHAL_CP7_SA_SIZE )
303 
304 /*  Offsets within the overall save area:  */
305 #define XT_CPENABLE      0 /* (2 bytes) coprocessors active for this thread */
306 #define XT_CPSTORED      2 /* (2 bytes) coprocessors saved for this thread */
307 #define XT_CP_CS_ST      4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
308 #define XT_CP_ASA        8 /* (4 bytes) ptr to aligned save area */
309 /*  Overall size allows for dynamic alignment:  */
310 #define XT_CP_SIZE       ( 12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN )
311 #else /* if XCHAL_CP_NUM > 0 */
312 #define XT_CP_SIZE       0
313 #endif /* if XCHAL_CP_NUM > 0 */
314 
315 
316 /*
317  * -------------------------------------------------------------------------------
318  * MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
319  *
320  * Convenient where the frame size requirements are the same for both ABIs.
321  *  ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
322  *  ENTRY0,    RET0    are for frameless functions (no locals, no calls).
323  *
324  * where size = size of stack frame in bytes (must be >0 and aligned to 16).
325  * For framed functions the frame is created and the return address saved at
326  * base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
327  * For frameless functions, there is no frame and return address remains in a0.
328  * Note: Because CPP macros expand to a single line, macros requiring multi-line
329  * expansions are implemented as assembler macros.
330  * -------------------------------------------------------------------------------
331  */
332 
333 #ifdef __ASSEMBLER__
334     #ifdef __XTENSA_CALL0_ABI__
335         /* Call0 */
336 #define ENTRY( sz )    entry1 sz
337            .macro entry1 size = 0x10
338                                 addi sp, sp, -\ size
339         s32i a0, sp, 0
340            .endm
341 #define ENTRY0
342 #define RET( sz )    ret1 sz
343            .macro ret1 size = 0x10
344                               l32i a0, sp, 0
345         addi sp, sp, \ size
346         ret
347            .endm
348 #define RET0    ret
349     #else /* ifdef __XTENSA_CALL0_ABI__ */
350         /* Windowed */
351 #define ENTRY( sz )    entry sp, sz
352 #define ENTRY0    entry sp, 0x10
353 #define RET( sz )      retw
354 #define RET0      retw
355     #endif /* ifdef __XTENSA_CALL0_ABI__ */
356 #endif /* ifdef __ASSEMBLER__ */
357 
358 
359 #endif /* XTENSA_CONTEXT_H */
360