From dd7b5cb228caab5b7fb8826090948a77de4a51a9 Mon Sep 17 00:00:00 2001 From: Johannes Schock Date: Sat, 26 Sep 2020 19:33:22 +0200 Subject: [PATCH] ARM stack fix: Same boundary calculation in do_stackcheck and stack_color. Use additional space from 8 byte aligning for stack in up_create_stack(). Moved arm_stack_color to arm_checkstack.c. --- arch/arm/src/common/arm_checkstack.c | 85 +++++++++++++++++++++------ arch/arm/src/common/arm_createstack.c | 43 ++++---------- arch/arm/src/common/arm_usestack.c | 14 ++++- 3 files changed, 91 insertions(+), 51 deletions(-) diff --git a/arch/arm/src/common/arm_checkstack.c b/arch/arm/src/common/arm_checkstack.c index 8f624a6b68..c3e51ba8e0 100644 --- a/arch/arm/src/common/arm_checkstack.c +++ b/arch/arm/src/common/arm_checkstack.c @@ -55,17 +55,31 @@ #ifdef CONFIG_STACK_COLORATION +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* 32bit alignment macros */ + +#define INT32_ALIGN_MASK (3) +#define INT32_ALIGN_DOWN(a) ((a) & ~INT32_ALIGN_MASK) +#define INT32_ALIGN_UP(a) (((a) + INT32_ALIGN_MASK) & ~INT32_ALIGN_MASK) + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static size_t do_stackcheck(uintptr_t alloc, size_t size); +static size_t do_stackcheck(FAR void *stackbase, size_t nbytes); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ /**************************************************************************** * Name: do_stackcheck * * Description: - * Determine (approximately) how much stack has been used be searching the + * Determine (approximately) how much stack has been used by searching the * stack memory for a high water mark. That is, the deepest level of the * stack that clobbered some recognizable marker in the stack memory. * @@ -78,26 +92,26 @@ static size_t do_stackcheck(uintptr_t alloc, size_t size); * ****************************************************************************/ -static size_t do_stackcheck(uintptr_t alloc, size_t size) +static size_t do_stackcheck(FAR void *stackbase, size_t nbytes) { - FAR uintptr_t start; - FAR uintptr_t end; + uintptr_t start; + uintptr_t end; FAR uint32_t *ptr; size_t mark; - if (size == 0) + if (nbytes == 0) { return 0; } - /* Get aligned addresses of the top and bottom of the stack */ + /* Take extra care that we do not check outside the stack boundaries */ - start = alloc & ~3; - end = (alloc + size + 3) & ~3; + start = INT32_ALIGN_UP((uintptr_t)stackbase); + end = INT32_ALIGN_DOWN((uintptr_t)stackbase + nbytes); /* Get the adjusted size based on the top and bottom of the stack */ - size = end - start; + nbytes = end - start; /* The ARM uses a push-down stack: the stack grows toward lower addresses * in memory. We need to start at the lowest address in the stack memory @@ -105,7 +119,7 @@ static size_t do_stackcheck(uintptr_t alloc, size_t size) * that does not have the magic value is the high water mark. */ - for (ptr = (FAR uint32_t *)start, mark = (size >> 2); + for (ptr = (FAR uint32_t *)start, mark = (nbytes >> 2); *ptr == STACK_COLOR && mark > 0; ptr++, mark--); @@ -126,7 +140,7 @@ static size_t do_stackcheck(uintptr_t alloc, size_t size) int j; ptr = (FAR uint32_t *)start; - for (i = 0; i < size; i += 4 * 64) + for (i = 0; i < nbytes; i += 4 * 64) { for (j = 0; j < 64; j++) { @@ -157,6 +171,39 @@ static size_t do_stackcheck(uintptr_t alloc, size_t size) * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: arm_stack_color + * + * Description: + * Write a well know value into the stack + * + ****************************************************************************/ + +void arm_stack_color(FAR void *stackbase, size_t nbytes) +{ + uintptr_t start; + uintptr_t end; + size_t nwords; + FAR uint32_t *ptr; + + /* Take extra care that we do not write outside the stack boundaries */ + + start = INT32_ALIGN_UP((uintptr_t)stackbase); + end = INT32_ALIGN_DOWN((uintptr_t)stackbase + nbytes); + + /* Get the adjusted size based on the top and bottom of the stack */ + + nwords = (end - start) >> 2; + ptr = (FAR uint32_t *)start; + + /* Set the entire stack to the coloration value */ + + while (nwords-- > 0) + { + *ptr++ = STACK_COLOR; + } +} + /**************************************************************************** * Name: up_check_stack and friends * @@ -175,8 +222,8 @@ static size_t do_stackcheck(uintptr_t alloc, size_t size) size_t up_check_tcbstack(FAR struct tcb_s *tcb) { - return do_stackcheck((uintptr_t)tcb->adj_stack_ptr - tcb->adj_stack_size, - tcb->adj_stack_size); + return do_stackcheck((FAR void *)((uintptr_t)tcb->adj_stack_ptr - + tcb->adj_stack_size), tcb->adj_stack_size); } ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb) @@ -198,17 +245,17 @@ ssize_t up_check_stack_remain(void) size_t up_check_intstack(void) { #ifdef CONFIG_SMP - return do_stackcheck(arm_intstack_base(), - (CONFIG_ARCH_INTERRUPTSTACK & ~3)); + return do_stackcheck((FAR void *)arm_intstack_base(), + INT32_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK)); #else - return do_stackcheck((uintptr_t)&g_intstackalloc, - (CONFIG_ARCH_INTERRUPTSTACK & ~3)); + return do_stackcheck((FAR void *)&g_intstackalloc, + INT32_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK)); #endif } size_t up_check_intstack_remain(void) { - return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack(); + return INT32_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK) - up_check_intstack(); } #endif diff --git a/arch/arm/src/common/arm_createstack.c b/arch/arm/src/common/arm_createstack.c index 97534cbd9d..dda4b1ff5e 100644 --- a/arch/arm/src/common/arm_createstack.c +++ b/arch/arm/src/common/arm_createstack.c @@ -58,6 +58,12 @@ #define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) #define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) +/* 32bit alignment macros */ + +#define INT32_ALIGN_MASK (3) +#define INT32_ALIGN_DOWN(a) ((a) & ~INT32_ALIGN_MASK) +#define INT32_ALIGN_UP(a) (((a) + INT32_ALIGN_MASK) & ~INT32_ALIGN_MASK) + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -103,10 +109,12 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { size_t alloc_size; + size_t tls_size; - /* Add the size of the TLS information structure and align */ + /* Add the size of the TLS information structure and align. */ - alloc_size = STACK_ALIGN_UP(stack_size + sizeof(struct tls_info_s)); + tls_size = INT32_ALIGN_UP(sizeof(struct tls_info_s)); + alloc_size = STACK_ALIGN_UP(stack_size + tls_size); #ifdef CONFIG_TLS_ALIGNED /* The allocated stack size must not exceed the maximum possible for the @@ -117,10 +125,11 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) if (alloc_size > TLS_MAXSTACK) { alloc_size = TLS_MAXSTACK; - stack_size = alloc_size - sizeof(struct tls_info_s); } #endif + stack_size = alloc_size - tls_size; + /* Is there already a stack allocated of a different size? */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) @@ -209,7 +218,7 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) /* Initialize the TLS data structure */ - memset(tcb->stack_alloc_ptr, 0, sizeof(struct tls_info_s)); + memset(tcb->stack_alloc_ptr, 0, tls_size); #ifdef CONFIG_STACK_COLORATION /* If stack debug is enabled, then fill the stack with a @@ -227,29 +236,3 @@ int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) return ERROR; } - -/**************************************************************************** - * Name: arm_stack_color - * - * Description: - * Write a well know value into the stack - * - ****************************************************************************/ - -#ifdef CONFIG_STACK_COLORATION -void arm_stack_color(FAR void *stackbase, size_t nbytes) -{ - /* Take extra care that we do not write outsize the stack boundaries */ - - uint32_t *stkptr = (uint32_t *)(((uintptr_t)stackbase + 3) & ~3); - uintptr_t stkend = (((uintptr_t)stackbase + nbytes) & ~3); - size_t nwords = (stkend - (uintptr_t)stackbase) >> 2; - - /* Set the entire stack to the coloration value */ - - while (nwords-- > 0) - { - *stkptr++ = STACK_COLOR; - } -} -#endif diff --git a/arch/arm/src/common/arm_usestack.c b/arch/arm/src/common/arm_usestack.c index e0e03b4668..45e28d72db 100644 --- a/arch/arm/src/common/arm_usestack.c +++ b/arch/arm/src/common/arm_usestack.c @@ -53,6 +53,12 @@ #define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) #define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) +/* 32bit alignment macros */ + +#define INT32_ALIGN_MASK (3) +#define INT32_ALIGN_DOWN(a) ((a) & ~INT32_ALIGN_MASK) +#define INT32_ALIGN_UP(a) (((a) + INT32_ALIGN_MASK) & ~INT32_ALIGN_MASK) + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -87,12 +93,16 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) { + size_t tls_size; + #ifdef CONFIG_TLS_ALIGNED /* Make certain that the user provided stack is properly aligned */ DEBUGASSERT(((uintptr_t)stack & TLS_STACK_MASK) == 0); #endif + tls_size = INT32_ALIGN_UP(sizeof(struct tls_info_s)); + /* Is there already a stack allocated? */ if (tcb->stack_alloc_ptr) @@ -125,7 +135,7 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) /* Offset by tls_size */ - stack = (FAR void *)((uintptr_t)stack + sizeof(struct tls_info_s)); + stack = (FAR void *)((uintptr_t)stack + tls_size); /* Is there enough room for at least TLS ? */ @@ -138,7 +148,7 @@ int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) /* Initialize the TLS data structure */ - memset(tcb->stack_alloc_ptr, 0, sizeof(struct tls_info_s)); + memset(tcb->stack_alloc_ptr, 0, tls_size); #ifdef CONFIG_STACK_COLORATION /* If stack debug is enabled, then fill the stack with a