]> begriffs open source - freertos/blob - portable/GCC/ARM_CA53_64_BIT/portASM.S
Update SMP branch readme for port migration (#999)
[freertos] / portable / GCC / ARM_CA53_64_BIT / portASM.S
1 /*
2  * FreeRTOS SMP Kernel V202110.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  * 1 tab == 4 spaces!
26  */
27
28         .text
29
30         /* Variables and functions. */
31         .extern ullMaxAPIPriorityMask
32         .extern pxCurrentTCB
33         .extern vTaskSwitchContext
34         .extern vApplicationIRQHandler
35         .extern ullPortInterruptNesting
36         .extern ullPortTaskHasFPUContext
37         .extern ullCriticalNesting
38         .extern ullPortYieldRequired
39         .extern ullICCEOIR
40         .extern ullICCIAR
41         .extern _freertos_vector_table
42
43         .global FreeRTOS_IRQ_Handler
44         .global FreeRTOS_SWI_Handler
45         .global vPortRestoreTaskContext
46
47
48 .macro portSAVE_CONTEXT
49
50         /* Switch to use the EL0 stack pointer. */
51         MSR     SPSEL, #0
52
53         /* Save the entire context. */
54         STP     X0, X1, [SP, #-0x10]!
55         STP     X2, X3, [SP, #-0x10]!
56         STP     X4, X5, [SP, #-0x10]!
57         STP     X6, X7, [SP, #-0x10]!
58         STP     X8, X9, [SP, #-0x10]!
59         STP     X10, X11, [SP, #-0x10]!
60         STP     X12, X13, [SP, #-0x10]!
61         STP     X14, X15, [SP, #-0x10]!
62         STP     X16, X17, [SP, #-0x10]!
63         STP     X18, X19, [SP, #-0x10]!
64         STP     X20, X21, [SP, #-0x10]!
65         STP     X22, X23, [SP, #-0x10]!
66         STP     X24, X25, [SP, #-0x10]!
67         STP     X26, X27, [SP, #-0x10]!
68         STP     X28, X29, [SP, #-0x10]!
69         STP     X30, XZR, [SP, #-0x10]!
70
71         /* Save the SPSR. */
72 #if defined( GUEST )
73         MRS             X3, SPSR_EL1
74         MRS             X2, ELR_EL1
75 #else
76         MRS             X3, SPSR_EL3
77         /* Save the ELR. */
78         MRS             X2, ELR_EL3
79 #endif
80
81         STP     X2, X3, [SP, #-0x10]!
82
83         /* Save the critical section nesting depth. */
84         LDR             X0, ullCriticalNestingConst
85         LDR             X3, [X0]
86
87         /* Save the FPU context indicator. */
88         LDR             X0, ullPortTaskHasFPUContextConst
89         LDR             X2, [X0]
90
91         /* Save the FPU context, if any (32 128-bit registers). */
92         CMP             X2, #0
93         B.EQ    1f
94         STP             Q0, Q1, [SP,#-0x20]!
95         STP             Q2, Q3, [SP,#-0x20]!
96         STP             Q4, Q5, [SP,#-0x20]!
97         STP             Q6, Q7, [SP,#-0x20]!
98         STP             Q8, Q9, [SP,#-0x20]!
99         STP             Q10, Q11, [SP,#-0x20]!
100         STP             Q12, Q13, [SP,#-0x20]!
101         STP             Q14, Q15, [SP,#-0x20]!
102         STP             Q16, Q17, [SP,#-0x20]!
103         STP             Q18, Q19, [SP,#-0x20]!
104         STP             Q20, Q21, [SP,#-0x20]!
105         STP             Q22, Q23, [SP,#-0x20]!
106         STP             Q24, Q25, [SP,#-0x20]!
107         STP             Q26, Q27, [SP,#-0x20]!
108         STP             Q28, Q29, [SP,#-0x20]!
109         STP             Q30, Q31, [SP,#-0x20]!
110
111 1:
112         /* Store the critical nesting count and FPU context indicator. */
113         STP     X2, X3, [SP, #-0x10]!
114
115         LDR     X0, pxCurrentTCBConst
116         LDR     X1, [X0]
117         MOV     X0, SP   /* Move SP into X0 for saving. */
118         STR     X0, [X1]
119
120         /* Switch to use the ELx stack pointer. */
121         MSR     SPSEL, #1
122
123         .endm
124
125 ; /**********************************************************************/
126
127 .macro portRESTORE_CONTEXT
128
129         /* Switch to use the EL0 stack pointer. */
130         MSR     SPSEL, #0
131
132         /* Set the SP to point to the stack of the task being restored. */
133         LDR             X0, pxCurrentTCBConst
134         LDR             X1, [X0]
135         LDR             X0, [X1]
136         MOV             SP, X0
137
138         LDP     X2, X3, [SP], #0x10  /* Critical nesting and FPU context. */
139
140         /* Set the PMR register to be correct for the current critical nesting
141         depth. */
142         LDR             X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
143         MOV             X1, #255                                        /* X1 holds the unmask value. */
144         LDR             X4, ullICCPMRConst                      /* X4 holds the address of the ICCPMR constant. */
145         CMP             X3, #0
146         LDR             X5, [X4]                                        /* X5 holds the address of the ICCPMR register. */
147         B.EQ    1f
148         LDR             X6, ullMaxAPIPriorityMaskConst
149         LDR             X1, [X6]                                        /* X1 holds the mask value. */
150 1:
151         STR             W1, [X5]                                        /* Write the mask value to ICCPMR. */
152         DSB     SY                                                      /* _RB_Barriers probably not required here. */
153         ISB     SY
154         STR             X3, [X0]                                        /* Restore the task's critical nesting count. */
155
156         /* Restore the FPU context indicator. */
157         LDR             X0, ullPortTaskHasFPUContextConst
158         STR             X2, [X0]
159
160         /* Restore the FPU context, if any. */
161         CMP             X2, #0
162         B.EQ    1f
163         LDP             Q30, Q31, [SP], #0x20
164         LDP             Q28, Q29, [SP], #0x20
165         LDP             Q26, Q27, [SP], #0x20
166         LDP             Q24, Q25, [SP], #0x20
167         LDP             Q22, Q23, [SP], #0x20
168         LDP             Q20, Q21, [SP], #0x20
169         LDP             Q18, Q19, [SP], #0x20
170         LDP             Q16, Q17, [SP], #0x20
171         LDP             Q14, Q15, [SP], #0x20
172         LDP             Q12, Q13, [SP], #0x20
173         LDP             Q10, Q11, [SP], #0x20
174         LDP             Q8, Q9, [SP], #0x20
175         LDP             Q6, Q7, [SP], #0x20
176         LDP             Q4, Q5, [SP], #0x20
177         LDP             Q2, Q3, [SP], #0x20
178         LDP             Q0, Q1, [SP], #0x20
179 1:
180         LDP     X2, X3, [SP], #0x10  /* SPSR and ELR. */
181
182 #if defined( GUEST )
183         /* Restore the SPSR. */
184         MSR             SPSR_EL1, X3
185         /* Restore the ELR. */
186         MSR             ELR_EL1, X2
187 #else
188         /* Restore the SPSR. */
189         MSR             SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
190         /* Restore the ELR. */
191         MSR             ELR_EL3, X2
192 #endif
193
194         LDP     X30, XZR, [SP], #0x10
195         LDP     X28, X29, [SP], #0x10
196         LDP     X26, X27, [SP], #0x10
197         LDP     X24, X25, [SP], #0x10
198         LDP     X22, X23, [SP], #0x10
199         LDP     X20, X21, [SP], #0x10
200         LDP     X18, X19, [SP], #0x10
201         LDP     X16, X17, [SP], #0x10
202         LDP     X14, X15, [SP], #0x10
203         LDP     X12, X13, [SP], #0x10
204         LDP     X10, X11, [SP], #0x10
205         LDP     X8, X9, [SP], #0x10
206         LDP     X6, X7, [SP], #0x10
207         LDP     X4, X5, [SP], #0x10
208         LDP     X2, X3, [SP], #0x10
209         LDP     X0, X1, [SP], #0x10
210
211         /* Switch to use the ELx stack pointer.  _RB_ Might not be required. */
212         MSR     SPSEL, #1
213
214         ERET
215
216         .endm
217
218
219 /******************************************************************************
220  * FreeRTOS_SWI_Handler handler is used to perform a context switch.
221  *****************************************************************************/
222 .align 8
223 .type FreeRTOS_SWI_Handler, %function
224 FreeRTOS_SWI_Handler:
225         /* Save the context of the current task and select a new task to run. */
226         portSAVE_CONTEXT
227 #if defined( GUEST )
228         MRS             X0, ESR_EL1
229 #else
230         MRS             X0, ESR_EL3
231 #endif
232
233         LSR             X1, X0, #26
234
235 #if defined( GUEST )
236         CMP             X1, #0x15       /* 0x15 = SVC instruction. */
237 #else
238         CMP             X1, #0x17       /* 0x17 = SMC instruction. */
239 #endif
240         B.NE    FreeRTOS_Abort
241         BL              vTaskSwitchContext
242
243         portRESTORE_CONTEXT
244
245 FreeRTOS_Abort:
246         /* Full ESR is in X0, exception class code is in X1. */
247         B               .
248
249 /******************************************************************************
250  * vPortRestoreTaskContext is used to start the scheduler.
251  *****************************************************************************/
252 .align 8
253 .type vPortRestoreTaskContext, %function
254 vPortRestoreTaskContext:
255 .set freertos_vector_base,      _freertos_vector_table
256
257         /* Install the FreeRTOS interrupt handlers. */
258         LDR             X1, =freertos_vector_base
259 #if defined( GUEST )
260         MSR             VBAR_EL1, X1
261 #else
262         MSR             VBAR_EL3, X1
263 #endif
264         DSB             SY
265         ISB             SY
266
267         /* Start the first task. */
268         portRESTORE_CONTEXT
269
270
271 /******************************************************************************
272  * FreeRTOS_IRQ_Handler handles IRQ entry and exit.
273  *****************************************************************************/
274 .align 8
275 .type FreeRTOS_IRQ_Handler, %function
276 FreeRTOS_IRQ_Handler:
277         /* Save volatile registers. */
278         STP             X0, X1, [SP, #-0x10]!
279         STP             X2, X3, [SP, #-0x10]!
280         STP             X4, X5, [SP, #-0x10]!
281         STP             X6, X7, [SP, #-0x10]!
282         STP             X8, X9, [SP, #-0x10]!
283         STP             X10, X11, [SP, #-0x10]!
284         STP             X12, X13, [SP, #-0x10]!
285         STP             X14, X15, [SP, #-0x10]!
286         STP             X16, X17, [SP, #-0x10]!
287         STP             X18, X19, [SP, #-0x10]!
288         STP             X29, X30, [SP, #-0x10]!
289
290         /* Save the SPSR and ELR. */
291 #if defined( GUEST )
292         MRS             X3, SPSR_EL1
293         MRS             X2, ELR_EL1
294 #else
295         MRS             X3, SPSR_EL3
296         MRS             X2, ELR_EL3
297 #endif
298         STP     X2, X3, [SP, #-0x10]!
299
300         /* Increment the interrupt nesting counter. */
301         LDR             X5, ullPortInterruptNestingConst
302         LDR             X1, [X5]        /* Old nesting count in X1. */
303         ADD             X6, X1, #1
304         STR             X6, [X5]        /* Address of nesting count variable in X5. */
305
306         /* Maintain the interrupt nesting information across the function call. */
307         STP             X1, X5, [SP, #-0x10]!
308
309         /* Read value from the interrupt acknowledge register, which is stored in W0
310         for future parameter and interrupt clearing use. */
311         LDR     X2, ullICCIARConst
312         LDR             X3, [X2]
313         LDR             W0, [X3]        /* ICCIAR in W0 as parameter. */
314
315         /* Maintain the ICCIAR value across the function call. */
316         STP             X0, X1, [SP, #-0x10]!
317
318         /* Call the C handler. */
319         BL vApplicationIRQHandler
320
321         /* Disable interrupts. */
322         MSR     DAIFSET, #2
323         DSB             SY
324         ISB             SY
325
326         /* Restore the ICCIAR value. */
327         LDP             X0, X1, [SP], #0x10
328
329         /* End IRQ processing by writing ICCIAR to the EOI register. */
330         LDR     X4, ullICCEOIRConst
331         LDR             X4, [X4]
332         STR             W0, [X4]
333
334         /* Restore the critical nesting count. */
335         LDP             X1, X5, [SP], #0x10
336         STR             X1, [X5]
337
338         /* Has interrupt nesting unwound? */
339         CMP             X1, #0
340         B.NE    Exit_IRQ_No_Context_Switch
341
342         /* Is a context switch required? */
343         LDR             X0, ullPortYieldRequiredConst
344         LDR             X1, [X0]
345         CMP             X1, #0
346         B.EQ    Exit_IRQ_No_Context_Switch
347
348         /* Reset ullPortYieldRequired to 0. */
349         MOV             X2, #0
350         STR             X2, [X0]
351
352         /* Restore volatile registers. */
353         LDP     X4, X5, [SP], #0x10  /* SPSR and ELR. */
354 #if defined( GUEST )
355         MSR             SPSR_EL1, X5
356         MSR             ELR_EL1, X4
357 #else
358         MSR             SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
359         MSR             ELR_EL3, X4
360 #endif
361         DSB             SY
362         ISB             SY
363
364         LDP             X29, X30, [SP], #0x10
365         LDP             X18, X19, [SP], #0x10
366         LDP             X16, X17, [SP], #0x10
367         LDP             X14, X15, [SP], #0x10
368         LDP             X12, X13, [SP], #0x10
369         LDP             X10, X11, [SP], #0x10
370         LDP             X8, X9, [SP], #0x10
371         LDP             X6, X7, [SP], #0x10
372         LDP             X4, X5, [SP], #0x10
373         LDP             X2, X3, [SP], #0x10
374         LDP             X0, X1, [SP], #0x10
375
376         /* Save the context of the current task and select a new task to run. */
377         portSAVE_CONTEXT
378         BL vTaskSwitchContext
379         portRESTORE_CONTEXT
380
381 Exit_IRQ_No_Context_Switch:
382         /* Restore volatile registers. */
383         LDP     X4, X5, [SP], #0x10  /* SPSR and ELR. */
384 #if defined( GUEST )
385         MSR             SPSR_EL1, X5
386         MSR             ELR_EL1, X4
387 #else
388         MSR             SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
389         MSR             ELR_EL3, X4
390 #endif
391         DSB             SY
392         ISB             SY
393
394         LDP             X29, X30, [SP], #0x10
395         LDP             X18, X19, [SP], #0x10
396         LDP             X16, X17, [SP], #0x10
397         LDP             X14, X15, [SP], #0x10
398         LDP             X12, X13, [SP], #0x10
399         LDP             X10, X11, [SP], #0x10
400         LDP             X8, X9, [SP], #0x10
401         LDP             X6, X7, [SP], #0x10
402         LDP             X4, X5, [SP], #0x10
403         LDP             X2, X3, [SP], #0x10
404         LDP             X0, X1, [SP], #0x10
405
406         ERET
407
408
409
410
411 .align 8
412 pxCurrentTCBConst: .dword pxCurrentTCB
413 ullCriticalNestingConst: .dword ullCriticalNesting
414 ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
415
416 ullICCPMRConst: .dword ullICCPMR
417 ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
418 vApplicationIRQHandlerConst: .word vApplicationIRQHandler
419 ullPortInterruptNestingConst: .dword ullPortInterruptNesting
420 ullPortYieldRequiredConst: .dword ullPortYieldRequired
421 ullICCIARConst: .dword ullICCIAR
422 ullICCEOIRConst: .dword ullICCEOIR
423
424
425
426 .end
427
428
429
430
431