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