mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-20 01:58:32 -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
1993
portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
Normal file
1993
portable/RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -108,13 +108,34 @@
|
|||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Constants used during system call enter and exit. */
|
||||
#define portPSR_STACK_PADDING_MASK ( 1UL << 9UL )
|
||||
#define portEXC_RETURN_STACK_FRAME_TYPE_MASK ( 1UL << 4UL )
|
||||
|
||||
/* Offsets in the stack to the parameters when inside the SVC handler. */
|
||||
#define portOFFSET_TO_LR ( 5 )
|
||||
#define portOFFSET_TO_PC ( 6 )
|
||||
#define portOFFSET_TO_PSR ( 7 )
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* Does addr lie within [start, end] address range? */
|
||||
#define portIS_ADDRESS_WITHIN_RANGE( addr, start, end ) \
|
||||
( ( ( addr ) >= ( start ) ) && ( ( addr ) <= ( end ) ) )
|
||||
|
||||
/* Is the access request satisfied by the available permissions? */
|
||||
#define portIS_AUTHORIZED( accessRequest, permissions ) \
|
||||
( ( ( permissions ) & ( accessRequest ) ) == accessRequest )
|
||||
|
||||
/* Max value that fits in a uint32_t type. */
|
||||
#define portUINT32_MAX ( ~( ( uint32_t ) 0 ) )
|
||||
|
||||
/* Check if adding a and b will result in overflow. */
|
||||
#define portADD_UINT32_WILL_OVERFLOW( a, b ) ( ( a ) > ( portUINT32_MAX - ( b ) ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
* variable. Note this is not saved as part of the task context as context
|
||||
* switches can only occur when uxCriticalNesting is zero. */
|
||||
|
@ -158,7 +179,7 @@ static void prvRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION;
|
|||
* C portion of the SVC handler. The SVC handler is split between an asm entry
|
||||
* and a C wrapper for simplicity of coding and maintenance.
|
||||
*/
|
||||
void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( used ) ) PRIVILEGED_FUNCTION;
|
||||
void vSVCHandler_C( uint32_t * pulRegisters ) __attribute__( ( used ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Function to enable the VFP.
|
||||
|
@ -215,6 +236,61 @@ void vResetPrivilege( void );
|
|||
#else
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Triggers lazy stacking of FPU registers.
|
||||
*/
|
||||
static void prvTriggerLazyStacking( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
/**
|
||||
* @brief Sets up the system call stack so that upon returning from
|
||||
* SVC, the system call stack is used.
|
||||
*
|
||||
* It is used for the system calls with up to 4 parameters.
|
||||
*
|
||||
* @param pulTaskStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
/**
|
||||
* @brief Sets up the system call stack so that upon returning from
|
||||
* SVC, the system call stack is used.
|
||||
*
|
||||
* It is used for the system calls with 5 parameters.
|
||||
*
|
||||
* @param pulTaskStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
/**
|
||||
* @brief Sets up the task stack so that upon returning from
|
||||
* SVC, the task stack is used again.
|
||||
*
|
||||
* @param pulSystemCallStack The current SP when the SVC was raised.
|
||||
* @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
|
||||
*/
|
||||
void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the calling task is privileged.
|
||||
*
|
||||
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
@ -223,43 +299,59 @@ void vResetPrivilege( void );
|
|||
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
||||
TaskFunction_t pxCode,
|
||||
void * pvParameters,
|
||||
BaseType_t xRunPrivileged )
|
||||
BaseType_t xRunPrivileged,
|
||||
xMPU_SETTINGS * xMPUSettings )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
* own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
|
||||
xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
|
||||
xMPUSettings->ulContext[ 0 ] = portINITIAL_CONTROL_IF_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
|
||||
xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
|
||||
xMPUSettings->ulContext[ 0 ] = portINITIAL_CONTROL_IF_UNPRIVILEGED;
|
||||
}
|
||||
xMPUSettings->ulContext[ 1 ] = 0x04040404; /* r4. */
|
||||
xMPUSettings->ulContext[ 2 ] = 0x05050505; /* r5. */
|
||||
xMPUSettings->ulContext[ 3 ] = 0x06060606; /* r6. */
|
||||
xMPUSettings->ulContext[ 4 ] = 0x07070707; /* r7. */
|
||||
xMPUSettings->ulContext[ 5 ] = 0x08080808; /* r8. */
|
||||
xMPUSettings->ulContext[ 6 ] = 0x09090909; /* r9. */
|
||||
xMPUSettings->ulContext[ 7 ] = 0x10101010; /* r10. */
|
||||
xMPUSettings->ulContext[ 8 ] = 0x11111111; /* r11. */
|
||||
xMPUSettings->ulContext[ 9 ] = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
|
||||
|
||||
return pxTopOfStack;
|
||||
xMPUSettings->ulContext[ 10 ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
|
||||
xMPUSettings->ulContext[ 11 ] = ( uint32_t ) pvParameters; /* r0. */
|
||||
xMPUSettings->ulContext[ 12 ] = 0x01010101; /* r1. */
|
||||
xMPUSettings->ulContext[ 13 ] = 0x02020202; /* r2. */
|
||||
xMPUSettings->ulContext[ 14 ] = 0x03030303; /* r3. */
|
||||
xMPUSettings->ulContext[ 15 ] = 0x12121212; /* r12. */
|
||||
xMPUSettings->ulContext[ 16 ] = 0; /* LR. */
|
||||
xMPUSettings->ulContext[ 17 ] = ( ( uint32_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC. */
|
||||
xMPUSettings->ulContext[ 18 ] = portINITIAL_XPSR; /* xPSR. */
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
{
|
||||
/* Ensure that the system call stack is double word aligned. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1 ] );
|
||||
xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = ( uint32_t * ) ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStack ) &
|
||||
( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
|
||||
|
||||
/* This is not NULL only for the duration of a system call. */
|
||||
xMPUSettings->xSystemCallStackInfo.pulTaskStack = NULL;
|
||||
}
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
return &( xMPUSettings->ulContext[ 19 ] );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void prvSVCHandler( uint32_t * pulParam )
|
||||
void vSVCHandler_C( uint32_t * pulParam )
|
||||
{
|
||||
uint8_t ucSVCNumber;
|
||||
uint32_t ulReg, ulPC;
|
||||
uint32_t ulPC, ulReg;
|
||||
|
||||
#if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||
extern uint32_t __syscalls_flash_start__;
|
||||
|
@ -300,11 +392,11 @@ void prvSVCHandler( uint32_t * pulParam )
|
|||
{
|
||||
__asm
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
/* *INDENT-OFF* */
|
||||
mrs ulReg, control /* Obtain current control value. */
|
||||
bic ulReg, # 1 /* Set privilege bit. */
|
||||
msr control, ulReg /* Write back new control value. */
|
||||
/* *INDENT-ON* */
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,14 +405,14 @@ void prvSVCHandler( uint32_t * pulParam )
|
|||
case portSVC_RAISE_PRIVILEGE:
|
||||
__asm
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
/* *INDENT-OFF* */
|
||||
mrs ulReg, control /* Obtain current control value. */
|
||||
bic ulReg, # 1 /* Set privilege bit. */
|
||||
msr control, ulReg /* Write back new control value. */
|
||||
/* *INDENT-ON* */
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
break;
|
||||
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||
|
||||
default: /* Unknown SVC call. */
|
||||
break;
|
||||
|
@ -328,9 +420,339 @@ void prvSVCHandler( uint32_t * pulParam )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm void prvTriggerLazyStacking( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
PRESERVE8
|
||||
|
||||
vpush {s0} /* Trigger lazy stacking. */
|
||||
vpop {s0} /* Nullify the affect of the above instruction. */
|
||||
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i, r1;
|
||||
extern uint32_t __syscalls_flash_start__;
|
||||
extern uint32_t __syscalls_flash_end__;
|
||||
|
||||
ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
|
||||
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
prvTriggerLazyStacking();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
|
||||
/* Make space on the system call stack for the stack frame. */
|
||||
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulSystemCallStack[ i ] = pulTaskStack[ i ];
|
||||
}
|
||||
|
||||
/* Use the pulSystemCallStack in thread mode. */
|
||||
__asm
|
||||
{
|
||||
msr psp, pulSystemCallStack
|
||||
};
|
||||
|
||||
/* Raise the privilege for the duration of the system call. */
|
||||
__asm
|
||||
{
|
||||
mrs r1, control /* Obtain current control value. */
|
||||
bic r1, #1 /* Clear nPRIV bit. */
|
||||
msr control, r1 /* Write back new control value. */
|
||||
};
|
||||
|
||||
/* Remember the location where we should copy the stack frame when we exit from
|
||||
* the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
|
||||
|
||||
/* Store the value of the Link Register before the SVC was raised. We need to
|
||||
* restore it when we exit from the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
|
||||
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
|
||||
{
|
||||
pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
|
||||
}
|
||||
|
||||
/* We ensure in pxPortInitialiseStack that the system call stack is
|
||||
* double word aligned and therefore, there is no need of padding.
|
||||
* Clear the bit[9] of stacked xPSR. */
|
||||
pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i, r1;
|
||||
extern uint32_t __syscalls_flash_start__;
|
||||
extern uint32_t __syscalls_flash_end__;
|
||||
|
||||
ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
|
||||
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
prvTriggerLazyStacking();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
|
||||
/* Make space on the system call stack for the stack frame and
|
||||
* the parameter passed on the stack. We only need to copy one
|
||||
* parameter but we still reserve 2 spaces to keep the stack
|
||||
* double word aligned. */
|
||||
pulSystemCallStack = pulSystemCallStack - ulStackFrameSize - 2UL;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulSystemCallStack[ i ] = pulTaskStack[ i ];
|
||||
}
|
||||
|
||||
/* Copy the parameter which is passed the stack. */
|
||||
if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
|
||||
{
|
||||
pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize + 1 ];
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize ];
|
||||
/* Record if the hardware used padding to force the stack pointer
|
||||
* to be double word aligned. */
|
||||
pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
|
||||
}
|
||||
|
||||
/* Use the pulSystemCallStack in thread mode. */
|
||||
__asm
|
||||
{
|
||||
msr psp, pulSystemCallStack
|
||||
};
|
||||
|
||||
/* Raise the privilege for the duration of the system call. */
|
||||
__asm
|
||||
{
|
||||
mrs r1, control /* Obtain current control value. */
|
||||
bic r1, #1 /* Clear nPRIV bit. */
|
||||
msr control, r1 /* Write back new control value. */
|
||||
};
|
||||
|
||||
/* Remember the location where we should copy the stack frame when we exit from
|
||||
* the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
|
||||
|
||||
/* Store the value of the Link Register before the SVC was raised. We need to
|
||||
* restore it when we exit from the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
|
||||
|
||||
/* We ensure in pxPortInitialiseStack that the system call stack is
|
||||
* double word aligned and therefore, there is no need of padding.
|
||||
* Clear the bit[9] of stacked xPSR. */
|
||||
pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
extern TaskHandle_t pxCurrentTCB;
|
||||
xMPU_SETTINGS * pxMpuSettings;
|
||||
uint32_t * pulTaskStack;
|
||||
uint32_t ulStackFrameSize, ulSystemCallLocation, i, r1;
|
||||
extern uint32_t __syscalls_flash_start__;
|
||||
extern uint32_t __syscalls_flash_end__;
|
||||
|
||||
ulSystemCallLocation = pulSystemCallStack[ portOFFSET_TO_PC ];
|
||||
|
||||
/* If the request did not come from the system call section, do nothing. */
|
||||
if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
|
||||
( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
|
||||
{
|
||||
pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
|
||||
pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
|
||||
|
||||
if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
|
||||
{
|
||||
/* Extended frame i.e. FPU in use. */
|
||||
ulStackFrameSize = 26;
|
||||
prvTriggerLazyStacking();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard frame i.e. FPU not in use. */
|
||||
ulStackFrameSize = 8;
|
||||
}
|
||||
|
||||
/* Make space on the task stack for the stack frame. */
|
||||
pulTaskStack = pulTaskStack - ulStackFrameSize;
|
||||
|
||||
/* Copy the stack frame. */
|
||||
for( i = 0; i < ulStackFrameSize; i++ )
|
||||
{
|
||||
pulTaskStack[ i ] = pulSystemCallStack[ i ];
|
||||
}
|
||||
|
||||
/* Use the pulTaskStack in thread mode. */
|
||||
__asm
|
||||
{
|
||||
msr psp, pulTaskStack
|
||||
};
|
||||
|
||||
/* Drop the privilege before returning to the thread mode. */
|
||||
__asm
|
||||
{
|
||||
mrs r1, control /* Obtain current control value. */
|
||||
orr r1, #1 /* Set nPRIV bit. */
|
||||
msr control, r1 /* Write back new control value. */
|
||||
};
|
||||
|
||||
/* Restore the stacked link register to what it was at the time of
|
||||
* system call entry. */
|
||||
pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
|
||||
|
||||
/* If the hardware used padding to force the stack pointer
|
||||
* to be double word aligned, set the stacked xPSR bit[9],
|
||||
* otherwise clear it. */
|
||||
if( ( pxMpuSettings->ulTaskFlags & portSTACK_FRAME_HAS_PADDING_FLAG ) == portSTACK_FRAME_HAS_PADDING_FLAG )
|
||||
{
|
||||
pulTaskStack[ portOFFSET_TO_PSR ] |= portPSR_STACK_PADDING_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulTaskStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
|
||||
}
|
||||
|
||||
/* This is not NULL only for the duration of the system call. */
|
||||
pxMpuSettings->xSystemCallStackInfo.pulTaskStack = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
BaseType_t xTaskIsPrivileged = pdFALSE;
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xTaskIsPrivileged = pdTRUE;
|
||||
}
|
||||
|
||||
return xTaskIsPrivileged;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
__asm void vPortSVCHandler( void )
|
||||
{
|
||||
extern prvSVCHandler
|
||||
extern vSVCHandler_C
|
||||
extern vSystemCallEnter
|
||||
extern vSystemCallEnter_1
|
||||
extern vSystemCallExit
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
PRESERVE8
|
||||
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
|
||||
ldr r1, [r0, #24]
|
||||
ldrb r2, [r1, #-2]
|
||||
cmp r2, #portSVC_SYSTEM_CALL_ENTER
|
||||
beq syscall_enter
|
||||
cmp r2, #portSVC_SYSTEM_CALL_ENTER_1
|
||||
beq syscall_enter_1
|
||||
cmp r2, #portSVC_SYSTEM_CALL_EXIT
|
||||
beq syscall_exit
|
||||
b vSVCHandler_C
|
||||
|
||||
syscall_enter
|
||||
mov r1, lr
|
||||
b vSystemCallEnter
|
||||
|
||||
syscall_enter_1
|
||||
mov r1, lr
|
||||
b vSystemCallEnter_1
|
||||
|
||||
syscall_exit
|
||||
mov r1, lr
|
||||
b vSystemCallExit
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
#else /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
__asm void vPortSVCHandler( void )
|
||||
{
|
||||
extern vSVCHandler_C
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
PRESERVE8
|
||||
|
@ -345,9 +767,11 @@ __asm void vPortSVCHandler( void )
|
|||
mrs r0, psp
|
||||
#endif
|
||||
|
||||
b prvSVCHandler
|
||||
b vSVCHandler_C
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm void prvRestoreContextOfFirstTask( void )
|
||||
|
@ -355,45 +779,54 @@ __asm void prvRestoreContextOfFirstTask( void )
|
|||
/* *INDENT-OFF* */
|
||||
PRESERVE8
|
||||
|
||||
ldr r0, =0xE000ED08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [ r0 ]
|
||||
ldr r0, [ r0 ]
|
||||
msr msp, r0 /* Set the msp back to the start of the stack. */
|
||||
ldr r3, =pxCurrentTCB /* Restore the context. */
|
||||
ldr r1, [ r3 ]
|
||||
ldr r0, [ r1 ] /* The first item in the TCB is the task top of stack. */
|
||||
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
||||
ldr r0, =0xE000ED08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
msr msp, r0 /* Set the msp back to the start of the stack. */
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [ r2 ] /* Read the value of MPU_CTRL. */
|
||||
bic r3, r3, # 1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [ r2 ] /* Disable MPU. */
|
||||
/*------------ Program MPU. ------------ */
|
||||
ldr r3, =pxCurrentTCB /* r3 = &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* r2 = pxCurrentTCB. */
|
||||
add r2, r2, #4 /* r2 = Second item in the TCB which is xMPUSettings. */
|
||||
|
||||
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r0, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r0] /* Read the value of MPU_CTRL. */
|
||||
bic r3, r3, # 1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r0] /* Disable MPU. */
|
||||
|
||||
ldr r0, =0xe000ed9c /* Region Base Address register. */
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [ r2 ] /* Read the value of MPU_CTRL. */
|
||||
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [ r2 ] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
ldr r0, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r0] /* Read the value of MPU_CTRL. */
|
||||
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r0] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
ldmia r0 !, { r3 - r11, r14 } /* Pop the registers that are not automatically saved on exception entry. */
|
||||
/*---------- Restore Context. ---------- */
|
||||
ldr r3, =pxCurrentTCB /* r3 = &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* r2 = pxCurrentTCB. */
|
||||
ldr r1, [r2] /* r1 = Location of saved context in TCB. */
|
||||
|
||||
ldmdb r1!, {r0, r4-r11} /* r0 contains PSP after the hardware had saved context. r4-r11 contain hardware saved context. */
|
||||
msr psp, r0
|
||||
stmia r0, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||
ldmdb r1!, {r3-r11, lr} /* r3 contains CONTROL register. r4-r11 and LR restored. */
|
||||
msr control, r3
|
||||
msr psp, r0 /* Restore the task stack pointer. */
|
||||
str r1, [r2] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
nop
|
||||
bx lr
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -650,72 +1083,90 @@ __asm void xPortPendSVHandler( void )
|
|||
/* *INDENT-OFF* */
|
||||
PRESERVE8
|
||||
|
||||
ldr r3, =pxCurrentTCB /* r3 = &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* r2 = pxCurrentTCB. */
|
||||
ldr r1, [r2] /* r1 = Location where the context should be saved. */
|
||||
|
||||
/*------------ Save Context. ----------- */
|
||||
mrs r3, control
|
||||
mrs r0, psp
|
||||
isb
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
|
||||
ldr r2, [ r3 ]
|
||||
add r0, r0, #0x20 /* Move r0 to location where s0 is saved. */
|
||||
tst lr, #0x10
|
||||
ittt eq
|
||||
vstmiaeq r1!, {s16-s31} /* Store s16-s31. */
|
||||
vldmiaeq r0, {s0-s16} /* Copy hardware saved FP context into s0-s16. */
|
||||
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
|
||||
sub r0, r0, #0x20 /* Set r0 back to the location of hardware saved context. */
|
||||
|
||||
tst r14, #0x10 /* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
it eq
|
||||
vstmdbeq r0 !, { s16 - s31 }
|
||||
stmia r1!, {r3-r11, lr} /* Store CONTROL register, r4-r11 and LR. */
|
||||
ldmia r0, {r4-r11} /* Copy hardware saved context into r4-r11. */
|
||||
stmia r1!, {r0, r4-r11} /* Store original PSP (after hardware has saved context) and the hardware saved context. */
|
||||
str r1, [r2] /* Save the location from where the context should be restored as the first member of TCB. */
|
||||
|
||||
mrs r1, control
|
||||
stmdb r0 !, { r1, r4 - r11, r14 } /* Save the remaining registers. */
|
||||
str r0, [ r2 ] /* Save the new top of stack into the first member of the TCB. */
|
||||
|
||||
stmdb sp !, { r0, r3 }
|
||||
mov r0, # configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
|
||||
cpsid i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
|
||||
#endif
|
||||
/*---------- Select next task. --------- */
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
|
||||
cpsid i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
|
||||
#endif
|
||||
msr basepri, r0
|
||||
dsb
|
||||
isb
|
||||
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
|
||||
cpsie i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
|
||||
#endif
|
||||
#if ( configENABLE_ERRATA_837070_WORKAROUND == 1 )
|
||||
cpsie i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */
|
||||
#endif
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp !, { r0, r3 }
|
||||
/* Restore the context. */
|
||||
ldr r1, [ r3 ]
|
||||
ldr r0, [ r1 ] /* The first item in the TCB is the task top of stack. */
|
||||
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [ r2 ] /* Read the value of MPU_CTRL. */
|
||||
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [ r2 ] /* Disable MPU. */
|
||||
/*------------ Program MPU. ------------ */
|
||||
ldr r3, =pxCurrentTCB /* r3 = &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* r2 = pxCurrentTCB. */
|
||||
add r2, r2, #4 /* r2 = Second item in the TCB which is xMPUSettings. */
|
||||
|
||||
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r0, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r0] /* Read the value of MPU_CTRL. */
|
||||
bic r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r0] /* Disable MPU. */
|
||||
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
|
||||
ldmia r1 !, { r4 - r11 } /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
|
||||
stmia r2, { r4 - r11 } /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16. */
|
||||
ldr r0, =0xe000ed9c /* Region Base Address register. */
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [ r2 ] /* Read the value of MPU_CTRL. */
|
||||
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [ r2 ] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */
|
||||
ldmia r2!, {r4-r11} /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */
|
||||
stmia r0, {r4-r11} /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16. */
|
||||
|
||||
ldmia r0 !, { r3 - r11, r14 } /* Pop the registers that are not automatically saved on exception entry. */
|
||||
ldr r0, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r0] /* Read the value of MPU_CTRL. */
|
||||
orr r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r0] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
/*---------- Restore Context. ---------- */
|
||||
ldr r3, =pxCurrentTCB /* r3 = &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* r2 = pxCurrentTCB. */
|
||||
ldr r1, [r2] /* r1 = Location of saved context in TCB. */
|
||||
|
||||
ldmdb r1!, {r0, r4-r11} /* r0 contains PSP after the hardware had saved context. r4-r11 contain hardware saved context. */
|
||||
msr psp, r0
|
||||
stmia r0!, {r4-r11} /* Copy the hardware saved context on the task stack. */
|
||||
ldmdb r1!, {r3-r11, lr} /* r3 contains CONTROL register. r4-r11 and LR restored. */
|
||||
msr control, r3
|
||||
|
||||
tst r14, #0x10 /* Is the task using the FPU context? If so, pop the high vfp registers too. */
|
||||
it eq
|
||||
vldmiaeq r0 !, { s16 - s31 }
|
||||
tst lr, #0x10
|
||||
ittt eq
|
||||
vldmdbeq r1!, {s0-s16} /* s0-s16 contain hardware saved FP context. */
|
||||
vstmiaeq r0!, {s0-s16} /* Copy hardware saved FP context on the task stack. */
|
||||
vldmdbeq r1!, {s16-s31} /* Restore s16-s31. */
|
||||
|
||||
msr psp, r0
|
||||
bx r14
|
||||
nop
|
||||
str r1, [r2] /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
bx lr
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -934,11 +1385,19 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
|
|||
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) __SRAM_segment_start__;
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionEndAddress = ( uint32_t ) __SRAM_segment_end__;
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionPermissions = ( tskMPU_READ_PERMISSION |
|
||||
tskMPU_WRITE_PERMISSION );
|
||||
|
||||
/* Invalidate user configurable regions. */
|
||||
for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID );
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionStartAddress = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionEndAddress = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = 0UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -961,6 +1420,12 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
|
|||
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
|
||||
( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionEndAddress = ( uint32_t ) ( ( uint32_t ) ( pxBottomOfStack ) +
|
||||
( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1UL );
|
||||
xMPUSettings->xRegionSettings[ 0 ].ulRegionPermissions = ( tskMPU_READ_PERMISSION |
|
||||
tskMPU_WRITE_PERMISSION );
|
||||
}
|
||||
|
||||
lIndex = 0;
|
||||
|
@ -981,12 +1446,28 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
|
|||
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
|
||||
( xRegions[ lIndex ].ulParameters ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionStartAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionEndAddress = ( uint32_t ) ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1UL );
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = 0UL;
|
||||
if( ( ( xRegions[ lIndex ].ulParameters & portMPU_REGION_READ_ONLY ) == portMPU_REGION_READ_ONLY ) ||
|
||||
( ( xRegions[lIndex].ulParameters & portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ) == portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ) )
|
||||
{
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = tskMPU_READ_PERMISSION;
|
||||
}
|
||||
if( ( xRegions[ lIndex ].ulParameters & portMPU_REGION_READ_WRITE ) == portMPU_REGION_READ_WRITE )
|
||||
{
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = ( tskMPU_READ_PERMISSION | tskMPU_WRITE_PERMISSION );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID );
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionStartAddress = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionEndAddress = 0UL;
|
||||
xMPUSettings->xRegionSettings[ ul ].ulRegionPermissions = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
|
@ -995,6 +1476,47 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
|
||||
uint32_t ulBufferLength,
|
||||
uint32_t ulAccessRequested ) /* PRIVILEGED_FUNCTION */
|
||||
|
||||
{
|
||||
uint32_t i, ulBufferStartAddress, ulBufferEndAddress;
|
||||
BaseType_t xAccessGranted = pdFALSE;
|
||||
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
|
||||
|
||||
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( portADD_UINT32_WILL_OVERFLOW( ( ( uint32_t ) pvBuffer ), ( ulBufferLength - 1UL ) ) == pdFALSE )
|
||||
{
|
||||
ulBufferStartAddress = ( uint32_t ) pvBuffer;
|
||||
ulBufferEndAddress = ( ( ( uint32_t ) pvBuffer ) + ulBufferLength - 1UL );
|
||||
|
||||
for( i = 0; i < portTOTAL_NUM_REGIONS_IN_TCB; i++ )
|
||||
{
|
||||
if( portIS_ADDRESS_WITHIN_RANGE( ulBufferStartAddress,
|
||||
xTaskMpuSettings->xRegionSettings[ i ].ulRegionStartAddress,
|
||||
xTaskMpuSettings->xRegionSettings[ i ].ulRegionEndAddress ) &&
|
||||
portIS_ADDRESS_WITHIN_RANGE( ulBufferEndAddress,
|
||||
xTaskMpuSettings->xRegionSettings[ i ].ulRegionStartAddress,
|
||||
xTaskMpuSettings->xRegionSettings[ i ].ulRegionEndAddress ) &&
|
||||
portIS_AUTHORIZED( ulAccessRequested, xTaskMpuSettings->xRegionSettings[ i ].ulRegionPermissions ) )
|
||||
{
|
||||
xAccessGranted = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xAccessGranted;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm uint32_t prvPortGetIPSR( void )
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
|
|
|
@ -193,9 +193,45 @@ typedef struct MPU_REGION_REGISTERS
|
|||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
typedef struct MPU_REGION_SETTINGS
|
||||
{
|
||||
uint32_t ulRegionStartAddress;
|
||||
uint32_t ulRegionEndAddress;
|
||||
uint32_t ulRegionPermissions;
|
||||
} xMPU_REGION_SETTINGS;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
#ifndef configSYSTEM_CALL_STACK_SIZE
|
||||
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
|
||||
#endif
|
||||
|
||||
typedef struct SYSTEM_CALL_STACK_INFO
|
||||
{
|
||||
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t * pulTaskStack;
|
||||
uint32_t ulLinkRegisterAtSystemCallEntry;
|
||||
} xSYSTEM_CALL_STACK_INFO;
|
||||
|
||||
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
#define MAX_CONTEXT_SIZE 52
|
||||
|
||||
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
|
||||
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
|
||||
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
|
||||
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS_IN_TCB ];
|
||||
xMPU_REGION_SETTINGS xRegionSettings[ portTOTAL_NUM_REGIONS_IN_TCB ];
|
||||
uint32_t ulContext[ MAX_CONTEXT_SIZE ];
|
||||
uint32_t ulTaskFlags;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
|
||||
#endif
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
|
@ -209,9 +245,12 @@ typedef struct MPU_SETTINGS
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
#define portSVC_SYSTEM_CALL_ENTER 3 /* System calls with upto 4 parameters. */
|
||||
#define portSVC_SYSTEM_CALL_ENTER_1 4 /* System calls with 5 parameters. */
|
||||
#define portSVC_SYSTEM_CALL_EXIT 5
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
|
@ -314,6 +353,16 @@ extern void vResetPrivilege( void );
|
|||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern BaseType_t xPortIsTaskPrivileged( void );
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the calling task is privileged.
|
||||
*
|
||||
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
|
||||
*/
|
||||
#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
|
||||
{
|
||||
__asm
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue