1/**************************************************************************/
2/*   Copyright (c) Cadence Design Systems, Inc.                           */
3/*                                                                        */
4/* Permission is hereby granted, free of charge, to any person obtaining  */
5/* a copy of this software and associated documentation files (the        */
6/* "Software"), to deal in the Software without restriction, including    */
7/* without limitation the rights to use, copy, modify, merge, publish,    */
8/* distribute, sublicense, and/or sell copies of the Software, and to     */
9/* permit persons to whom the Software is furnished to do so, subject to  */
10/* the following conditions:                                              */
11/*                                                                        */
12/* The above copyright notice and this permission notice shall be         */
13/* included in all copies or substantial portions of the Software.        */
14/*                                                                        */
15/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */
16/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */
17/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
18/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */
19/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */
20/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */
21/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
22/**************************************************************************/
23
24
25/**************************************************************************/
26/*                                                                        */
27/*  DESCRIPTION                                                           */
28/*                                                                        */
29/*    XTENSA CONTEXT SAVE AND RESTORE ROUTINES                            */
30/*                                                                        */
31/* Low-level functions for handling generic context save and restore of   */
32/* registers not specifically addressed by the interrupt vectors and      */
33/* handlers. Those registers (not handled by these functions) are PC, PS, */
34/* A0, A1 (SP). Except for the calls to RTOS functions, this code is      */
35/* generic to Xtensa.                                                     */
36/*                                                                        */
37/* Note that in Call0 ABI, interrupt handlers are expected to preserve    */
38/* the callee-save regs (A12-A15), which is always the case if the        */
39/* handlers are coded in C. However A12, A13 are made available as        */
40/* scratch registers for interrupt dispatch code, so are presumed saved   */
41/* anyway, and are always restored even in Call0 ABI. Only A14, A15 are   */
42/* truly handled as callee-save regs.                                     */
43/*                                                                        */
44/*  RELEASE HISTORY                                                       */
45/*                                                                        */
46/*    DATE              NAME                      DESCRIPTION             */
47/*                                                                        */
48/*  12-31-2020     Cadence Design Systems   Initial Version 6.1.3         */
49/*                                                                        */
50/**************************************************************************/
51
52
53#include "xtensa_rtos.h"
54
55#ifdef XT_USE_OVLY
56#include <xtensa/overlay_os_asm.h>
57#endif
58
59    .text
60
61#if XCHAL_HAVE_XEA2
62
63/***************************************************************************
64
65    _xt_context_save
66
67    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
68
69Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the
70interrupt stack frame defined in xtensa_rtos.h.
71Its counterpart is _xt_context_restore (which also restores A12, A13).
72
73Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.
74This function preserves A12 & A13 in order to provide the caller with 2 scratch
75regs that need not be saved over the call to this function. The choice of which
762 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,
77to avoid moving data more than necessary. Caller can assign regs accordingly.
78
79Entry Conditions:
80    A0  = Return address in caller.
81    A1  = Stack pointer of interrupted thread or handler ("interruptee").
82    Original A12, A13 have already been saved in the interrupt stack frame.
83    Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the
84    point of interruption.
85    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
86
87Exit conditions:
88    A0  = Return address in caller.
89    A1  = Stack pointer of interrupted thread or handler ("interruptee").
90    A12, A13 as at entry (preserved).
91    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
92
93***************************************************************************/
94
95    .global _xt_context_save
96    .type   _xt_context_save,@function
97    .align  4
98_xt_context_save:
99
100    s32i    a2,  sp, XT_STK_A2
101    s32i    a3,  sp, XT_STK_A3
102    s32i    a4,  sp, XT_STK_A4
103    s32i    a5,  sp, XT_STK_A5
104    s32i    a6,  sp, XT_STK_A6
105    s32i    a7,  sp, XT_STK_A7
106    s32i    a8,  sp, XT_STK_A8
107    s32i    a9,  sp, XT_STK_A9
108    s32i    a10, sp, XT_STK_A10
109    s32i    a11, sp, XT_STK_A11
110
111    /*
112    Call0 ABI callee-saved regs a12-15 do not need to be saved here.
113    a12-13 are the caller's responsibility so it can use them as scratch.
114    So only need to save a14-a15 here for Windowed ABI (not Call0).
115    */
116    #ifndef __XTENSA_CALL0_ABI__
117    s32i    a14, sp, XT_STK_A14
118    s32i    a15, sp, XT_STK_A15
119    #endif
120
121    rsr     a3,  SAR
122    s32i    a3,  sp, XT_STK_SAR
123
124    #if XCHAL_HAVE_LOOPS
125    rsr     a3,  LBEG
126    s32i    a3,  sp, XT_STK_LBEG
127    rsr     a3,  LEND
128    s32i    a3,  sp, XT_STK_LEND
129    rsr     a3,  LCOUNT
130    s32i    a3,  sp, XT_STK_LCOUNT
131    #endif
132
133    #if XCHAL_HAVE_EXCLUSIVE
134    /* Save and clear state of ATOMCTL */
135    movi    a3,  0
136    getex   a3
137    s32i    a3,  sp, XT_STK_ATOMCTL
138    #endif
139
140    #if XT_USE_SWPRI
141    /* Save virtual priority mask */
142    movi    a3,  _xt_vpri_mask
143    l32i    a3,  a3, 0
144    s32i    a3,  sp, XT_STK_VPRI
145    #endif
146
147    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
148    mov     a9,  a0                     /* preserve ret addr */
149    #endif
150
151    #ifndef __XTENSA_CALL0_ABI__
152    /*
153    To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.
154    Need to save a9,12,13 temporarily (in frame temps) and recover originals.
155    Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow
156    and underflow exceptions disabled (assured by PS.EXCM == 1).
157    */
158    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */
159    s32i    a13, sp, XT_STK_TMP1
160    s32i    a9,  sp, XT_STK_TMP2
161
162    /*
163    Save the overlay state if we are supporting overlays. Since we just saved
164    three registers, we can conveniently use them here. Note that as of now,
165    overlays only work for windowed calling ABI.
166    */
167    #ifdef XT_USE_OVLY
168    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */
169    _xt_overlay_get_state    a9, a12, a13
170    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */
171    #endif
172
173    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */
174    l32i    a13, sp, XT_STK_A13
175    l32i    a9,  sp, XT_STK_A9
176    addi    sp,  sp, XT_STK_FRMSZ       /* restore the interruptee's SP */
177    call0   xthal_window_spill_nw       /* preserves only a4,5,8,9,12,13 */
178    addi    sp,  sp, -XT_STK_FRMSZ
179    l32i    a12, sp, XT_STK_TMP0        /* recover stuff from stack frame */
180    l32i    a13, sp, XT_STK_TMP1
181    l32i    a9,  sp, XT_STK_TMP2
182    #endif
183
184    #if XCHAL_EXTRA_SA_SIZE > 0
185    /*
186    NOTE: Normally the xthal_save_extra_nw macro only affects address
187    registers a2-a5. It is theoretically possible for Xtensa processor
188    designers to write TIE that causes more address registers to be
189    affected, but it is generally unlikely. If that ever happens,
190    more registers need to be saved/restored around this macro invocation.
191    Here we assume a9,12,13 are preserved.
192    Future Xtensa tools releases might limit the regs that can be affected.
193    */
194    addi    a2,  sp, XT_STK_EXTRA       /* where to save it */
195    # if XCHAL_EXTRA_SA_ALIGN > 16
196    movi    a3, -XCHAL_EXTRA_SA_ALIGN
197    and     a2, a2, a3                  /* align dynamically >16 bytes */
198    # endif
199    call0   xthal_save_extra_nw         /* destroys a0,2,3,4,5 */
200    #endif
201
202    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
203    mov     a0, a9                      /* retrieve ret addr */
204    #endif
205
206    ret
207
208/*******************************************************************************
209
210_xt_context_restore
211
212    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
213
214Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0
215ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt
216stack frame defined in xtensa_rtos.h .
217Its counterpart is _xt_context_save (whose caller saved A12, A13).
218
219Caller is responsible to restore PC, PS, A0, A1 (SP).
220
221Entry Conditions:
222    A0  = Return address in caller.
223    A1  = Stack pointer of interrupted thread or handler ("interruptee").
224
225Exit conditions:
226    A0  = Return address in caller.
227    A1  = Stack pointer of interrupted thread or handler ("interruptee").
228    Other processor state except PC, PS, A0, A1 (SP), is as at the point
229    of interruption.
230
231*******************************************************************************/
232
233    .global _xt_context_restore
234    .type   _xt_context_restore,@function
235    .align  4
236_xt_context_restore:
237
238    #if XCHAL_EXTRA_SA_SIZE > 0
239    /*
240    NOTE: Normally the xthal_restore_extra_nw macro only affects address
241    registers a2-a5. It is theoretically possible for Xtensa processor
242    designers to write TIE that causes more address registers to be
243    affected, but it is generally unlikely. If that ever happens,
244    more registers need to be saved/restored around this macro invocation.
245    Here we only assume a13 is preserved.
246    Future Xtensa tools releases might limit the regs that can be affected.
247    */
248    mov     a13, a0                     /* preserve ret addr */
249    addi    a2,  sp, XT_STK_EXTRA       /* where to find it */
250    # if XCHAL_EXTRA_SA_ALIGN > 16
251    movi    a3, -XCHAL_EXTRA_SA_ALIGN
252    and     a2, a2, a3                  /* align dynamically >16 bytes */
253    # endif
254    call0   xthal_restore_extra_nw      /* destroys a0,2,3,4,5 */
255    mov     a0,  a13                    /* retrieve ret addr */
256    #endif
257
258    #if XCHAL_HAVE_LOOPS
259    l32i    a2,  sp, XT_STK_LBEG
260    l32i    a3,  sp, XT_STK_LEND
261    wsr     a2,  LBEG
262    l32i    a2,  sp, XT_STK_LCOUNT
263    wsr     a3,  LEND
264    wsr     a2,  LCOUNT
265    #endif
266
267    #if XCHAL_HAVE_EXCLUSIVE
268    /* Restore state of ATOMCTL */
269    l32i    a2,  sp, XT_STK_ATOMCTL
270    getex   a2
271    #endif
272
273    #ifdef XT_USE_OVLY
274    /*
275    If we are using overlays, this is a good spot to check if we need
276    to restore an overlay for the incoming task. Here we have a bunch
277    of registers to spare. Note that this step is going to use a few
278    bytes of storage below SP (SP-20 to SP-32) if an overlay is going
279    to be restored.
280    */
281    l32i    a2,  sp, XT_STK_PC          /* retrieve PC */
282    l32i    a3,  sp, XT_STK_PS          /* retrieve PS */
283    l32i    a4,  sp, XT_STK_OVLY        /* retrieve overlay state */
284    l32i    a5,  sp, XT_STK_A1          /* retrieve stack ptr */
285    _xt_overlay_check_map    a2, a3, a4, a5, a6
286    s32i    a2,  sp, XT_STK_PC          /* save updated PC */
287    s32i    a3,  sp, XT_STK_PS          /* save updated PS */
288    #endif
289
290    #ifdef XT_USE_SWPRI
291    /* Restore virtual interrupt priority and interrupt enable */
292    movi    a3,  _xt_intdata
293    l32i    a4,  a3, 0                  /* a4 = _xt_intenable */
294    l32i    a5,  sp, XT_STK_VPRI        /* a5 = saved _xt_vpri_mask */
295    and     a4,  a4, a5
296    wsr     a4,  INTENABLE              /* update INTENABLE */
297    s32i    a5,  a3, 4                  /* restore _xt_vpri_mask */
298    #endif
299
300    l32i    a3,  sp, XT_STK_SAR
301    l32i    a2,  sp, XT_STK_A2
302    wsr     a3,  SAR
303    l32i    a3,  sp, XT_STK_A3
304    l32i    a4,  sp, XT_STK_A4
305    l32i    a5,  sp, XT_STK_A5
306    l32i    a6,  sp, XT_STK_A6
307    l32i    a7,  sp, XT_STK_A7
308    l32i    a8,  sp, XT_STK_A8
309    l32i    a9,  sp, XT_STK_A9
310    l32i    a10, sp, XT_STK_A10
311    l32i    a11, sp, XT_STK_A11
312
313    /*
314    Call0 ABI callee-saved regs a12-15 do not need to be restored here.
315    However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(),
316    so need to be restored anyway, despite being callee-saved in Call0.
317    */
318    l32i    a12, sp, XT_STK_A12
319    l32i    a13, sp, XT_STK_A13
320    #ifndef __XTENSA_CALL0_ABI__
321    l32i    a14, sp, XT_STK_A14
322    l32i    a15, sp, XT_STK_A15
323    #endif
324
325    ret
326
327#endif /* XCHAL_HAVE_XEA3 */
328
329
330/*******************************************************************************
331
332_xt_coproc_init
333
334Initializes global co-processor management data, setting all co-processors
335to "unowned". Leaves CPENABLE as it found it (does NOT clear it).
336
337Called during initialization of the RTOS, before any threads run.
338
339This may be called from normal Xtensa single-threaded application code which
340might use co-processors. The Xtensa run-time initialization enables all
341co-processors. They must remain enabled here, else a co-processor exception
342might occur outside of a thread, which the exception handler doesn't expect.
343
344Entry Conditions:
345    Xtensa single-threaded run-time environment is in effect.
346    No thread is yet running.
347
348Exit conditions:
349    None.
350
351Obeys ABI conventions per prototype:
352    void _xt_coproc_init(void)
353
354*******************************************************************************/
355
356#if XCHAL_CP_NUM > 0
357
358    .global _xt_coproc_init
359    .type   _xt_coproc_init,@function
360    .align  4
361_xt_coproc_init:
362    ENTRY0
363
364    /* Initialize thread co-processor ownerships to 0 (unowned). */
365    movi    a2, _xt_coproc_owner_sa         /* a2 = base of owner array */
366    addi    a3, a2, XCHAL_CP_MAX << 2       /* a3 = top+1 of owner array */
367    movi    a4, 0                           /* a4 = 0 (unowned) */
3681:  s32i    a4, a2, 0
369    addi    a2, a2, 4
370    bltu    a2, a3, 1b
371
372    RET0
373
374#endif
375
376
377/*******************************************************************************
378
379_xt_coproc_release
380
381Releases any and all co-processors owned by a given thread. The thread is
382identified by it's co-processor state save area defined in xtensa_context.h .
383
384Must be called before a thread's co-proc save area is deleted to avoid
385memory corruption when the exception handler tries to save the state.
386May be called when a thread terminates or completes but does not delete
387the co-proc save area, to avoid the exception handler having to save the
388thread's co-proc state before another thread can use it (optimization).
389
390Entry Conditions:
391    A2  = Pointer to base of co-processor state save area.
392
393Exit conditions:
394    None.
395
396Obeys ABI conventions per prototype:
397    void _xt_coproc_release(void * coproc_sa_base)
398
399*******************************************************************************/
400
401#if XCHAL_CP_NUM > 0
402
403    .global _xt_coproc_release
404    .type   _xt_coproc_release,@function
405    .align  4
406_xt_coproc_release:
407    ENTRY0                                  /* a2 = base of save area */
408
409    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */
410    addi    a4, a3, XCHAL_CP_MAX << 2       /* a4 = top+1 of owner array */
411    movi    a5, 0                           /* a5 = 0 (unowned) */
412
413#if XCHAL_HAVE_XEA3
414    movi    a6, PS_DI
415    xps     a6, a6                          /* lock interrupts */
416#else
417    rsil    a6, XCHAL_EXCM_LEVEL            /* lock interrupts */
418#endif
419
4201:  l32i    a7, a3, 0                       /* a7 = owner at a3 */
421    bne     a2, a7, 2f                      /* if (coproc_sa_base == owner) */
422    s32i    a5, a3, 0                       /*   owner = unowned */
4232:  addi    a3, a3, 1<<2                    /* a3 = next entry in owner array */
424    bltu    a3, a4, 1b                      /* repeat until end of array */
425
4263:
427    wsr     a6, PS                          /* restore interrupts */
428    rsync
429
430    RET0
431
432#endif
433
434