mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-02 12:24:07 -04:00
Memory Protection Unit (MPU) Enhancements (#705)
Memory Protection Unit (MPU) Enhancements This commit introduces a new MPU wrapper that places additional restrictions on unprivileged tasks. The following is the list of changes introduced with the new MPU wrapper: 1. Opaque and indirectly verifiable integers for kernel object handles: All the kernel object handles (for example, queue handles) are now opaque integers. Previously object handles were raw pointers. 2. Saving the task context in Task Control Block (TCB): When a task is swapped out by the scheduler, the task's context is now saved in its TCB. Previously the task's context was saved on its stack. 3. Execute system calls on a separate privileged only stack: FreeRTOS system calls, which execute with elevated privilege, now use a separate privileged only stack. Previously system calls used the calling task's stack. The application writer can control the size of the system call stack using new configSYSTEM_CALL_STACK_SIZE config macro. 4. Memory bounds checks: FreeRTOS system calls which accept a pointer and de-reference it, now verify that the calling task has required permissions to access the memory location referenced by the pointer. 5. System call restrictions: The following system calls are no longer available to unprivileged tasks: - vQueueDelete - xQueueCreateMutex - xQueueCreateMutexStatic - xQueueCreateCountingSemaphore - xQueueCreateCountingSemaphoreStatic - xQueueGenericCreate - xQueueGenericCreateStatic - xQueueCreateSet - xQueueRemoveFromSet - xQueueGenericReset - xTaskCreate - xTaskCreateStatic - vTaskDelete - vTaskPrioritySet - vTaskSuspendAll - xTaskResumeAll - xTaskGetHandle - xTaskCallApplicationTaskHook - vTaskList - vTaskGetRunTimeStats - xTaskCatchUpTicks - xEventGroupCreate - xEventGroupCreateStatic - vEventGroupDelete - xStreamBufferGenericCreate - xStreamBufferGenericCreateStatic - vStreamBufferDelete - xStreamBufferReset Also, an unprivileged task can no longer use vTaskSuspend to suspend any task other than itself. We thank the following people for their inputs in these enhancements: - David Reiss of Meta Platforms, Inc. - Lan Luo, Xinhui Shao, Yumeng Wei, Zixia Liu, Huaiyu Yan and Zhen Ling of School of Computer Science and Engineering, Southeast University, China. - Xinwen Fu of Department of Computer Science, University of Massachusetts Lowell, USA. - Yuequi Chen, Zicheng Wang, Minghao Lin of University of Colorado Boulder, USA.
This commit is contained in:
parent
18e2937239
commit
97050a17aa
123 changed files with 94802 additions and 6515 deletions
|
@ -32,12 +32,21 @@ the code is included in C files but excluded by the preprocessor in assembly
|
|||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
#ifndef configUSE_MPU_WRAPPERS_V1
|
||||
#define configUSE_MPU_WRAPPERS_V1 0
|
||||
#endif
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
EXTERN vSystemCallEnter
|
||||
EXTERN vSystemCallEnter_1
|
||||
EXTERN vSystemCallExit
|
||||
#endif
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
|
@ -89,50 +98,81 @@ vPortAllocateSecureContext:
|
|||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
program_mpu_first_task:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r0, [r3] /* r0 = pxCurrentTCB. */
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||
str r2, [r1] /* Disable MPU. */
|
||||
|
||||
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r1, [r2] /* Program MAIR0. */
|
||||
|
||||
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r1] /* Program RNR = 4. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
movs r3, #8 /* r3 = 8. */
|
||||
str r3, [r1] /* Program RNR = 8. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
movs r3, #12 /* r3 = 12. */
|
||||
str r3, [r1] /* Program RNR = 12. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
|
||||
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||
orr r2, #1 /* r2 = r1 | 1 i.e. Set the bit 0 in r2. */
|
||||
str r2, [r1] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
restore_context_first_task:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||
|
||||
restore_special_regs_first_task:
|
||||
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||
msr psp, r3
|
||||
msr psplim, r4
|
||||
msr control, r5
|
||||
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r4] /* Restore xSecureContext. */
|
||||
|
||||
restore_general_regs_first_task:
|
||||
ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||
stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||
ldmdb r2!, {r4-r11} /* r4-r11 restored. */
|
||||
|
||||
restore_context_done_first_task:
|
||||
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx lr
|
||||
|
||||
#else /* configENABLE_MPU */
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
|
@ -145,6 +185,7 @@ vRestoreContextOfFirstTask:
|
|||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -183,6 +224,143 @@ vClearInterruptMask:
|
|||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
ldr r2, [r1] /* r2 = Location in TCB where the context should be saved. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
save_s_context:
|
||||
push {r0-r2, lr}
|
||||
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r0-r2, lr}
|
||||
|
||||
save_ns_context:
|
||||
mov r3, lr /* r3 = LR (EXC_RETURN). */
|
||||
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. */
|
||||
bmi save_special_regs /* r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||
|
||||
save_general_regs:
|
||||
mrs r3, psp
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
add r3, r3, #0x20 /* Move r3 to location where s0 is saved. */
|
||||
tst lr, #0x10
|
||||
ittt eq
|
||||
vstmiaeq r2!, {s16-s31} /* Store s16-s31. */
|
||||
vldmiaeq r3, {s0-s16} /* Copy hardware saved FP context into s0-s16. */
|
||||
vstmiaeq r2!, {s0-s16} /* Store hardware saved FP context. */
|
||||
sub r3, r3, #0x20 /* Set r3 back to the location of hardware saved context. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
stmia r2!, {r4-r11} /* Store r4-r11. */
|
||||
ldmia r3, {r4-r11} /* Copy the hardware saved context into r4-r11. */
|
||||
stmia r2!, {r4-r11} /* Store the hardware saved context. */
|
||||
|
||||
save_special_regs:
|
||||
mrs r3, psp /* r3 = PSP. */
|
||||
mrs r4, psplim /* r4 = PSPLIM. */
|
||||
mrs r5, control /* r5 = CONTROL. */
|
||||
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||
|
||||
select_next_task:
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
program_mpu:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r0, [r3] /* r0 = pxCurrentTCB.*/
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||
bic r2, #1 /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||
str r2, [r1] /* Disable MPU. */
|
||||
|
||||
adds r0, #4 /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||
ldr r1, [r0] /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r1, [r2] /* Program MAIR0. */
|
||||
|
||||
adds r0, #4 /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||
ldr r1, =0xe000ed98 /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r1] /* Program RNR = 4. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
movs r3, #8 /* r3 = 8. */
|
||||
str r3, [r1] /* Program RNR = 8. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
movs r3, #12 /* r3 = 12. */
|
||||
str r3, [r1] /* Program RNR = 12. */
|
||||
ldmia r0!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
|
||||
ldr r1, =0xe000ed94 /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r2, [r1] /* Read the value of MPU_CTRL. */
|
||||
orr r2, #1 /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||
str r2, [r1] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
restore_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* r1 = pxCurrentTCB.*/
|
||||
ldr r2, [r1] /* r2 = Location of saved context in TCB. */
|
||||
|
||||
restore_special_regs:
|
||||
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
|
||||
msr psp, r3
|
||||
msr psplim, r4
|
||||
msr control, r5
|
||||
ldr r4, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r4] /* Restore xSecureContext. */
|
||||
cbz r0, restore_ns_context /* No secure context to restore. */
|
||||
|
||||
restore_s_context:
|
||||
push {r1-r3, lr}
|
||||
bl SecureContext_LoadContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r1-r3, lr}
|
||||
|
||||
restore_ns_context:
|
||||
mov r0, lr /* r0 = LR (EXC_RETURN). */
|
||||
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. */
|
||||
bmi restore_context_done /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
|
||||
|
||||
restore_general_regs:
|
||||
ldmdb r2!, {r4-r11} /* r4-r11 contain hardware saved context. */
|
||||
stmia r3!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||
ldmdb r2!, {r4-r11} /* r4-r11 restored. */
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10
|
||||
ittt eq
|
||||
vldmdbeq r2!, {s0-s16} /* s0-s16 contain hardware saved FP context. */
|
||||
vstmiaeq r3!, {s0-s16} /* Copy hardware saved FP context on the task stack. */
|
||||
vldmdbeq r2!, {s16-s31} /* Restore s16-s31. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
restore_context_done:
|
||||
str r2, [r1] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
bx lr
|
||||
|
||||
#else /* configENABLE_MPU */
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
|
@ -200,20 +378,11 @@ PendSV_Handler:
|
|||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
|
@ -224,17 +393,6 @@ PendSV_Handler:
|
|||
it eq
|
||||
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #16 /* r2 = r2 + 16. */
|
||||
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #16 /* r2 = r2 - 16. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #12 /* r2 = r2 + 12. */
|
||||
|
@ -243,7 +401,6 @@ PendSV_Handler:
|
|||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #12 /* r2 = r2 - 12. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
|
@ -258,51 +415,6 @@ PendSV_Handler:
|
|||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r3] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r3] /* Program MAIR0. */
|
||||
ldr r3, =0xe000ed98 /* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r3] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r3!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r3] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
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. */
|
||||
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. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
|
@ -319,7 +431,6 @@ PendSV_Handler:
|
|||
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. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
|
||||
|
@ -330,14 +441,50 @@ PendSV_Handler:
|
|||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
|
||||
ldr r1, [r0, #24]
|
||||
ldrb r2, [r1, #-2]
|
||||
cmp r2, #4 /* portSVC_SYSTEM_CALL_ENTER. */
|
||||
beq syscall_enter
|
||||
cmp r2, #5 /* portSVC_SYSTEM_CALL_ENTER_1. */
|
||||
beq syscall_enter_1
|
||||
cmp r2, #6 /* portSVC_SYSTEM_CALL_EXIT. */
|
||||
beq syscall_exit
|
||||
b vPortSVCHandler_C
|
||||
|
||||
syscall_enter:
|
||||
mov r1, lr
|
||||
b vSystemCallEnter
|
||||
|
||||
syscall_enter_1:
|
||||
mov r1, lr
|
||||
b vSystemCallEnter_1
|
||||
|
||||
syscall_exit:
|
||||
mov r1, lr
|
||||
b vSystemCallExit
|
||||
|
||||
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue