Skip to content

Commit 3f23eab

Browse files
committed
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> Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
1 parent 029545f commit 3f23eab

File tree

23 files changed

+380
-259
lines changed

23 files changed

+380
-259
lines changed

include/portable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
#define portBASE_TYPE_EXIT_CRITICAL() taskEXIT_CRITICAL()
9494
#endif
9595

96+
#ifndef portGET_CURRENT_TOP_OF_STACK
97+
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { pxCurrentTopOfStack = ( StackType_t * ) pxCurrentTCB->pxTopOfStack; }
98+
#endif
99+
96100
#ifndef configSTACK_DEPTH_TYPE
97101
#define configSTACK_DEPTH_TYPE StackType_t
98102
#endif

include/stack_macros.h

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@
5757

5858
/* Only the current stack state is to be checked. */
5959
#define taskCHECK_FOR_STACK_OVERFLOW() \
60-
do { \
60+
do \
61+
{ \
62+
StackType_t * pxCurrentTopOfStack; \
63+
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
64+
\
6165
/* Is the currently saved stack pointer within the stack limit? */ \
62-
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
66+
if( pxCurrentTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
6367
{ \
6468
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
6569
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
@@ -72,36 +76,42 @@
7276
#if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
7377

7478
/* Only the current stack state is to be checked. */
75-
#define taskCHECK_FOR_STACK_OVERFLOW() \
76-
do { \
77-
\
78-
/* Is the currently saved stack pointer within the stack limit? */ \
79-
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
80-
{ \
81-
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
82-
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
83-
} \
79+
#define taskCHECK_FOR_STACK_OVERFLOW() \
80+
do \
81+
{ \
82+
StackType_t * pxCurrentTopOfStack; \
83+
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
84+
\
85+
/* Is the currently saved stack pointer within the stack limit? */ \
86+
if( pxCurrentTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
87+
{ \
88+
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
89+
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
90+
} \
8491
} while( 0 )
8592

8693
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
8794
/*-----------------------------------------------------------*/
8895

8996
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
9097

91-
#define taskCHECK_FOR_STACK_OVERFLOW() \
92-
do { \
93-
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
94-
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
95-
\
96-
if( ( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) || \
97-
( pulStack[ 0 ] != ulCheckValue ) || \
98-
( pulStack[ 1 ] != ulCheckValue ) || \
99-
( pulStack[ 2 ] != ulCheckValue ) || \
100-
( pulStack[ 3 ] != ulCheckValue ) ) \
101-
{ \
102-
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
103-
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
104-
} \
98+
#define taskCHECK_FOR_STACK_OVERFLOW() \
99+
do \
100+
{ \
101+
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
102+
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
103+
StackType_t * pxCurrentTopOfStack; \
104+
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
105+
\
106+
if( ( pxCurrentTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) || \
107+
( pulStack[ 0 ] != ulCheckValue ) || \
108+
( pulStack[ 1 ] != ulCheckValue ) || \
109+
( pulStack[ 2 ] != ulCheckValue ) || \
110+
( pulStack[ 3 ] != ulCheckValue ) ) \
111+
{ \
112+
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
113+
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
114+
} \
105115
} while( 0 )
106116

107117
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
@@ -110,18 +120,20 @@
110120
#if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
111121

112122
#define taskCHECK_FOR_STACK_OVERFLOW() \
113-
do { \
123+
do \
124+
{ \
114125
int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
115126
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
116127
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
117128
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
118129
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
119130
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
120-
\
131+
StackType_t * pxCurrentTopOfStack; \
132+
portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ); \
121133
\
122134
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
123135
\
124-
if( ( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) || \
136+
if( ( pxCurrentTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) || \
125137
( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) ) \
126138
{ \
127139
char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \

portable/ARMv8M/non_secure/portmacrocommon.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
202202

203203
#if ( configENABLE_MPU == 1 )
204204

205-
/**
206-
* @brief Settings to define an MPU region.
207-
*/
205+
/**
206+
* @brief Settings to define an MPU region.
207+
*/
208208
typedef struct MPURegionSettings
209209
{
210210
uint32_t ulRBAR; /**< RBAR for the region. */
@@ -217,9 +217,14 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
217217
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
218218
#endif
219219

220-
/**
221-
* @brief System call stack.
222-
*/
220+
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
221+
* pxTopOfStack member of TCB points to the context location in TCB. We,
222+
* therefore, need to read PSP to find the task's current top of stack. */
223+
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
224+
225+
/**
226+
* @brief System call stack.
227+
*/
223228
typedef struct SYSTEM_CALL_STACK_INFO
224229
{
225230
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
@@ -232,9 +237,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
232237

233238
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
234239

235-
/**
236-
* @brief MPU settings as stored in the TCB.
237-
*/
240+
/**
241+
* @brief MPU settings as stored in the TCB.
242+
*/
238243
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
239244

240245
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
@@ -348,11 +353,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
348353

349354
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
350355

351-
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
356+
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
352357
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
353358
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
354359

355-
/* Size of an Access Control List (ACL) entry in bits. */
360+
/* Size of an Access Control List (ACL) entry in bits. */
356361
#define portACL_ENTRY_SIZE_BITS ( 32U )
357362

358363
typedef struct MPU_SETTINGS

portable/GCC/ARM_CM23/non_secure/portmacrocommon.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
202202

203203
#if ( configENABLE_MPU == 1 )
204204

205-
/**
206-
* @brief Settings to define an MPU region.
207-
*/
205+
/**
206+
* @brief Settings to define an MPU region.
207+
*/
208208
typedef struct MPURegionSettings
209209
{
210210
uint32_t ulRBAR; /**< RBAR for the region. */
@@ -217,9 +217,14 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
217217
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
218218
#endif
219219

220-
/**
221-
* @brief System call stack.
222-
*/
220+
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
221+
* pxTopOfStack member of TCB points to the context location in TCB. We,
222+
* therefore, need to read PSP to find the task's current top of stack. */
223+
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
224+
225+
/**
226+
* @brief System call stack.
227+
*/
223228
typedef struct SYSTEM_CALL_STACK_INFO
224229
{
225230
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
@@ -232,9 +237,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
232237

233238
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
234239

235-
/**
236-
* @brief MPU settings as stored in the TCB.
237-
*/
240+
/**
241+
* @brief MPU settings as stored in the TCB.
242+
*/
238243
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
239244

240245
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
@@ -348,11 +353,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
348353

349354
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
350355

351-
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
356+
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
352357
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
353358
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
354359

355-
/* Size of an Access Control List (ACL) entry in bits. */
360+
/* Size of an Access Control List (ACL) entry in bits. */
356361
#define portACL_ENTRY_SIZE_BITS ( 32U )
357362

358363
typedef struct MPU_SETTINGS

portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
202202

203203
#if ( configENABLE_MPU == 1 )
204204

205-
/**
206-
* @brief Settings to define an MPU region.
207-
*/
205+
/**
206+
* @brief Settings to define an MPU region.
207+
*/
208208
typedef struct MPURegionSettings
209209
{
210210
uint32_t ulRBAR; /**< RBAR for the region. */
@@ -217,9 +217,14 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
217217
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
218218
#endif
219219

220-
/**
221-
* @brief System call stack.
222-
*/
220+
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
221+
* pxTopOfStack member of TCB points to the context location in TCB. We,
222+
* therefore, need to read PSP to find the task's current top of stack. */
223+
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
224+
225+
/**
226+
* @brief System call stack.
227+
*/
223228
typedef struct SYSTEM_CALL_STACK_INFO
224229
{
225230
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
@@ -232,9 +237,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
232237

233238
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
234239

235-
/**
236-
* @brief MPU settings as stored in the TCB.
237-
*/
240+
/**
241+
* @brief MPU settings as stored in the TCB.
242+
*/
238243
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
239244

240245
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
@@ -348,11 +353,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
348353

349354
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
350355

351-
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
356+
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
352357
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
353358
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
354359

355-
/* Size of an Access Control List (ACL) entry in bits. */
360+
/* Size of an Access Control List (ACL) entry in bits. */
356361
#define portACL_ENTRY_SIZE_BITS ( 32U )
357362

358363
typedef struct MPU_SETTINGS

portable/GCC/ARM_CM33/non_secure/portmacrocommon.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
202202

203203
#if ( configENABLE_MPU == 1 )
204204

205-
/**
206-
* @brief Settings to define an MPU region.
207-
*/
205+
/**
206+
* @brief Settings to define an MPU region.
207+
*/
208208
typedef struct MPURegionSettings
209209
{
210210
uint32_t ulRBAR; /**< RBAR for the region. */
@@ -217,9 +217,14 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
217217
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
218218
#endif
219219

220-
/**
221-
* @brief System call stack.
222-
*/
220+
/* When MPU wrapper v2 is used, the task's context is stored in TCB and
221+
* pxTopOfStack member of TCB points to the context location in TCB. We,
222+
* therefore, need to read PSP to find the task's current top of stack. */
223+
#define portGET_CURRENT_TOP_OF_STACK( pxCurrentTopOfStack ) { __asm volatile ( "mrs %0, psp" : "=r" ( pxCurrentTopOfStack ) ); }
224+
225+
/**
226+
* @brief System call stack.
227+
*/
223228
typedef struct SYSTEM_CALL_STACK_INFO
224229
{
225230
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
@@ -232,9 +237,9 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
232237

233238
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
234239

235-
/**
236-
* @brief MPU settings as stored in the TCB.
237-
*/
240+
/**
241+
* @brief MPU settings as stored in the TCB.
242+
*/
238243
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
239244

240245
#if ( ( configENABLE_TRUSTZONE == 1 ) && ( configENABLE_PAC == 1 ) )
@@ -348,11 +353,11 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P
348353

349354
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
350355

351-
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
356+
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
352357
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
353358
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
354359

355-
/* Size of an Access Control List (ACL) entry in bits. */
360+
/* Size of an Access Control List (ACL) entry in bits. */
356361
#define portACL_ENTRY_SIZE_BITS ( 32U )
357362

358363
typedef struct MPU_SETTINGS

0 commit comments

Comments
 (0)