mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 02:32:42 -05: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