1/* 2 * FreeRTOS Kernel <DEVELOPMENT BRANCH> 3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * Copyright 2024 Arm Limited and/or its affiliates 5 * <open-source-office@arm.com> 6 * 7 * SPDX-License-Identifier: MIT 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy of 10 * this software and associated documentation files (the "Software"), to deal in 11 * the Software without restriction, including without limitation the rights to 12 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 * the Software, and to permit persons to whom the Software is furnished to do so, 14 * subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in all 17 * copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 21 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 22 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * https://www.FreeRTOS.org 27 * https://github.com/FreeRTOS 28 * 29 */ 30/* Including FreeRTOSConfig.h here will cause build errors if the header file 31contains code not understood by the assembler - for example the 'extern' keyword. 32To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so 33the code is included in C files but excluded by the preprocessor in assembly 34files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */ 35#include "FreeRTOSConfig.h" 36 37/* System call numbers includes. */ 38#include "mpu_syscall_numbers.h" 39 40#ifndef configUSE_MPU_WRAPPERS_V1 41 #define configUSE_MPU_WRAPPERS_V1 0 42#endif 43 44 EXTERN pxCurrentTCB 45 EXTERN xSecureContext 46 EXTERN vTaskSwitchContext 47 EXTERN vPortSVCHandler_C 48 EXTERN SecureContext_SaveContext 49 EXTERN SecureContext_LoadContext 50#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 51 EXTERN vSystemCallEnter 52 EXTERN vSystemCallExit 53#endif 54 55 PUBLIC xIsPrivileged 56 PUBLIC vResetPrivilege 57 PUBLIC vPortAllocateSecureContext 58 PUBLIC vRestoreContextOfFirstTask 59 PUBLIC vRaisePrivilege 60 PUBLIC vStartFirstTask 61 PUBLIC ulSetInterruptMask 62 PUBLIC vClearInterruptMask 63 PUBLIC PendSV_Handler 64 PUBLIC SVC_Handler 65 PUBLIC vPortFreeSecureContext 66/*-----------------------------------------------------------*/ 67 68/*---------------- Unprivileged Functions -------------------*/ 69 70/*-----------------------------------------------------------*/ 71 72 SECTION .text:CODE:NOROOT(2) 73 THUMB 74/*-----------------------------------------------------------*/ 75 76xIsPrivileged: 77 mrs r0, control /* r0 = CONTROL. */ 78 tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ 79 ite ne 80 movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ 81 moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */ 82 bx lr /* Return. */ 83/*-----------------------------------------------------------*/ 84 85vResetPrivilege: 86 mrs r0, control /* r0 = CONTROL. */ 87 orr r0, r0, #1 /* r0 = r0 | 1. */ 88 msr control, r0 /* CONTROL = r0. */ 89 bx lr /* Return to the caller. */ 90/*-----------------------------------------------------------*/ 91 92vPortAllocateSecureContext: 93 svc 100 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 100. */ 94 bx lr /* Return. */ 95/*-----------------------------------------------------------*/ 96 97/*----------------- Privileged Functions --------------------*/ 98 99/*-----------------------------------------------------------*/ 100 101 SECTION privileged_functions:CODE:NOROOT(2) 102 THUMB 103/*-----------------------------------------------------------*/ 104 105#if ( configENABLE_MPU == 1 ) 106 107vRestoreContextOfFirstTask: 108 program_mpu_first_task: 109 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 110 ldr r0, [r3] /* r0 = pxCurrentTCB. */ 111 112 dmb /* Complete outstanding transfers before disabling MPU. */ 113 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 114 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 115 bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */ 116 str r2, [r1] /* Disable MPU. */ 117 118 adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */ 119 ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */ 120 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ 121 str r1, [r2] /* Program MAIR0. */ 122 123 adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */ 124 ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */ 125 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ 126 127 movs r3, #4 /* r3 = 4. */ 128 str r3, [r1] /* Program RNR = 4. */ 129 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 130 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 131 132 #if ( configTOTAL_MPU_REGIONS == 16 ) 133 movs r3, #8 /* r3 = 8. */ 134 str r3, [r1] /* Program RNR = 8. */ 135 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 136 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 137 movs r3, #12 /* r3 = 12. */ 138 str r3, [r1] /* Program RNR = 12. */ 139 ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */ 140 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 141 #endif /* configTOTAL_MPU_REGIONS == 16 */ 142 143 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 144 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 145 orr r2, #1 /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */ 146 str r2, [r1] /* Enable MPU. */ 147 dsb /* Force memory writes before continuing. */ 148 149 restore_context_first_task: 150 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 151 ldr r1, [r3] /* r1 = pxCurrentTCB.*/ 152 ldr r2, [r1] /* r2 = Location of saved context in TCB. */ 153 154 restore_special_regs_first_task: 155 #if ( configENABLE_PAC == 1 ) 156 ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */ 157 msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */ 158 msr PAC_KEY_P_1, r4 159 msr PAC_KEY_P_2, r5 160 msr PAC_KEY_P_3, r6 161 clrm {r3-r6} /* Clear r3-r6. */ 162 #endif /* configENABLE_PAC */ 163 ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ 164 msr psp, r3 165 msr psplim, r4 166 msr control, r5 167 ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 168 str r0, [r4] /* Restore xSecureContext. */ 169 170 restore_general_regs_first_task: 171 ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */ 172 stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */ 173 ldmdb r2!, {r4-r11} /* r4-r11 restored. */ 174 175 restore_context_done_first_task: 176 str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */ 177 mov r0, #0 178 msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ 179 bx lr 180 181#else /* configENABLE_MPU */ 182 183vRestoreContextOfFirstTask: 184 ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 185 ldr r3, [r2] /* Read pxCurrentTCB. */ 186 ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ 187 188#if ( configENABLE_PAC == 1 ) 189 ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */ 190 msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */ 191 msr PAC_KEY_P_2, r2 192 msr PAC_KEY_P_1, r3 193 msr PAC_KEY_P_0, r4 194 clrm {r1-r4} /* Clear r1-r4. */ 195#endif /* configENABLE_PAC */ 196 197 ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ 198 ldr r4, =xSecureContext 199 str r1, [r4] /* Set xSecureContext to this task's value for the same. */ 200 msr psplim, r2 /* Set this task's PSPLIM value. */ 201 mrs r1, control /* Obtain current control register value. */ 202 orrs r1, r1, #2 /* r1 = r1 | 0x2 - Set the second bit to use the program stack pointe (PSP). */ 203 msr control, r1 /* Write back the new control register value. */ 204 adds r0, #32 /* Discard everything up to r0. */ 205 msr psp, r0 /* This is now the new top of stack to use in the task. */ 206 isb 207 mov r0, #0 208 msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */ 209 bx r3 /* Finally, branch to EXC_RETURN. */ 210 211#endif /* configENABLE_MPU */ 212/*-----------------------------------------------------------*/ 213 214vRaisePrivilege: 215 mrs r0, control /* Read the CONTROL register. */ 216 bic r0, r0, #1 /* Clear the bit 0. */ 217 msr control, r0 /* Write back the new CONTROL value. */ 218 bx lr /* Return to the caller. */ 219/*-----------------------------------------------------------*/ 220 221vStartFirstTask: 222 ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */ 223 ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */ 224 ldr r0, [r0] /* The first entry in vector table is stack pointer. */ 225 msr msp, r0 /* Set the MSP back to the start of the stack. */ 226 cpsie i /* Globally enable interrupts. */ 227 cpsie f 228 dsb 229 isb 230 svc 102 /* System call to start the first task. portSVC_START_SCHEDULER = 102. */ 231/*-----------------------------------------------------------*/ 232 233ulSetInterruptMask: 234 mrs r0, basepri /* r0 = basepri. Return original basepri value. */ 235 mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY 236 msr basepri, r1 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 237 dsb 238 isb 239 bx lr /* Return. */ 240/*-----------------------------------------------------------*/ 241 242vClearInterruptMask: 243 msr basepri, r0 /* basepri = ulMask. */ 244 dsb 245 isb 246 bx lr /* Return. */ 247/*-----------------------------------------------------------*/ 248 249#if ( configENABLE_MPU == 1 ) 250 251PendSV_Handler: 252 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 253 ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ 254 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 255 ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ 256 ldr r2, [r1] /* r2 = Location in TCB where the context should be saved. */ 257 258 cbz r0, save_ns_context /* No secure context to save. */ 259 save_s_context: 260 push {r0-r2, lr} 261 bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 262 pop {r0-r2, lr} 263 264 save_ns_context: 265 mov r3, lr /* r3 = LR (EXC_RETURN). */ 266 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. */ 267 bmi save_special_regs /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */ 268 269 save_general_regs: 270 mrs r3, psp 271 272 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 273 add r3, r3, #0x20 /* Move r3 to location where s0 is saved. */ 274 tst lr, #0x10 275 ittt eq 276 vstmiaeq r2!, {s16-s31} /* Store s16-s31. */ 277 vldmiaeq r3, {s0-s16} /* Copy hardware saved FP context into s0-s16. */ 278 vstmiaeq r2!, {s0-s16} /* Store hardware saved FP context. */ 279 sub r3, r3, #0x20 /* Set r3 back to the location of hardware saved context. */ 280 #endif /* configENABLE_FPU || configENABLE_MVE */ 281 282 stmia r2!, {r4-r11} /* Store r4-r11. */ 283 ldmia r3, {r4-r11} /* Copy the hardware saved context into r4-r11. */ 284 stmia r2!, {r4-r11} /* Store the hardware saved context. */ 285 286 save_special_regs: 287 mrs r3, psp /* r3 = PSP. */ 288 mrs r4, psplim /* r4 = PSPLIM. */ 289 mrs r5, control /* r5 = CONTROL. */ 290 stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ 291 #if ( configENABLE_PAC == 1 ) 292 mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */ 293 mrs r4, PAC_KEY_P_1 294 mrs r5, PAC_KEY_P_2 295 mrs r6, PAC_KEY_P_3 296 stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */ 297 clrm {r3-r6} /* Clear r3-r6. */ 298 #endif /* configENABLE_PAC */ 299 300 str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ 301 302 select_next_task: 303 mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY 304 msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 305 dsb 306 isb 307 bl vTaskSwitchContext 308 mov r0, #0 /* r0 = 0. */ 309 msr basepri, r0 /* Enable interrupts. */ 310 311 program_mpu: 312 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 313 ldr r0, [r3] /* r0 = pxCurrentTCB.*/ 314 315 dmb /* Complete outstanding transfers before disabling MPU. */ 316 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 317 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 318 bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */ 319 str r2, [r1] /* Disable MPU. */ 320 321 adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */ 322 ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */ 323 ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */ 324 str r1, [r2] /* Program MAIR0. */ 325 326 adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */ 327 ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */ 328 ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */ 329 330 movs r3, #4 /* r3 = 4. */ 331 str r3, [r1] /* Program RNR = 4. */ 332 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 333 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 334 335 #if ( configTOTAL_MPU_REGIONS == 16 ) 336 movs r3, #8 /* r3 = 8. */ 337 str r3, [r1] /* Program RNR = 8. */ 338 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 339 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 340 movs r3, #12 /* r3 = 12. */ 341 str r3, [r1] /* Program RNR = 12. */ 342 ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */ 343 stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */ 344 #endif /* configTOTAL_MPU_REGIONS == 16 */ 345 346 ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */ 347 ldr r2, [r1] /* Read the value of MPU_CTRL. */ 348 orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */ 349 str r2, [r1] /* Enable MPU. */ 350 dsb /* Force memory writes before continuing. */ 351 352 restore_context: 353 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 354 ldr r1, [r3] /* r1 = pxCurrentTCB.*/ 355 ldr r2, [r1] /* r2 = Location of saved context in TCB. */ 356 357 restore_special_regs: 358 #if ( configENABLE_PAC == 1 ) 359 ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */ 360 msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */ 361 msr PAC_KEY_P_1, r4 362 msr PAC_KEY_P_2, r5 363 msr PAC_KEY_P_3, r6 364 clrm {r3-r6} /* Clear r3-r6. */ 365 #endif /* configENABLE_PAC */ 366 ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ 367 msr psp, r3 368 msr psplim, r4 369 msr control, r5 370 ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 371 str r0, [r4] /* Restore xSecureContext. */ 372 cbz r0, restore_ns_context /* No secure context to restore. */ 373 374 restore_s_context: 375 push {r1-r3, lr} 376 bl SecureContext_LoadContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 377 pop {r1-r3, lr} 378 379 restore_ns_context: 380 mov r0, lr /* r0 = LR (EXC_RETURN). */ 381 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. */ 382 bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */ 383 384 restore_general_regs: 385 ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */ 386 stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */ 387 ldmdb r2!, {r4-r11} /* r4-r11 restored. */ 388 389 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 390 tst lr, #0x10 391 ittt eq 392 vldmdbeq r2!, {s0-s16} /* s0-s16 contain hardware saved FP context. */ 393 vstmiaeq r3!, {s0-s16} /* Copy hardware saved FP context on the task stack. */ 394 vldmdbeq r2!, {s16-s31} /* Restore s16-s31. */ 395 #endif /* configENABLE_FPU || configENABLE_MVE */ 396 397 restore_context_done: 398 str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */ 399 bx lr 400 401#else /* configENABLE_MPU */ 402 403PendSV_Handler: 404 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 405 ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ 406 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 407 ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */ 408 mrs r2, psp /* Read PSP in r2. */ 409 410 cbz r0, save_ns_context /* No secure context to save. */ 411 save_s_context: 412 push {r0-r2, lr} 413 bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 414 pop {r0-r2, lr} 415 416 save_ns_context: 417 mov r3, lr /* r3 = LR. */ 418 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. */ 419 bmi save_special_regs /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */ 420 421 save_general_regs: 422 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 423 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ 424 it eq 425 vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ 426 #endif /* configENABLE_FPU || configENABLE_MVE */ 427 stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */ 428 429 save_special_regs: 430 mrs r3, psplim /* r3 = PSPLIM. */ 431 stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */ 432 #if ( configENABLE_PAC == 1 ) 433 mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */ 434 mrs r4, PAC_KEY_P_2 435 mrs r5, PAC_KEY_P_1 436 mrs r6, PAC_KEY_P_0 437 stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */ 438 clrm {r3-r6} /* Clear r3-r6. */ 439 #endif /* configENABLE_PAC */ 440 441 str r2, [r1] /* Save the new top of stack in TCB. */ 442 443 select_next_task: 444 mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY 445 msr basepri, r0 /* Disable interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 446 dsb 447 isb 448 bl vTaskSwitchContext 449 mov r0, #0 /* r0 = 0. */ 450 msr basepri, r0 /* Enable interrupts. */ 451 452 restore_context: 453 ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ 454 ldr r1, [r3] /* Read pxCurrentTCB. */ 455 ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ 456 457 restore_special_regs: 458 #if ( configENABLE_PAC == 1 ) 459 ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */ 460 msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */ 461 msr PAC_KEY_P_2, r4 462 msr PAC_KEY_P_1, r5 463 msr PAC_KEY_P_0, r6 464 clrm {r3-r6} /* Clear r3-r6. */ 465 #endif /* configENABLE_PAC */ 466 ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */ 467 msr psplim, r3 /* Restore the PSPLIM register value for the task. */ 468 ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ 469 str r0, [r3] /* Restore the task's xSecureContext. */ 470 cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */ 471 472 restore_s_context: 473 push {r1-r3, lr} 474 bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ 475 pop {r1-r3, lr} 476 477 restore_ns_context: 478 mov r0, lr /* r0 = LR (EXC_RETURN). */ 479 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. */ 480 bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */ 481 482 restore_general_regs: 483 ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ 484 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) 485 tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ 486 it eq 487 vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ 488 #endif /* configENABLE_FPU || configENABLE_MVE */ 489 490 restore_context_done: 491 msr psp, r2 /* Remember the new top of stack for the task. */ 492 bx lr 493 494#endif /* configENABLE_MPU */ 495/*-----------------------------------------------------------*/ 496 497#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 498 499SVC_Handler: 500 tst lr, #4 501 ite eq 502 mrseq r0, msp 503 mrsne r0, psp 504 505 ldr r1, [r0, #24] 506 ldrb r2, [r1, #-2] 507 cmp r2, #NUM_SYSTEM_CALLS 508 blt syscall_enter 509 cmp r2, #104 /* portSVC_SYSTEM_CALL_EXIT. */ 510 beq syscall_exit 511 b vPortSVCHandler_C 512 513 syscall_enter: 514 mov r1, lr 515 b vSystemCallEnter 516 517 syscall_exit: 518 mov r1, lr 519 b vSystemCallExit 520 521#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 522 523SVC_Handler: 524 tst lr, #4 525 ite eq 526 mrseq r0, msp 527 mrsne r0, psp 528 b vPortSVCHandler_C 529 530#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 531/*-----------------------------------------------------------*/ 532 533vPortFreeSecureContext: 534 /* r0 = uint32_t *pulTCB. */ 535 ldr r2, [r0] /* The first item in the TCB is the top of the stack. */ 536 ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */ 537 cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */ 538 it ne 539 svcne 101 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 101. */ 540 bx lr /* Return. */ 541/*-----------------------------------------------------------*/ 542 543 END 544