ARMv8.1-M: Add task dedicated PAC key support (#1195)

armv8.1-m: Add task dedicated PAC key

To harden the security, each task is assigned a dedicated PAC key, so that attackers needs to guess the all the tasks' PAC keys right to exploit the system using Return Oriented Programming.

The kernel is now updated to support the following:
* A PAC key set with a random number generated and is saved in the task's context when a task is created.
* As part of scheduling, the task's PAC key is stored/restored to/from the task's context when a task is unscheduled/scheduled from/to run.

stack-overflow-check: Introduce portGET_CURRENT_TOP_OF_STACK macro

When MPU wrapper v2 is used, the task's context is stored in TCB and `pxTopOfStack`` member of TCB points to the context location in TCB. We, therefore, need to read PSP to find the task's current top of stack.

Signed-off-by: Ahmed Ismail <Ahmed.Ismail@arm.com>
This commit is contained in:
Ahmed Ismail 2025-01-14 05:20:52 +00:00 committed by GitHub
parent c38427eea4
commit 78e0cc778a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 6662 additions and 3530 deletions

View file

@ -106,6 +106,7 @@ CLKSOURCE
CLKSTA CLKSTA
CLRB CLRB
CLRF CLRF
clrm
CLRPSW CLRPSW
CMCNT CMCNT
CMCON CMCON
@ -678,6 +679,7 @@ pylint
pytest pytest
pyyaml pyyaml
RAMPZ RAMPZ
randomisation
RASR RASR
Rationalised Rationalised
Raynald Raynald

View file

@ -93,6 +93,10 @@
#define portBASE_TYPE_EXIT_CRITICAL() taskEXIT_CRITICAL() #define portBASE_TYPE_EXIT_CRITICAL() taskEXIT_CRITICAL()
#endif #endif
#ifndef portGET_CURRENT_TOP_OF_STACK
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { pxCurrentTopOfStack = ( StackType_t * ) pxCurrentTCB->pxTopOfStack; }
#endif
#ifndef configSTACK_DEPTH_TYPE #ifndef configSTACK_DEPTH_TYPE
#define configSTACK_DEPTH_TYPE StackType_t #define configSTACK_DEPTH_TYPE StackType_t
#endif #endif

View file

@ -57,9 +57,13 @@
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
do { \ do \
{ \
StackType_t * pxCurrentTopOfStack; \
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
\
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ if( pxCurrentTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
{ \ { \
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
@ -73,10 +77,13 @@
/* Only the current stack state is to be checked. */ /* Only the current stack state is to be checked. */
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
do { \ do \
{ \
StackType_t * pxCurrentTopOfStack; \
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
\ \
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ if( pxCurrentTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
{ \ { \
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
@ -89,11 +96,14 @@
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
do { \ do \
{ \
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \ const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
StackType_t * pxCurrentTopOfStack; \
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
\ \
if( ( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) || \ if( ( pxCurrentTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) || \
( pulStack[ 0 ] != ulCheckValue ) || \ ( pulStack[ 0 ] != ulCheckValue ) || \
( pulStack[ 1 ] != ulCheckValue ) || \ ( pulStack[ 1 ] != ulCheckValue ) || \
( pulStack[ 2 ] != ulCheckValue ) || \ ( pulStack[ 2 ] != ulCheckValue ) || \
@ -110,18 +120,20 @@
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
do { \ do \
{ \
int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
\ StackType_t * pxCurrentTopOfStack; \
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
\ \
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
\ \
if( ( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) || \ if( ( pxCurrentTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) || \
( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) ) \ ( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) ) \
{ \ { \
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -132,6 +140,15 @@
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */ " ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n" " ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
@ -280,7 +297,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" \n" " \n"
" save_general_regs: \n" " save_general_regs: \n"
" mrs r3, psp \n" " mrs r3, psp \n"
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */ " add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n" " tst lr, #0x10 \n"
@ -290,7 +306,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */ " sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */ " stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
@ -300,6 +315,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */ " mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */ " mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -358,6 +381,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -412,38 +443,37 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r2, psp \n" /* Read PSP in r2. */ " mrs r2, psp \n" /* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n" /* No secure context to save. */
" push {r0-r2, r14} \n" " save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r2, lr} \n"
" mov lr, r3 \n" /* LR = r3. */
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB.*/
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " lsls r3, r3, #25 \n" /* 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 \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */ " str r2, [r1] \n" /* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n" /* r2 = r2 + 12. */
" stm r2, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n" /* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
@ -454,34 +484,45 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n" /* Enable interrupts. */
" \n" " \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " restore_special_regs: \n"
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
" mov lr, r4 \n" /* LR = r4. */ " ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */ " str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " \n"
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " restore_s_context: \n"
" push {r2, r4} \n" " push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r1-r3, lr} \n"
" mov lr, r4 \n" /* LR = r4. */
" lsls r1, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* 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 \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */ " msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )

View file

@ -100,6 +100,14 @@
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -130,6 +138,15 @@
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */ " mrs r1, control \n" /* Obtain current control register value. */
@ -270,7 +287,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */ " sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */ " stmia r1!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
@ -279,6 +295,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */ " mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */ " mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -337,6 +361,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -381,6 +413,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n" /* Save the new top of stack in TCB. */
@ -397,6 +438,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -152,6 +152,14 @@ vRestoreContextOfFirstTask:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -177,6 +185,15 @@ vRestoreContextOfFirstTask:
ldr r3, [r2] /* Read 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. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
@ -271,6 +288,15 @@ PendSV_Handler:
mrs r4, psplim /* r4 = PSPLIM. */ mrs r4, psplim /* r4 = PSPLIM. */
mrs r5, control /* r5 = CONTROL. */ mrs r5, control /* r5 = CONTROL. */
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_1
mrs r5, PAC_KEY_P_2
mrs r6, PAC_KEY_P_3
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -329,6 +355,14 @@ PendSV_Handler:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -374,38 +408,37 @@ PendSV_Handler:
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} save_s_context:
push {r0-r2, lr}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r2, lr}
mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */
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. */
b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ mov r3, lr /* r3 = LR. */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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 /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
save_general_regs:
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
save_special_regs:
mrs r3, psplim /* r3 = PSPLIM. */
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_1
mrs r6, PAC_KEY_P_0
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */
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. */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -416,34 +449,45 @@ PendSV_Handler:
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
restore_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ restore_special_regs:
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
mov lr, r4 /* LR = r4. */ ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_1, r5
msr PAC_KEY_P_0, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's 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. */ 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. */ restore_s_context:
push {r2, r4} push {r1-r3, lr}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r1-r3, lr}
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
restore_ns_context: 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:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
restore_context_done:
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr

View file

@ -142,6 +142,14 @@ vRestoreContextOfFirstTask:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -165,6 +173,15 @@ vRestoreContextOfFirstTask:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
mrs r1, control /* Obtain current control register value. */ mrs r1, control /* Obtain current control register value. */
@ -233,7 +250,6 @@ PendSV_Handler:
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */ vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */ sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
stmia r1!, {r4-r11} /* Store r4-r11. */ stmia r1!, {r4-r11} /* Store r4-r11. */
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */ ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
stmia r1!, {r4-r11} /* Store the hardware saved context. */ stmia r1!, {r4-r11} /* Store the hardware saved context. */
@ -242,6 +258,15 @@ PendSV_Handler:
mrs r3, psplim /* r3 = PSPLIM. */ mrs r3, psplim /* r3 = PSPLIM. */
mrs r4, control /* r4 = CONTROL. */ mrs r4, control /* r4 = CONTROL. */
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_3
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */ str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -300,6 +325,14 @@ PendSV_Handler:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -335,6 +368,15 @@ PendSV_Handler:
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#if ( configENABLE_PAC == 1 )
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r2, PAC_KEY_P_2
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_0
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
@ -351,6 +393,15 @@ PendSV_Handler:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r3
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_0, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -132,6 +140,15 @@
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */ " ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n" " ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
@ -280,7 +297,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" \n" " \n"
" save_general_regs: \n" " save_general_regs: \n"
" mrs r3, psp \n" " mrs r3, psp \n"
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */ " add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n" " tst lr, #0x10 \n"
@ -290,7 +306,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */ " sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */ " stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
@ -300,6 +315,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */ " mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */ " mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -358,6 +381,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -412,38 +443,37 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r2, psp \n" /* Read PSP in r2. */ " mrs r2, psp \n" /* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n" /* No secure context to save. */
" push {r0-r2, r14} \n" " save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r2, lr} \n"
" mov lr, r3 \n" /* LR = r3. */
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB.*/
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " lsls r3, r3, #25 \n" /* 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 \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */ " str r2, [r1] \n" /* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n" /* r2 = r2 + 12. */
" stm r2, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n" /* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
@ -454,34 +484,45 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n" /* Enable interrupts. */
" \n" " \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " restore_special_regs: \n"
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
" mov lr, r4 \n" /* LR = r4. */ " ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */ " str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " \n"
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " restore_s_context: \n"
" push {r2, r4} \n" " push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r1-r3, lr} \n"
" mov lr, r4 \n" /* LR = r4. */
" lsls r1, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* 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 \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */ " msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -130,6 +138,15 @@
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */ " mrs r1, control \n" /* Obtain current control register value. */
@ -270,7 +287,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */ " sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */ " stmia r1!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
@ -279,6 +295,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */ " mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */ " mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -337,6 +361,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -381,6 +413,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n" /* Save the new top of stack in TCB. */
@ -397,6 +438,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -132,6 +140,15 @@
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */ " ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n" " ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
@ -280,7 +297,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" \n" " \n"
" save_general_regs: \n" " save_general_regs: \n"
" mrs r3, psp \n" " mrs r3, psp \n"
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */ " add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n" " tst lr, #0x10 \n"
@ -290,7 +306,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */ " sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */ " stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
@ -300,6 +315,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */ " mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */ " mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -358,6 +381,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -412,38 +443,37 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r2, psp \n" /* Read PSP in r2. */ " mrs r2, psp \n" /* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n" /* No secure context to save. */
" push {r0-r2, r14} \n" " save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r2, lr} \n"
" mov lr, r3 \n" /* LR = r3. */
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB.*/
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " lsls r3, r3, #25 \n" /* 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 \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */ " str r2, [r1] \n" /* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n" /* r2 = r2 + 12. */
" stm r2, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n" /* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
@ -454,34 +484,45 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n" /* Enable interrupts. */
" \n" " \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " restore_special_regs: \n"
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
" mov lr, r4 \n" /* LR = r4. */ " ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */ " str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " \n"
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " restore_s_context: \n"
" push {r2, r4} \n" " push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r1-r3, lr} \n"
" mov lr, r4 \n" /* LR = r4. */
" lsls r1, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* 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 \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */ " msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -130,6 +138,15 @@
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */ " mrs r1, control \n" /* Obtain current control register value. */
@ -270,7 +287,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */ " sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */ " stmia r1!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
@ -279,6 +295,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */ " mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */ " mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -337,6 +361,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -381,6 +413,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n" /* Save the new top of stack in TCB. */
@ -397,6 +438,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -132,6 +140,15 @@
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */ " ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n" " ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
@ -280,7 +297,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" \n" " \n"
" save_general_regs: \n" " save_general_regs: \n"
" mrs r3, psp \n" " mrs r3, psp \n"
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */ " add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n" " tst lr, #0x10 \n"
@ -290,7 +306,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */ " sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */ " stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
@ -300,6 +315,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */ " mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */ " mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -358,6 +381,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -412,38 +443,37 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r2, psp \n" /* Read PSP in r2. */ " mrs r2, psp \n" /* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n" /* No secure context to save. */
" push {r0-r2, r14} \n" " save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r2, lr} \n"
" mov lr, r3 \n" /* LR = r3. */
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB.*/
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " lsls r3, r3, #25 \n" /* 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 \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */ " str r2, [r1] \n" /* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n" /* r2 = r2 + 12. */
" stm r2, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n" /* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
@ -454,34 +484,45 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n" /* Enable interrupts. */
" \n" " \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " restore_special_regs: \n"
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
" mov lr, r4 \n" /* LR = r4. */ " ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */ " str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " \n"
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " restore_s_context: \n"
" push {r2, r4} \n" " push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r1-r3, lr} \n"
" mov lr, r4 \n" /* LR = r4. */
" lsls r1, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* 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 \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */ " msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -130,6 +138,15 @@
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */ " mrs r1, control \n" /* Obtain current control register value. */
@ -270,7 +287,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */ " sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */ " stmia r1!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
@ -279,6 +295,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */ " mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */ " mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -337,6 +361,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -381,6 +413,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n" /* Save the new top of stack in TCB. */
@ -397,6 +438,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -132,6 +140,15 @@
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */ " ldr r3, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
" ldr r4, =xSecureContext \n" " ldr r4, =xSecureContext \n"
" str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */
@ -280,7 +297,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" \n" " \n"
" save_general_regs: \n" " save_general_regs: \n"
" mrs r3, psp \n" " mrs r3, psp \n"
" \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */ " add r3, r3, #0x20 \n" /* Move r3 to location where s0 is saved. */
" tst lr, #0x10 \n" " tst lr, #0x10 \n"
@ -290,7 +306,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r2!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */ " sub r3, r3, #0x20 \n" /* Set r3 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r2!, {r4-r11} \n" /* Store r4-r11. */ " stmia r2!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r3, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r2!, {r4-r11} \n" /* Store the hardware saved context. */
@ -300,6 +315,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r4, psplim \n" /* r4 = PSPLIM. */ " mrs r4, psplim \n" /* r4 = PSPLIM. */
" mrs r5, control \n" /* r5 = CONTROL. */ " mrs r5, control \n" /* r5 = CONTROL. */
" stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r2!, {r0, r3-r5, lr} \n" /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_1 \n"
" mrs r5, PAC_KEY_P_2 \n"
" mrs r6, PAC_KEY_P_3 \n"
" stmia r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r2, [r1] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -358,6 +381,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */ " ldr r2, [r1] \n" /* r2 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r2!, {r3-r6} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_2, r5 \n"
" msr PAC_KEY_P_3, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ " ldmdb r2!, {r0, r3-r5, lr} \n" /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
" msr psp, r3 \n" " msr psp, r3 \n"
" msr psplim, r4 \n" " msr psplim, r4 \n"
@ -412,38 +443,37 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r2, psp \n" /* Read PSP in r2. */ " mrs r2, psp \n" /* Read PSP in r2. */
" \n" " \n"
" cbz r0, save_ns_context \n" /* No secure context to save. */ " cbz r0, save_ns_context \n" /* No secure context to save. */
" push {r0-r2, r14} \n" " save_s_context: \n"
" push {r0-r2, lr} \n"
" bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_SaveContext \n" /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r0-r3} \n" /* LR is now in r3. */ " pop {r0-r2, lr} \n"
" mov lr, r3 \n" /* LR = r3. */
" lsls r1, r3, #25 \n" /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
" bpl save_ns_context \n" /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
" \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB.*/
" subs r2, r2, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */
" str r2, [r1] \n" /* Save the new top of stack in TCB. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" b select_next_task \n"
" \n" " \n"
" save_ns_context: \n" " save_ns_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " mov r3, lr \n" /* r3 = LR (EXC_RETURN). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " lsls r3, r3, #25 \n" /* 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 \n" /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
" \n"
" save_general_regs: \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */ " vstmdbeq r2!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" subs r2, r2, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ " stmdb r2!, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" \n"
" save_special_regs: \n"
" mrs r3, psplim \n" /* r3 = PSPLIM. */
" stmdb r2!, {r0, r3, lr} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
" mrs r3, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_1 \n"
" mrs r6, PAC_KEY_P_0 \n"
" stmdb r2!, {r3-r6} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" \n"
" str r2, [r1] \n" /* Save the new top of stack in TCB. */ " str r2, [r1] \n" /* Save the new top of stack in TCB. */
" adds r2, r2, #12 \n" /* r2 = r2 + 12. */
" stm r2, {r4-r11} \n" /* Store the registers that are not saved automatically. */
" mrs r1, psplim \n" /* r1 = PSPLIM. */
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" subs r2, r2, #12 \n" /* r2 = r2 - 12. */
" stmia r2!, {r0, r1, r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
@ -454,34 +484,45 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r0, #0 \n" /* r0 = 0. */ " mov r0, #0 \n" /* r0 = 0. */
" msr basepri, r0 \n" /* Enable interrupts. */ " msr basepri, r0 \n" /* Enable interrupts. */
" \n" " \n"
" restore_context: \n"
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " ldr r1, [r3] \n" /* Read pxCurrentTCB. */
" ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */ " ldr r2, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
" \n" " \n"
" ldmia r2!, {r0, r1, r4} \n" /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ " restore_special_regs: \n"
" msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
" mov lr, r4 \n" /* LR = r4. */ " ldmia r2!, {r3-r6} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r3 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_1, r5 \n"
" msr PAC_KEY_P_0, r6 \n"
" clrm {r3-r6} \n" /* Clear r3-r6. */
#endif /* configENABLE_PAC */
" ldmia r2!, {r0, r3, lr} \n" /* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
" msr psplim, r3 \n" /* Restore the PSPLIM register value for the task. */
" ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ " ldr r3, =xSecureContext \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */
" str r0, [r3] \n" /* Restore the task's xSecureContext. */ " str r0, [r3] \n" /* Restore the task's xSecureContext. */
" cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */
" ldr r3, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " \n"
" ldr r1, [r3] \n" /* Read pxCurrentTCB. */ " restore_s_context: \n"
" push {r2, r4} \n" " push {r1-r3, lr} \n"
" bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ " bl SecureContext_LoadContext \n" /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
" pop {r2, r4} \n" " pop {r1-r3, lr} \n"
" mov lr, r4 \n" /* LR = r4. */
" lsls r1, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */
" bx lr \n"
" \n" " \n"
" restore_ns_context: \n" " restore_ns_context: \n"
" mov r0, lr \n" /* r0 = LR (EXC_RETURN). */
" lsls r0, r0, #25 \n" /* 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 \n" /* r0 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used to store the stack frame. */
" \n"
" restore_general_regs: \n"
" ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ " ldmia r2!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
" it eq \n" " it eq \n"
" vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */ " vldmiaeq r2!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" restore_context_done: \n"
" msr psp, r2 \n" /* Remember the new top of stack for the task. */ " msr psp, r2 \n" /* Remember the new top of stack for the task. */
" bx lr \n" " bx lr \n"
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -100,6 +100,14 @@
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs_first_task: \n" " restore_special_regs_first_task: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -130,6 +138,15 @@
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r1-r4} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r1 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r2 \n"
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_0, r4 \n"
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */ " msr psplim, r1 \n" /* Set this task's PSPLIM value. */
" mrs r1, control \n" /* Obtain current control register value. */ " mrs r1, control \n" /* Obtain current control register value. */
@ -270,7 +287,6 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */ " vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */ " sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
" \n"
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */ " stmia r1!, {r4-r11} \n" /* Store r4-r11. */
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */ " ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */ " stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
@ -279,6 +295,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mrs r3, psplim \n" /* r3 = PSPLIM. */ " mrs r3, psplim \n" /* r3 = PSPLIM. */
" mrs r4, control \n" /* r4 = CONTROL. */ " mrs r4, control \n" /* r4 = CONTROL. */
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ " stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
" mrs r2, PAC_KEY_P_0 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_2 \n"
" mrs r5, PAC_KEY_P_3 \n"
" stmia r1!, {r2-r5} \n" /* Store the task's dedicated PAC key on the task's context. */
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */ " str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
" \n" " \n"
" select_next_task: \n" " select_next_task: \n"
@ -337,6 +361,14 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */ " ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
" \n" " \n"
" restore_special_regs: \n" " restore_special_regs: \n"
#if ( configENABLE_PAC == 1 )
" ldmdb r1!, {r2-r5} \n" /* Read task's dedicated PAC key from the task's context. */
" msr PAC_KEY_P_0, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_1, r3 \n"
" msr PAC_KEY_P_2, r4 \n"
" msr PAC_KEY_P_3, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ " ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
" msr psp, r2 \n" " msr psp, r2 \n"
" msr psplim, r3 \n" " msr psplim, r3 \n"
@ -381,6 +413,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
" stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" mrs r1, PAC_KEY_P_3 \n" /* Read task's dedicated PAC key from the PAC key registers. */
" mrs r2, PAC_KEY_P_2 \n"
" mrs r3, PAC_KEY_P_1 \n"
" mrs r4, PAC_KEY_P_0 \n"
" stmdb r0!, {r1-r4} \n" /* Store the task's dedicated PAC key on the stack. */
" clrm {r1-r4} \n" /* Clear r1-r4. */
#endif /* configENABLE_PAC */
" \n"
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ " ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" str r0, [r1] \n" /* Save the new top of stack in TCB. */ " str r0, [r1] \n" /* Save the new top of stack in TCB. */
@ -397,6 +438,15 @@ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __att
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */ " ldr r1, [r2] \n" /* Read pxCurrentTCB. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
" \n" " \n"
#if ( configENABLE_PAC == 1 )
" ldmia r0!, {r2-r5} \n" /* Read task's dedicated PAC key from stack. */
" msr PAC_KEY_P_3, r2 \n" /* Write the task's dedicated PAC key to the PAC key registers. */
" msr PAC_KEY_P_2, r3 \n"
" msr PAC_KEY_P_1, r4 \n"
" msr PAC_KEY_P_0, r5 \n"
" clrm {r2-r5} \n" /* Clear r2-r5. */
#endif /* configENABLE_PAC */
" \n"
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
" \n" " \n"
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -152,6 +152,14 @@ vRestoreContextOfFirstTask:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -177,6 +185,15 @@ vRestoreContextOfFirstTask:
ldr r3, [r2] /* Read 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. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
@ -271,6 +288,15 @@ PendSV_Handler:
mrs r4, psplim /* r4 = PSPLIM. */ mrs r4, psplim /* r4 = PSPLIM. */
mrs r5, control /* r5 = CONTROL. */ mrs r5, control /* r5 = CONTROL. */
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_1
mrs r5, PAC_KEY_P_2
mrs r6, PAC_KEY_P_3
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -329,6 +355,14 @@ PendSV_Handler:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -374,38 +408,37 @@ PendSV_Handler:
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} save_s_context:
push {r0-r2, lr}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r2, lr}
mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */
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. */
b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ mov r3, lr /* r3 = LR. */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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 /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
save_general_regs:
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
save_special_regs:
mrs r3, psplim /* r3 = PSPLIM. */
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_1
mrs r6, PAC_KEY_P_0
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */
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. */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -416,34 +449,45 @@ PendSV_Handler:
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
restore_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ restore_special_regs:
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
mov lr, r4 /* LR = r4. */ ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_1, r5
msr PAC_KEY_P_0, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's 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. */ 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. */ restore_s_context:
push {r2, r4} push {r1-r3, lr}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r1-r3, lr}
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
restore_ns_context: 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:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
restore_context_done:
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -142,6 +142,14 @@ vRestoreContextOfFirstTask:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -165,6 +173,15 @@ vRestoreContextOfFirstTask:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
mrs r1, control /* Obtain current control register value. */ mrs r1, control /* Obtain current control register value. */
@ -233,7 +250,6 @@ PendSV_Handler:
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */ vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */ sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
stmia r1!, {r4-r11} /* Store r4-r11. */ stmia r1!, {r4-r11} /* Store r4-r11. */
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */ ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
stmia r1!, {r4-r11} /* Store the hardware saved context. */ stmia r1!, {r4-r11} /* Store the hardware saved context. */
@ -242,6 +258,15 @@ PendSV_Handler:
mrs r3, psplim /* r3 = PSPLIM. */ mrs r3, psplim /* r3 = PSPLIM. */
mrs r4, control /* r4 = CONTROL. */ mrs r4, control /* r4 = CONTROL. */
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_3
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */ str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -300,6 +325,14 @@ PendSV_Handler:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -335,6 +368,15 @@ PendSV_Handler:
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#if ( configENABLE_PAC == 1 )
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r2, PAC_KEY_P_2
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_0
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
@ -351,6 +393,15 @@ PendSV_Handler:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r3
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_0, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -152,6 +152,14 @@ vRestoreContextOfFirstTask:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -177,6 +185,15 @@ vRestoreContextOfFirstTask:
ldr r3, [r2] /* Read 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. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
@ -271,6 +288,15 @@ PendSV_Handler:
mrs r4, psplim /* r4 = PSPLIM. */ mrs r4, psplim /* r4 = PSPLIM. */
mrs r5, control /* r5 = CONTROL. */ mrs r5, control /* r5 = CONTROL. */
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_1
mrs r5, PAC_KEY_P_2
mrs r6, PAC_KEY_P_3
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -329,6 +355,14 @@ PendSV_Handler:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -374,38 +408,37 @@ PendSV_Handler:
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} save_s_context:
push {r0-r2, lr}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r2, lr}
mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */
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. */
b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ mov r3, lr /* r3 = LR. */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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 /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
save_general_regs:
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
save_special_regs:
mrs r3, psplim /* r3 = PSPLIM. */
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_1
mrs r6, PAC_KEY_P_0
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */
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. */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -416,34 +449,45 @@ PendSV_Handler:
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
restore_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ restore_special_regs:
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
mov lr, r4 /* LR = r4. */ ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_1, r5
msr PAC_KEY_P_0, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's 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. */ 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. */ restore_s_context:
push {r2, r4} push {r1-r3, lr}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r1-r3, lr}
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
restore_ns_context: 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:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
restore_context_done:
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -142,6 +142,14 @@ vRestoreContextOfFirstTask:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -165,6 +173,15 @@ vRestoreContextOfFirstTask:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
mrs r1, control /* Obtain current control register value. */ mrs r1, control /* Obtain current control register value. */
@ -233,7 +250,6 @@ PendSV_Handler:
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */ vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */ sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
stmia r1!, {r4-r11} /* Store r4-r11. */ stmia r1!, {r4-r11} /* Store r4-r11. */
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */ ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
stmia r1!, {r4-r11} /* Store the hardware saved context. */ stmia r1!, {r4-r11} /* Store the hardware saved context. */
@ -242,6 +258,15 @@ PendSV_Handler:
mrs r3, psplim /* r3 = PSPLIM. */ mrs r3, psplim /* r3 = PSPLIM. */
mrs r4, control /* r4 = CONTROL. */ mrs r4, control /* r4 = CONTROL. */
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_3
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */ str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -300,6 +325,14 @@ PendSV_Handler:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -335,6 +368,15 @@ PendSV_Handler:
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#if ( configENABLE_PAC == 1 )
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r2, PAC_KEY_P_2
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_0
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
@ -351,6 +393,15 @@ PendSV_Handler:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r3
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_0, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -152,6 +152,14 @@ vRestoreContextOfFirstTask:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -177,6 +185,15 @@ vRestoreContextOfFirstTask:
ldr r3, [r2] /* Read 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. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
@ -271,6 +288,15 @@ PendSV_Handler:
mrs r4, psplim /* r4 = PSPLIM. */ mrs r4, psplim /* r4 = PSPLIM. */
mrs r5, control /* r5 = CONTROL. */ mrs r5, control /* r5 = CONTROL. */
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_1
mrs r5, PAC_KEY_P_2
mrs r6, PAC_KEY_P_3
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -329,6 +355,14 @@ PendSV_Handler:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -374,38 +408,37 @@ PendSV_Handler:
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} save_s_context:
push {r0-r2, lr}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r2, lr}
mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */
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. */
b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ mov r3, lr /* r3 = LR. */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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 /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
save_general_regs:
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
save_special_regs:
mrs r3, psplim /* r3 = PSPLIM. */
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_1
mrs r6, PAC_KEY_P_0
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */
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. */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -416,34 +449,45 @@ PendSV_Handler:
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
restore_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ restore_special_regs:
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
mov lr, r4 /* LR = r4. */ ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_1, r5
msr PAC_KEY_P_0, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's 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. */ 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. */ restore_s_context:
push {r2, r4} push {r1-r3, lr}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r1-r3, lr}
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
restore_ns_context: 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:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
restore_context_done:
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -142,6 +142,14 @@ vRestoreContextOfFirstTask:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -165,6 +173,15 @@ vRestoreContextOfFirstTask:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
mrs r1, control /* Obtain current control register value. */ mrs r1, control /* Obtain current control register value. */
@ -233,7 +250,6 @@ PendSV_Handler:
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */ vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */ sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
stmia r1!, {r4-r11} /* Store r4-r11. */ stmia r1!, {r4-r11} /* Store r4-r11. */
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */ ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
stmia r1!, {r4-r11} /* Store the hardware saved context. */ stmia r1!, {r4-r11} /* Store the hardware saved context. */
@ -242,6 +258,15 @@ PendSV_Handler:
mrs r3, psplim /* r3 = PSPLIM. */ mrs r3, psplim /* r3 = PSPLIM. */
mrs r4, control /* r4 = CONTROL. */ mrs r4, control /* r4 = CONTROL. */
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_3
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */ str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -300,6 +325,14 @@ PendSV_Handler:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -335,6 +368,15 @@ PendSV_Handler:
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#if ( configENABLE_PAC == 1 )
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r2, PAC_KEY_P_2
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_0
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
@ -351,6 +393,15 @@ PendSV_Handler:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r3
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_0, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -152,6 +152,14 @@ vRestoreContextOfFirstTask:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -177,6 +185,15 @@ vRestoreContextOfFirstTask:
ldr r3, [r2] /* Read 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. */ ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
ldr r4, =xSecureContext ldr r4, =xSecureContext
str r1, [r4] /* Set xSecureContext to this task's value for the same. */ str r1, [r4] /* Set xSecureContext to this task's value for the same. */
@ -271,6 +288,15 @@ PendSV_Handler:
mrs r4, psplim /* r4 = PSPLIM. */ mrs r4, psplim /* r4 = PSPLIM. */
mrs r5, control /* r5 = CONTROL. */ mrs r5, control /* r5 = CONTROL. */
stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r2!, {r0, r3-r5, lr} /* Store xSecureContext, original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_1
mrs r5, PAC_KEY_P_2
mrs r6, PAC_KEY_P_3
stmia r2!, {r3-r6} /* Store the task's dedicated PAC key on the task's context. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */ str r2, [r1] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -329,6 +355,14 @@ PendSV_Handler:
ldr r2, [r1] /* r2 = Location of saved context in TCB. */ ldr r2, [r1] /* r2 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r2!, {r3-r6} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_2, r5
msr PAC_KEY_P_3, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */ ldmdb r2!, {r0, r3-r5, lr} /* r0 = xSecureContext, r3 = original PSP, r4 = PSPLIM, r5 = CONTROL, LR restored. */
msr psp, r3 msr psp, r3
msr psplim, r4 msr psplim, r4
@ -374,38 +408,37 @@ PendSV_Handler:
mrs r2, psp /* Read PSP in r2. */ mrs r2, psp /* Read PSP in r2. */
cbz r0, save_ns_context /* No secure context to save. */ cbz r0, save_ns_context /* No secure context to save. */
push {r0-r2, r14} save_s_context:
push {r0-r2, lr}
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r0-r3} /* LR is now in r3. */ pop {r0-r2, lr}
mov lr, r3 /* LR = r3. */
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */
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. */
b select_next_task
save_ns_context: save_ns_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ mov r3, lr /* r3 = LR. */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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 /* If r3 < 0 ==> Bit[6] in EXC_RETURN is 1 ==> secure stack was used. */
save_general_regs:
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */ vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ stmdb r2!, {r4-r11} /* Store the registers that are not saved automatically. */
save_special_regs:
mrs r3, psplim /* r3 = PSPLIM. */
stmdb r2!, {r0, r3, lr} /* Store xSecureContext, PSPLIM and LR on the stack. */
#if ( configENABLE_PAC == 1 )
mrs r3, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_1
mrs r6, PAC_KEY_P_0
stmdb r2!, {r3-r6} /* Store the task's dedicated PAC key on the stack. */
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
str r2, [r1] /* Save the new top of stack in TCB. */ str r2, [r1] /* Save the new top of stack in TCB. */
adds r2, r2, #12 /* r2 = r2 + 12. */
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
mrs r1, psplim /* r1 = PSPLIM. */
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. */
select_next_task: select_next_task:
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -416,34 +449,45 @@ PendSV_Handler:
mov r0, #0 /* r0 = 0. */ mov r0, #0 /* r0 = 0. */
msr basepri, r0 /* Enable interrupts. */ msr basepri, r0 /* Enable interrupts. */
restore_context:
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r3] /* Read pxCurrentTCB. */ 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. */ ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */ restore_special_regs:
msr psplim, r1 /* Restore the PSPLIM register value for the task. */ #if ( configENABLE_PAC == 1 )
mov lr, r4 /* LR = r4. */ ldmia r2!, {r3-r6} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r3 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_1, r5
msr PAC_KEY_P_0, r6
clrm {r3-r6} /* Clear r3-r6. */
#endif /* configENABLE_PAC */
ldmia r2!, {r0, r3, lr} http://files.iar.com/ftp/pub/box/bxarm-9.60.3.deb/* Read from stack - r0 = xSecureContext, r3 = PSPLIM and LR restored. */
msr psplim, r3 /* Restore the PSPLIM register value for the task. */
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */ ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
str r0, [r3] /* Restore the task's 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. */ 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. */ restore_s_context:
push {r2, r4} push {r1-r3, lr}
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */ bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
pop {r2, r4} pop {r1-r3, lr}
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
restore_ns_context: 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:
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */ ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */ tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
it eq it eq
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */ vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
restore_context_done:
msr psp, r2 /* Remember the new top of stack for the task. */ msr psp, r2 /* Remember the new top of stack for the task. */
bx lr bx lr

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */

View file

@ -229,6 +229,7 @@ typedef void ( * portISR_t )( void );
#define portMPU_RLAR_REGION_ENABLE ( 1UL ) #define portMPU_RLAR_REGION_ENABLE ( 1UL )
#if ( portARMV8M_MINOR_VERSION >= 1 ) #if ( portARMV8M_MINOR_VERSION >= 1 )
/* Enable Privileged eXecute Never MPU attribute for the selected memory /* Enable Privileged eXecute Never MPU attribute for the selected memory
* region. */ * region. */
#define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL ) #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
@ -1212,6 +1213,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __syscalls_flash_start__; extern uint32_t * __syscalls_flash_start__;
@ -1282,6 +1284,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
* point (i.e. the caller of the MPU_<API>). We need to restore it * point (i.e. the caller of the MPU_<API>). We need to restore it
* when we exit from the system call. */ * when we exit from the system call. */
pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ]; pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
/* Store the value of the PSPLIM register before the SVC was raised. /* Store the value of the PSPLIM register before the SVC was raised.
* We need to restore it when we exit from the system call. */ * We need to restore it when we exit from the system call. */
#if ( portUSE_PSPLIM_REGISTER == 1 ) #if ( portUSE_PSPLIM_REGISTER == 1 )
@ -1300,6 +1303,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
/* Start executing the system call upon returning from this handler. */ /* Start executing the system call upon returning from this handler. */
pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ]; pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
/* Raise a request to exit from the system call upon finishing the /* Raise a request to exit from the system call upon finishing the
* system call. */ * system call. */
pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit; pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
@ -1359,6 +1363,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
uint32_t ulStackFrameSize, ulSystemCallLocation, i; uint32_t ulStackFrameSize, ulSystemCallLocation, i;
#if defined( __ARMCC_VERSION ) #if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being /* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */ * exported from linker scripts. */
extern uint32_t * __privileged_functions_start__; extern uint32_t * __privileged_functions_start__;
@ -1582,6 +1587,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */ #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
xMPUSettings->ulContext[ ulIndex ] = ulTaskPacKey[ i ];
ulIndex++;
}
}
#endif /* configENABLE_PAC */
return &( xMPUSettings->ulContext[ ulIndex ] ); return &( xMPUSettings->ulContext[ ulIndex ] );
} }
@ -1664,6 +1683,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
} }
#endif /* portPRELOAD_REGISTERS */ #endif /* portPRELOAD_REGISTERS */
#if ( configENABLE_PAC == 1 )
{
uint32_t ulTaskPacKey[ 4 ], i;
vApplicationGenerateTaskRandomPacKey( &( ulTaskPacKey[ 0 ] ) );
for( i = 0; i < 4; i++ )
{
pxTopOfStack--;
*pxTopOfStack = ulTaskPacKey[ i ];
}
}
#endif /* configENABLE_PAC */
return pxTopOfStack; return pxTopOfStack;
} }

View file

@ -142,6 +142,14 @@ vRestoreContextOfFirstTask:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs_first_task: restore_special_regs_first_task:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -165,6 +173,15 @@ vRestoreContextOfFirstTask:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r1-r4} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r1 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r2
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_0, r4
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
msr psplim, r1 /* Set this task's PSPLIM value. */ msr psplim, r1 /* Set this task's PSPLIM value. */
mrs r1, control /* Obtain current control register value. */ mrs r1, control /* Obtain current control register value. */
@ -233,7 +250,6 @@ PendSV_Handler:
vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */ vstmiaeq r1!, {s0-s16} /* Store hardware saved FP context. */
sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */ sub r2, r2, #0x20 /* Set r2 back to the location of hardware saved context. */
#endif /* configENABLE_FPU || configENABLE_MVE */ #endif /* configENABLE_FPU || configENABLE_MVE */
stmia r1!, {r4-r11} /* Store r4-r11. */ stmia r1!, {r4-r11} /* Store r4-r11. */
ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */ ldmia r2, {r4-r11} /* Copy the hardware saved context into r4-r11. */
stmia r1!, {r4-r11} /* Store the hardware saved context. */ stmia r1!, {r4-r11} /* Store the hardware saved context. */
@ -242,6 +258,15 @@ PendSV_Handler:
mrs r3, psplim /* r3 = PSPLIM. */ mrs r3, psplim /* r3 = PSPLIM. */
mrs r4, control /* r4 = CONTROL. */ mrs r4, control /* r4 = CONTROL. */
stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */ stmia r1!, {r2-r4, lr} /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
#if ( configENABLE_PAC == 1 )
mrs r2, PAC_KEY_P_0 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_2
mrs r5, PAC_KEY_P_3
stmia r1!, {r2-r5} /* Store the task's dedicated PAC key on the task's context. */
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */ str r1, [r0] /* Save the location from where the context should be restored as the first member of TCB. */
select_next_task: select_next_task:
@ -300,6 +325,14 @@ PendSV_Handler:
ldr r1, [r0] /* r1 = Location of saved context in TCB. */ ldr r1, [r0] /* r1 = Location of saved context in TCB. */
restore_special_regs: restore_special_regs:
#if ( configENABLE_PAC == 1 )
ldmdb r1!, {r2-r5} /* Read task's dedicated PAC key from the task's context. */
msr PAC_KEY_P_0, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_1, r3
msr PAC_KEY_P_2, r4
msr PAC_KEY_P_3, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */ ldmdb r1!, {r2-r4, lr} /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
msr psp, r2 msr psp, r2
msr psplim, r3 msr psplim, r3
@ -335,6 +368,15 @@ PendSV_Handler:
mov r3, lr /* r3 = LR/EXC_RETURN. */ mov r3, lr /* r3 = LR/EXC_RETURN. */
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */ stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
#if ( configENABLE_PAC == 1 )
mrs r1, PAC_KEY_P_3 /* Read task's dedicated PAC key from the PAC key registers. */
mrs r2, PAC_KEY_P_2
mrs r3, PAC_KEY_P_1
mrs r4, PAC_KEY_P_0
stmdb r0!, {r1-r4} /* Store the task's dedicated PAC key on the stack. */
clrm {r1-r4} /* Clear r1-r4. */
#endif /* configENABLE_PAC */
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
str r0, [r1] /* Save the new top of stack in TCB. */ str r0, [r1] /* Save the new top of stack in TCB. */
@ -351,6 +393,15 @@ PendSV_Handler:
ldr r1, [r2] /* Read pxCurrentTCB. */ ldr r1, [r2] /* Read pxCurrentTCB. */
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
#if ( configENABLE_PAC == 1 )
ldmia r0!, {r2-r5} /* Read task's dedicated PAC key from stack. */
msr PAC_KEY_P_3, r2 /* Write the task's dedicated PAC key to the PAC key registers. */
msr PAC_KEY_P_2, r3
msr PAC_KEY_P_1, r4
msr PAC_KEY_P_0, r5
clrm {r2-r5} /* Clear r2-r5. */
#endif /* configENABLE_PAC */
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )

View file

@ -1,6 +1,8 @@
/* /*
* FreeRTOS Kernel <DEVELOPMENT BRANCH> * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2024 Arm Limited and/or its affiliates
* <open-source-office@arm.com>
* *
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
* *
@ -125,6 +127,18 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
#endif /* configENABLE_MPU */ #endif /* configENABLE_MPU */
#if ( configENABLE_PAC == 1 )
/**
* @brief Generates 128-bit task's random PAC key.
*
* @param[out] pulTaskPacKey Pointer to a 4-word (128-bits) array to be
* filled with a 128-bit random number.
*/
void vApplicationGenerateTaskRandomPacKey( uint32_t * pulTaskPacKey );
#endif /* configENABLE_PAC */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/** /**
@ -203,6 +217,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2. #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 #endif
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
* pxTopOfStack member of TCB points to the context location in TCB. We,
* therefore, need to read PSP to find the task's current top of stack. */
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
/** /**
* @brief System call stack. * @brief System call stack.
*/ */
@ -223,7 +242,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+------------------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><-----------------------------><-----------><---->
* 16 16 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 70
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +-----------+---------------+----------+-----------------+------------------------------+-----+ * +-----------+---------------+----------+-----------------+------------------------------+-----+
@ -236,7 +268,20 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 54 #define MAX_CONTEXT_SIZE 54
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | | | PC, xPSR | EXC_RETURN | | |
* +-----------+---------------+----------+-----------------+----------------------+------------+-----+
*
* <-----------><--------------><---------><----------------><---------------------><-----------><---->
* 16 16 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 69
#else /* if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
/* /*
* +-----------+---------------+----------+-----------------+----------------------+-----+ * +-----------+---------------+----------+-----------------+----------------------+-----+
@ -249,11 +294,24 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 53 #define MAX_CONTEXT_SIZE 53
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
#if ( configENABLE_TRUSTZONE == 1 ) #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+------------------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | TaskPacKey | |
* | | PC, xPSR | CONTROL, EXC_RETURN | | |
* +----------+-----------------+------------------------------+------------+-----+
*
* <---------><----------------><------------------------------><-----------><---->
* 8 8 5 16 1
*/
#define MAX_CONTEXT_SIZE 38
#elif ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 0 ) )
/* /*
* +----------+-----------------+------------------------------+-----+ * +----------+-----------------+------------------------------+-----+
@ -266,6 +324,19 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 22 #define MAX_CONTEXT_SIZE 22
#elif ( ( configENABLE_TRUSTZONE == 0 ) && ( configENABLE_PAC == 1 ) )
/*
* +----------+-----------------+----------------------+------------+-----+
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | TaskPacKey | |
* | | PC, xPSR | EXC_RETURN | | |
* +----------+-----------------+----------------------+------------+-----+
*
* <---------><----------------><----------------------><-----------><---->
* 8 8 4 16 1
*/
#define MAX_CONTEXT_SIZE 37
#else /* #if( configENABLE_TRUSTZONE == 1 ) */ #else /* #if( configENABLE_TRUSTZONE == 1 ) */
/* /*
@ -279,7 +350,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
*/ */
#define MAX_CONTEXT_SIZE 21 #define MAX_CONTEXT_SIZE 21
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */ #endif /* #if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) ) */
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */ #endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */