2 * FreeRTOS Kernel V10.2.1
\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 dmb /* Complete outstanding transfers before disabling MPU. */
\r
92 ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
\r
93 ldr r4, [r2] /* Read the value of MPU_CTRL. */
\r
94 bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
\r
95 str r4, [r2] /* Disable MPU. */
\r
97 adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
\r
98 ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
\r
99 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
\r
100 str r4, [r2] /* Program MAIR0. */
\r
101 ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
\r
102 movs r4, #4 /* r4 = 4. */
\r
103 str r4, [r2] /* Program RNR = 4. */
\r
104 adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
\r
105 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
\r
106 ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
\r
107 stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
\r
109 ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
\r
110 ldr r4, [r2] /* Read the value of MPU_CTRL. */
\r
111 orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
\r
112 str r4, [r2] /* Enable MPU. */
\r
113 dsb /* Force memory writes before continuing. */
\r
114 #endif /* configENABLE_MPU */
\r
116 #if ( configENABLE_MPU == 1 )
\r
117 ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
\r
118 ldr r5, =xSecureContext
\r
119 str r1, [r5] /* Set xSecureContext to this task's value for the same. */
\r
120 msr psplim, r2 /* Set this task's PSPLIM value. */
\r
121 msr control, r3 /* Set this task's CONTROL value. */
\r
122 adds r0, #32 /* Discard everything up to r0. */
\r
123 msr psp, r0 /* This is now the new top of stack to use in the task. */
\r
125 bx r4 /* Finally, branch to EXC_RETURN. */
\r
126 #else /* configENABLE_MPU */
\r
127 ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
\r
128 ldr r4, =xSecureContext
\r
129 str r1, [r4] /* Set xSecureContext to this task's value for the same. */
\r
130 msr psplim, r2 /* Set this task's PSPLIM value. */
\r
131 movs r1, #2 /* r1 = 2. */
\r
132 msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
\r
133 adds r0, #32 /* Discard everything up to r0. */
\r
134 msr psp, r0 /* This is now the new top of stack to use in the task. */
\r
136 bx r3 /* Finally, branch to EXC_RETURN. */
\r
137 #endif /* configENABLE_MPU */
\r
138 /*-----------------------------------------------------------*/
\r
141 mrs r0, control /* Read the CONTROL register. */
\r
142 bic r0, r0, #1 /* Clear the bit 0. */
\r
143 msr control, r0 /* Write back the new CONTROL value. */
\r
144 bx lr /* Return to the caller. */
\r
145 /*-----------------------------------------------------------*/
\r
148 ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
\r
149 ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
\r
150 ldr r0, [r0] /* The first entry in vector table is stack pointer. */
\r
151 msr msp, r0 /* Set the MSP back to the start of the stack. */
\r
152 cpsie i /* Globally enable interrupts. */
\r
156 svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
\r
157 /*-----------------------------------------------------------*/
\r
159 ulSetInterruptMaskFromISR:
\r
163 /*-----------------------------------------------------------*/
\r
165 vClearInterruptMaskFromISR:
\r
168 /*-----------------------------------------------------------*/
\r
171 mrs r1, psp /* Read PSP in r1. */
\r
172 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
173 ldr r0, [r2] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
\r
175 cbz r0, save_ns_context /* No secure context to save. */
\r
177 bl SecureContext_SaveContext
\r
178 pop {r0-r3} /* LR is now in r3. */
\r
179 mov lr, r3 /* LR = r3. */
\r
180 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
181 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
182 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
183 ldr r2, [r3] /* Read pxCurrentTCB. */
\r
184 #if ( configENABLE_MPU == 1 )
\r
185 subs r1, r1, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
186 str r1, [r2] /* Save the new top of stack in TCB. */
\r
187 mrs r2, psplim /* r2 = PSPLIM. */
\r
188 mrs r3, control /* r3 = CONTROL. */
\r
189 mov r4, lr /* r4 = LR/EXC_RETURN. */
\r
190 stmia r1!, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
191 #else /* configENABLE_MPU */
\r
192 subs r1, r1, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
\r
193 str r1, [r2] /* Save the new top of stack in TCB. */
\r
194 mrs r2, psplim /* r2 = PSPLIM. */
\r
195 mov r3, lr /* r3 = LR/EXC_RETURN. */
\r
196 stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
\r
197 #endif /* configENABLE_MPU */
\r
201 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
202 ldr r2, [r3] /* Read pxCurrentTCB. */
\r
203 #if ( configENABLE_FPU == 1 )
\r
204 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
\r
206 vstmdbeq r1!, {s16-s31} /* Store the FPU registers which are not saved automatically. */
\r
207 #endif /* configENABLE_FPU */
\r
208 #if ( configENABLE_MPU == 1 )
\r
209 subs r1, r1, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
\r
210 str r1, [r2] /* Save the new top of stack in TCB. */
\r
211 adds r1, r1, #16 /* r1 = r1 + 16. */
\r
212 stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
\r
213 mrs r2, psplim /* r2 = PSPLIM. */
\r
214 mrs r3, control /* r3 = CONTROL. */
\r
215 mov r4, lr /* r4 = LR/EXC_RETURN. */
\r
216 subs r1, r1, #16 /* r1 = r1 - 16. */
\r
217 stm r1, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
\r
218 #else /* configENABLE_MPU */
\r
219 subs r1, r1, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
\r
220 str r1, [r2] /* Save the new top of stack in TCB. */
\r
221 adds r1, r1, #12 /* r1 = r1 + 12. */
\r
222 stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
\r
223 mrs r2, psplim /* r2 = PSPLIM. */
\r
224 mov r3, lr /* r3 = LR/EXC_RETURN. */
\r
225 subs r1, r1, #12 /* r1 = r1 - 12. */
\r
226 stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
\r
227 #endif /* configENABLE_MPU */
\r
231 bl vTaskSwitchContext
\r
234 ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
\r
235 ldr r3, [r2] /* Read pxCurrentTCB. */
\r
236 ldr r1, [r3] /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
\r
238 #if ( configENABLE_MPU == 1 )
\r
239 dmb /* Complete outstanding transfers before disabling MPU. */
\r
240 ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
\r
241 ldr r4, [r2] /* Read the value of MPU_CTRL. */
\r
242 bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
\r
243 str r4, [r2] /* Disable MPU. */
\r
245 adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
\r
246 ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
\r
247 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
\r
248 str r4, [r2] /* Program MAIR0. */
\r
249 ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
\r
250 movs r4, #4 /* r4 = 4. */
\r
251 str r4, [r2] /* Program RNR = 4. */
\r
252 adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
\r
253 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
\r
254 ldmia r3!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
\r
255 stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
\r
257 ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
\r
258 ldr r4, [r2] /* Read the value of MPU_CTRL. */
\r
259 orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
\r
260 str r4, [r2] /* Enable MPU. */
\r
261 dsb /* Force memory writes before continuing. */
\r
262 #endif /* configENABLE_MPU */
\r
264 #if ( configENABLE_MPU == 1 )
\r
265 ldmia r1!, {r0, r2-r4} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
\r
266 msr psplim, r2 /* Restore the PSPLIM register value for the task. */
\r
267 msr control, r3 /* Restore the CONTROL register value for the task. */
\r
268 mov lr, r4 /* LR = r4. */
\r
269 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
270 str r0, [r2] /* Restore the task's xSecureContext. */
\r
271 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
\r
273 bl SecureContext_LoadContext /* Restore the secure context. */
\r
275 mov lr, r4 /* LR = r4. */
\r
276 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
277 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
278 msr psp, r1 /* Remember the new top of stack for the task. */
\r
280 #else /* configENABLE_MPU */
\r
281 ldmia r1!, {r0, r2-r3} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
\r
282 msr psplim, r2 /* Restore the PSPLIM register value for the task. */
\r
283 mov lr, r3 /* LR = r3. */
\r
284 ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
\r
285 str r0, [r2] /* Restore the task's xSecureContext. */
\r
286 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
\r
288 bl SecureContext_LoadContext /* Restore the secure context. */
\r
290 mov lr, r3 /* LR = r3. */
\r
291 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
292 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
293 msr psp, r1 /* Remember the new top of stack for the task. */
\r
295 #endif /* configENABLE_MPU */
\r
297 restore_ns_context:
\r
298 ldmia r1!, {r4-r11} /* Restore the registers that are not automatically restored. */
\r
299 #if ( configENABLE_FPU == 1 )
\r
300 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
\r
302 vldmiaeq r1!, {s16-s31} /* Restore the FPU registers which are not restored automatically. */
\r
303 #endif /* configENABLE_FPU */
\r
304 msr psp, r1 /* Remember the new top of stack for the task. */
\r
306 /*-----------------------------------------------------------*/
\r
313 b vPortSVCHandler_C
\r
314 /*-----------------------------------------------------------*/
\r
316 vPortFreeSecureContext:
\r
317 /* r0 = uint32_t *pulTCB. */
\r
318 ldr r1, [r0] /* The first item in the TCB is the top of the stack. */
\r
319 ldr r0, [r1] /* The first item on the stack is the task's xSecureContext. */
\r
320 cmp r0, #0 /* Raise svc if task's xSecureContext is not NULL. */
\r
322 svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
\r
323 bx lr /* Return. */
\r
324 /*-----------------------------------------------------------*/
\r