1/* 2 * FreeRTOS Kernel V10.6.2 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/* Including FreeRTOSConfig.h here will cause build errors if the header file 29contains code not understood by the assembler - for example the 'extern' keyword. 30To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so 31the code is included in C files but excluded by the preprocessor in assembly 32files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ 33#include "FreeRTOSConfig.h" 34 35/* System call numbers includes. */ 36#include "mpu_syscall_numbers.h" 37 38#ifndef configUSE_MPU_WRAPPERS_V1 39 #define configUSE_MPU_WRAPPERS_V1 0 40#endif 41 42 EXTERN pxCurrentTCB 43 EXTERN xSecureContext 44 EXTERN vTaskSwitchContext 45 EXTERN vPortSVCHandler_C 46 EXTERN SecureContext_SaveContext 47 EXTERN SecureContext_LoadContext 48#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 49 EXTERN vSystemCallEnter 50 EXTERN vSystemCallExit 51#endif 52 53 PUBLIC xIsPrivileged 54 PUBLIC vResetPrivilege 55 PUBLIC vPortAllocateSecureContext 56 PUBLIC vRestoreContextOfFirstTask 57 PUBLIC vRaisePrivilege 58 PUBLIC vStartFirstTask 59 PUBLIC ulSetInterruptMask 60 PUBLIC vClearInterruptMask 61 PUBLIC PendSV_Handler 62 PUBLIC SVC_Handler 63 PUBLIC vPortFreeSecureContext 64/*-----------------------------------------------------------*/ 65 66/*---------------- Unprivileged Functions -------------------*/ 67 68/*-----------------------------------------------------------*/ 69 70 SECTION .text:CODE:NOROOT(2) 71 THUMB 72/*-----------------------------------------------------------*/ 73 74xIsPrivileged: 75 mrs r0, control /* r0 = CONTROL. */ 76 tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ 77 ite ne 78 movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ 79 moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */ 80 bx lr /* Return. */ 81/*-----------------------------------------------------------*/ 82 83vResetPrivilege: 84 mrs r0, control /* r0 = CONTROL. */ 85 orr r0, r0, #1 /* r0 = r0 | 1. */ 86 msr control, r0 /* CONTROL = r0. */ 87 bx lr /* Return to the caller. */ 88/*-----------------------------------------------------------*/ 89 90vPortAllocateSecureContext: 91 svc 100 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 100. */ 92 bx lr /* Return. */ 93/*-----------------------------------------------------------*/ 94 95/*----------------- Privileged Functions --------------------*/ 96 97/*-----------------------------------------------------------*/ 98 99 SECTION privileged_functions:CODE:NOROOT(2) 100 THUMB 101/*-----------------------------------------------------------*/ 102 103#if ( configENABLE_MPU == 1 ) 104 105vRestoreContextOfFirstTask: 106 program_mpu_first_task: 107 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 108 ldr r0, [r3] /* r0 = pxCurrentTCB. */ 109 110 dmb /* Complete outstanding transfers before disabling MPU. */ 111 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 112 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 113 bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */ 114 str r2, [r1] /* Disable MPU. */ 115 116 adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */ 117 ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */ 118 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ 119 str r1, [r2] /* Program MAIR0. */ 120 121 adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */ 122 ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */ 123 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ 124 125 movs r3, #4 /* r3 = 4. */ 126 str r3, [r1] /* Program RNR = 4. */ 127 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 128 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 129 130 #if ( configTOTAL_MPU_REGIONS == 16 ) 131 movs r3, #8 /* r3 = 8. */ 132 str r3, [r1] /* Program RNR = 8. */ 133 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 134 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 135 movs r3, #12 /* r3 = 12. */ 136 str r3, [r1] /* Program RNR = 12. */ 137 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 138 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 139 #endif /* configTOTAL_MPU_REGIONS == 16 */ 140 141 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 142 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 143 orr r2, #1 /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */ 144 str r2, [r1] /* Enable MPU. */ 145 dsb /* Force memory writes before continuing. */ 146 147 restore_context_first_task: 148 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 149 ldr r1, [r3] /* r1 = pxCurrentTCB.*/ 150 ldr r2, [r1] /* r2 = Location of saved context in TCB. */ 151 152 restore_special_regs_first_task: 153 ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ 154 msr psp, r3 155 msr psplim, r4 156 msr control, r5 157 ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 158 str r0, [r4] /* Restore xSecureContext. */ 159 160 restore_general_regs_first_task: 161 ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */ 162 stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */ 163 ldmdb r2!, {r4-r11} /* r4-r11 restored. */ 164 165 restore_context_done_first_task: 166 str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */ 167 mov r0, #0 168 msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ 169 bx lr 170 171#else /* configENABLE_MPU */ 172 173vRestoreContextOfFirstTask: 174 ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 175 ldr r3, [r2] /* Read pxCurrentTCB. */ 176 ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ 177 178 ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ 179 ldr r4, =xSecureContext 180 str r1, [r4] /* Set xSecureContext to this task's value for the same. */ 181 msr psplim, r2 /* Set this task's PSPLIM value. */ 182 movs r1, #2 /* r1 = 2. */ 183 msr CONTROL, r1 /* Switch to use PSP in the thread mode. */ 184 adds r0, #32 /* Discard everything up to r0. */ 185 msr psp, r0 /* This is now the new top of stack to use in the task. */ 186 isb 187 mov r0, #0 188 msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ 189 bx r3 /* Finally, branch to EXC_RETURN. */ 190 191#endif /* configENABLE_MPU */ 192/*-----------------------------------------------------------*/ 193 194vRaisePrivilege: 195 mrs r0, control /* Read the CONTROL register. */ 196 bic r0, r0, #1 /* Clear the bit 0. */ 197 msr control, r0 /* Write back the new CONTROL value. */ 198 bx lr /* Return to the caller. */ 199/*-----------------------------------------------------------*/ 200 201vStartFirstTask: 202 ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ 203 ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ 204 ldr r0, [r0] /* The first entry in vector table is stack pointer. */ 205 msr msp, r0 /* Set the MSP back to the start of the stack. */ 206 cpsie i /* Globally enable interrupts. */ 207 cpsie f 208 dsb 209 isb 210 svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */ 211/*-----------------------------------------------------------*/ 212 213ulSetInterruptMask: 214 mrs r0, basepri /* r0 = basepri. Return original basepri value. */ 215 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY 216 msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 217 dsb 218 isb 219 bx lr /* Return. */ 220/*-----------------------------------------------------------*/ 221 222vClearInterruptMask: 223 msr basepri, r0 /* basepri = ulMask. */ 224 dsb 225 isb 226 bx lr /* Return. */ 227/*-----------------------------------------------------------*/ 228 229#if ( configENABLE_MPU == 1 ) 230 231PendSV_Handler: 232 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 233 ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ 234 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 235 ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ 236 ldr r2, [r1] /* r2 = Location in TCB where the context should be saved. */ 237 238 cbz r0, save_ns_context /* No secure context to save. */ 239 save_s_context: 240 push {r0-r2, lr} 241 bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 242 pop {r0-r2, lr} 243 244 save_ns_context: 245 mov r3, lr /* r3 = LR (EXC_RETURN). */ 246 lsls r3, r3, #25 /* r3 = 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. */ 247 bmi save_special_regs /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */ 248 249 save_general_regs: 250 mrs r3, psp 251 252 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 253 add r3, r3, #0x20 /* Move r3 to location where s0 is saved. */ 254 tst lr, #0x10 255 ittt eq 256 vstmiaeq r2!, {s16-s31} /* Store s16-s31. */ 257 vldmiaeq r3, {s0-s16} /* Copy hardware saved FP context into s0-s16. */ 258 vstmiaeq r2!, {s0-s16} /* Store hardware saved FP context. */ 259 sub r3, r3, #0x20 /* Set r3 back to the location of hardware saved context. */ 260 #endif /* configENABLE_FPU || configENABLE_MVE */ 261 262 stmia r2!, {r4-r11} /* Store r4-r11. */ 263 ldmia r3, {r4-r11} /* Copy the hardware saved context into r4-r11. */ 264 stmia r2!, {r4-r11} /* Store the hardware saved context. */ 265 266 save_special_regs: 267 mrs r3, psp /* r3 = PSP. */ 268 mrs r4, psplim /* r4 = PSPLIM. */ 269 mrs r5, control /* r5 = CONTROL. */ 270 stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ 271 str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ 272 273 select_next_task: 274 mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY 275 msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 276 dsb 277 isb 278 bl vTaskSwitchContext 279 mov r0, #0 /* r0 = 0. */ 280 msr basepri, r0 /* Enable interrupts. */ 281 282 program_mpu: 283 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 284 ldr r0, [r3] /* r0 = pxCurrentTCB.*/ 285 286 dmb /* Complete outstanding transfers before disabling MPU. */ 287 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 288 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 289 bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */ 290 str r2, [r1] /* Disable MPU. */ 291 292 adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */ 293 ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */ 294 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ 295 str r1, [r2] /* Program MAIR0. */ 296 297 adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */ 298 ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */ 299 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ 300 301 movs r3, #4 /* r3 = 4. */ 302 str r3, [r1] /* Program RNR = 4. */ 303 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 304 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 305 306 #if ( configTOTAL_MPU_REGIONS == 16 ) 307 movs r3, #8 /* r3 = 8. */ 308 str r3, [r1] /* Program RNR = 8. */ 309 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 310 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 311 movs r3, #12 /* r3 = 12. */ 312 str r3, [r1] /* Program RNR = 12. */ 313 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 314 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 315 #endif /* configTOTAL_MPU_REGIONS == 16 */ 316 317 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 318 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 319 orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */ 320 str r2, [r1] /* Enable MPU. */ 321 dsb /* Force memory writes before continuing. */ 322 323 restore_context: 324 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 325 ldr r1, [r3] /* r1 = pxCurrentTCB.*/ 326 ldr r2, [r1] /* r2 = Location of saved context in TCB. */ 327 328 restore_special_regs: 329 ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ 330 msr psp, r3 331 msr psplim, r4 332 msr control, r5 333 ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 334 str r0, [r4] /* Restore xSecureContext. */ 335 cbz r0, restore_ns_context /* No secure context to restore. */ 336 337 restore_s_context: 338 push {r1-r3, lr} 339 bl SecureContext_LoadContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 340 pop {r1-r3, lr} 341 342 restore_ns_context: 343 mov r0, lr /* r0 = LR (EXC_RETURN). */ 344 lsls r0, r0, #25 /* r0 = r0 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */ 345 bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */ 346 347 restore_general_regs: 348 ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */ 349 stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */ 350 ldmdb r2!, {r4-r11} /* r4-r11 restored. */ 351 352 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 353 tst lr, #0x10 354 ittt eq 355 vldmdbeq r2!, {s0-s16} /* s0-s16 contain hardware saved FP context. */ 356 vstmiaeq r3!, {s0-s16} /* Copy hardware saved FP context on the task stack. */ 357 vldmdbeq r2!, {s16-s31} /* Restore s16-s31. */ 358 #endif /* configENABLE_FPU || configENABLE_MVE */ 359 360 restore_context_done: 361 str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */ 362 bx lr 363 364#else /* configENABLE_MPU */ 365 366PendSV_Handler: 367 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 368 ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ 369 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 370 ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ 371 mrs r2, psp /* Read PSP in r2. */ 372 373 cbz r0, save_ns_context /* No secure context to save. */ 374 push {r0-r2, r14} 375 bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 376 pop {r0-r3} /* LR is now in r3. */ 377 mov lr, r3 /* LR = r3. */ 378 lsls r1, r3, #25 /* r1 = 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. */ 379 bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ 380 381 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 382 ldr r1, [r3] /* Read pxCurrentTCB. */ 383 subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */ 384 str r2, [r1] /* Save the new top of stack in TCB. */ 385 mrs r1, psplim /* r1 = PSPLIM. */ 386 mov r3, lr /* r3 = LR/EXC_RETURN. */ 387 stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */ 388 b select_next_task 389 390 save_ns_context: 391 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 392 ldr r1, [r3] /* Read pxCurrentTCB. */ 393 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 394 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ 395 it eq 396 vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ 397 #endif /* configENABLE_FPU || configENABLE_MVE */ 398 subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ 399 str r2, [r1] /* Save the new top of stack in TCB. */ 400 adds r2, r2, #12 /* r2 = r2 + 12. */ 401 stm r2, {r4-r11} /* Store the registers that are not saved automatically. */ 402 mrs r1, psplim /* r1 = PSPLIM. */ 403 mov r3, lr /* r3 = LR/EXC_RETURN. */ 404 subs r2, r2, #12 /* r2 = r2 - 12. */ 405 stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */ 406 407 select_next_task: 408 mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY 409 msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 410 dsb 411 isb 412 bl vTaskSwitchContext 413 mov r0, #0 /* r0 = 0. */ 414 msr basepri, r0 /* Enable interrupts. */ 415 416 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 417 ldr r1, [r3] /* Read pxCurrentTCB. */ 418 ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ 419 420 ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ 421 msr psplim, r1 /* Restore the PSPLIM register value for the task. */ 422 mov lr, r4 /* LR = r4. */ 423 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 424 str r0, [r3] /* Restore the task's xSecureContext. */ 425 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ 426 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 427 ldr r1, [r3] /* Read pxCurrentTCB. */ 428 push {r2, r4} 429 bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 430 pop {r2, r4} 431 mov lr, r4 /* LR = r4. */ 432 lsls r1, r4, #25 /* r1 = 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. */ 433 bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */ 434 msr psp, r2 /* Remember the new top of stack for the task. */ 435 bx lr 436 437 restore_ns_context: 438 ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ 439 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 440 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ 441 it eq 442 vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ 443 #endif /* configENABLE_FPU || configENABLE_MVE */ 444 msr psp, r2 /* Remember the new top of stack for the task. */ 445 bx lr 446 447#endif /* configENABLE_MPU */ 448/*-----------------------------------------------------------*/ 449 450#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 451 452SVC_Handler: 453 tst lr, #4 454 ite eq 455 mrseq r0, msp 456 mrsne r0, psp 457 458 ldr r1, [r0, #24] 459 ldrb r2, [r1, #-2] 460 cmp r2, #NUM_SYSTEM_CALLS 461 blt syscall_enter 462 cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */ 463 beq syscall_exit 464 b vPortSVCHandler_C 465 466 syscall_enter: 467 mov r1, lr 468 b vSystemCallEnter 469 470 syscall_exit: 471 mov r1, lr 472 b vSystemCallExit 473 474#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 475 476SVC_Handler: 477 tst lr, #4 478 ite eq 479 mrseq r0, msp 480 mrsne r0, psp 481 b vPortSVCHandler_C 482 483#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 484/*-----------------------------------------------------------*/ 485 486vPortFreeSecureContext: 487 /* r0 = uint32_t *pulTCB. */ 488 ldr r2, [r0] /* The first item in the TCB is the top of the stack. */ 489 ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */ 490 cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */ 491 it ne 492 svcne 101 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */ 493 bx lr /* Return. */ 494/*-----------------------------------------------------------*/ 495 496 END 497