2 * FreeRTOS Kernel V10.2.0
\r
3 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
29 EXTERN xSecureContext
\r
30 EXTERN vTaskSwitchContext
\r
31 EXTERN vPortSVCHandler_C
\r
32 EXTERN SecureContext_SaveContext
\r
33 EXTERN SecureContext_LoadContext
\r
35 PUBLIC xIsPrivileged
\r
36 PUBLIC vResetPrivilege
\r
37 PUBLIC vPortAllocateSecureContext
\r
38 PUBLIC vRestoreContextOfFirstTask
\r
39 PUBLIC vRaisePrivilege
\r
40 PUBLIC vStartFirstTask
\r
41 PUBLIC ulSetInterruptMaskFromISR
\r
42 PUBLIC vClearInterruptMaskFromISR
\r
43 PUBLIC PendSV_Handler
\r
45 PUBLIC vPortFreeSecureContext
\r
46 /*-----------------------------------------------------------*/
\r
48 /*---------------- Unprivileged Functions -------------------*/
\r
50 /*-----------------------------------------------------------*/
\r
52 SECTION .text:CODE:NOROOT(2)
\r
54 /*-----------------------------------------------------------*/
\r
57 mrs r0, control /* r0 = CONTROL. */
\r
58 tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
\r
60 movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
\r
61 moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
\r
63 /*-----------------------------------------------------------*/
\r
66 mrs r0, control /* r0 = CONTROL. */
\r
67 orr r0, r0, #1 /* r0 = r0 | 1. */
\r
68 msr control, r0 /* CONTROL = r0. */
\r
69 bx lr /* Return to the caller. */
\r
70 /*-----------------------------------------------------------*/
\r
72 vPortAllocateSecureContext:
\r
73 svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
\r
75 /*-----------------------------------------------------------*/
\r
77 /*----------------- Privileged Functions --------------------*/
\r
79 /*-----------------------------------------------------------*/
\r
81 SECTION privileged_functions:CODE:NOROOT(2)
\r
83 /*-----------------------------------------------------------*/
\r
85 vRestoreContextOfFirstTask:
\r
86 ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
87 ldr r3, [r2] /* Read pxCurrentTCB. */
\r
88 ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
\r
90 #if ( configENABLE_MPU == 1 )
\r
91 adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
\r
92 ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
\r
93 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
\r
94 str r4, [r2] /* Program MAIR0. */
\r
95 ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
\r
96 movs r4, #4 /* r4 = 4. */
\r
97 str r4, [r2] /* Program RNR = 4. */
\r
98 adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
\r
99 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
\r
100 ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
\r
101 stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
\r
102 #endif /* configENABLE_MPU */
\r
104 #if ( configENABLE_MPU == 1 )
\r
105 ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
\r
106 ldr r5, =xSecureContext
\r
107 str r1, [r5] /* Set xSecureContext to this task's value for the same. */
\r
108 msr psplim, r2 /* Set this task's PSPLIM value. */
\r
109 msr control, r3 /* Set this task's CONTROL value. */
\r
110 adds r0, #32 /* Discard everything up to r0. */
\r
111 msr psp, r0 /* This is now the new top of stack to use in the task. */
\r
113 bx r4 /* Finally, branch to EXC_RETURN. */
\r
114 #else /* configENABLE_MPU */
\r
115 ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
\r
116 ldr r4, =xSecureContext
\r
117 str r1, [r4] /* Set xSecureContext to this task's value for the same. */
\r
118 msr psplim, r2 /* Set this task's PSPLIM value. */
\r
119 movs r1, #2 /* r1 = 2. */
\r
120 msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
\r
121 adds r0, #32 /* Discard everything up to r0. */
\r
122 msr psp, r0 /* This is now the new top of stack to use in the task. */
\r
124 bx r3 /* Finally, branch to EXC_RETURN. */
\r
125 #endif /* configENABLE_MPU */
\r
126 /*-----------------------------------------------------------*/
\r
129 mrs r0, control /* Read the CONTROL register. */
\r
130 bic r0, r0, #1 /* Clear the bit 0. */
\r
131 msr control, r0 /* Write back the new CONTROL value. */
\r
132 bx lr /* Return to the caller. */
\r
133 /*-----------------------------------------------------------*/
\r
136 ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
\r
137 ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
\r
138 ldr r0, [r0] /* The first entry in vector table is stack pointer. */
\r
139 msr msp, r0 /* Set the MSP back to the start of the stack. */
\r
140 cpsie i /* Globally enable interrupts. */
\r
144 svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
\r
145 /*-----------------------------------------------------------*/
\r
147 ulSetInterruptMaskFromISR:
\r
151 /*-----------------------------------------------------------*/
\r
153 vClearInterruptMaskFromISR:
\r
156 /*-----------------------------------------------------------*/
\r
159 mrs r1, psp /* Read PSP in r1. */
\r
160 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
161 ldr r0, [r2] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
\r
163 cbz r0, save_ns_context /* No secure context to save. */
\r
165 bl SecureContext_SaveContext
\r
166 pop {r0-r3} /* LR is now in r3. */
\r
167 mov lr, r3 /* LR = r3. */
\r
168 lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
\r
169 bpl save_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
\r
170 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
171 ldr r2, [r3] /* Read pxCurrentTCB. */
\r
172 #if ( configENABLE_MPU == 1 )
\r
173 subs r1, r1, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
174 str r1, [r2] /* Save the new top of stack in TCB. */
\r
175 mrs r2, psplim /* r2 = PSPLIM. */
\r
176 mrs r3, control /* r3 = CONTROL. */
\r
177 mov r4, lr /* r4 = LR/EXC_RETURN. */
\r
178 stmia r1!, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
179 #else /* configENABLE_MPU */
\r
180 subs r1, r1, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
\r
181 str r1, [r2] /* Save the new top of stack in TCB. */
\r
182 mrs r2, psplim /* r2 = PSPLIM. */
\r
183 mov r3, lr /* r3 = LR/EXC_RETURN. */
\r
184 stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
\r
185 #endif /* configENABLE_MPU */
\r
189 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
190 ldr r2, [r3] /* Read pxCurrentTCB. */
\r
191 #if ( configENABLE_FPU == 1 )
\r
192 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
\r
194 vstmdbeq r1!, {s16-s31} /* Store the FPU registers which are not saved automatically. */
\r
195 #endif /* configENABLE_FPU */
\r
196 #if ( configENABLE_MPU == 1 )
\r
197 subs r1, r1, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
\r
198 str r1, [r2] /* Save the new top of stack in TCB. */
\r
199 adds r1, r1, #16 /* r1 = r1 + 16. */
\r
200 stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
\r
201 mrs r2, psplim /* r2 = PSPLIM. */
\r
202 mrs r3, control /* r3 = CONTROL. */
\r
203 mov r4, lr /* r4 = LR/EXC_RETURN. */
\r
204 subs r1, r1, #16 /* r1 = r1 - 16. */
\r
205 stm r1, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
206 #else /* configENABLE_MPU */
\r
207 subs r1, r1, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
\r
208 str r1, [r2] /* Save the new top of stack in TCB. */
\r
209 adds r1, r1, #12 /* r1 = r1 + 12. */
\r
210 stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
\r
211 mrs r2, psplim /* r2 = PSPLIM. */
\r
212 mov r3, lr /* r3 = LR/EXC_RETURN. */
\r
213 subs r1, r1, #12 /* r1 = r1 - 12. */
\r
214 stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
\r
215 #endif /* configENABLE_MPU */
\r
219 bl vTaskSwitchContext
\r
222 ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
223 ldr r3, [r2] /* Read pxCurrentTCB. */
\r
224 ldr r1, [r3] /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
\r
226 #if ( configENABLE_MPU == 1 )
\r
227 adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
\r
228 ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
\r
229 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
\r
230 str r4, [r2] /* Program MAIR0. */
\r
231 ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
\r
232 movs r4, #4 /* r4 = 4. */
\r
233 str r4, [r2] /* Program RNR = 4. */
\r
234 adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
\r
235 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
\r
236 ldmia r3!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
\r
237 stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
\r
238 #endif /* configENABLE_MPU */
\r
240 #if ( configENABLE_MPU == 1 )
\r
241 ldmia r1!, {r0, r2-r4} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
\r
242 msr psplim, r2 /* Restore the PSPLIM register value for the task. */
\r
243 msr control, r3 /* Restore the CONTROL register value for the task. */
\r
244 mov lr, r4 /* LR = r4. */
\r
245 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
246 str r0, [r2] /* Restore the task's xSecureContext. */
\r
247 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
\r
249 bl SecureContext_LoadContext /* Restore the secure context. */
\r
251 mov lr, r4 /* LR = r4. */
\r
252 lsls r2, r4, #25 /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
\r
253 bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
\r
254 msr psp, r1 /* Remember the new top of stack for the task. */
\r
256 #else /* configENABLE_MPU */
\r
257 ldmia r1!, {r0, r2-r3} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
\r
258 msr psplim, r2 /* Restore the PSPLIM register value for the task. */
\r
259 mov lr, r3 /* LR = r3. */
\r
260 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
261 str r0, [r2] /* Restore the task's xSecureContext. */
\r
262 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
\r
264 bl SecureContext_LoadContext /* Restore the secure context. */
\r
266 mov lr, r3 /* LR = r3. */
\r
267 lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
\r
268 bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
\r
269 msr psp, r1 /* Remember the new top of stack for the task. */
\r
271 #endif /* configENABLE_MPU */
\r
273 restore_ns_context:
\r
274 ldmia r1!, {r4-r11} /* Restore the registers that are not automatically restored. */
\r
275 #if ( configENABLE_FPU == 1 )
\r
276 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
\r
278 vldmiaeq r1!, {s16-s31} /* Restore the FPU registers which are not restored automatically. */
\r
279 #endif /* configENABLE_FPU */
\r
280 msr psp, r1 /* Remember the new top of stack for the task. */
\r
282 /*-----------------------------------------------------------*/
\r
289 b vPortSVCHandler_C
\r
290 /*-----------------------------------------------------------*/
\r
292 vPortFreeSecureContext:
\r
293 /* r0 = uint32_t *pulTCB. */
\r
294 ldr r1, [r0] /* The first item in the TCB is the top of the stack. */
\r
295 ldr r0, [r1] /* The first item on the stack is the task's xSecureContext. */
\r
296 cmp r0, #0 /* Raise svc if task's xSecureContext is not NULL. */
\r
298 svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
\r
299 bx lr /* Return. */
\r
300 /*-----------------------------------------------------------*/
\r