diff --git a/arch/arm/src/rp2040/rp2040_start.c b/arch/arm/src/rp2040/rp2040_start.c index 498befdd5b0..8952e680408 100644 --- a/arch/arm/src/rp2040/rp2040_start.c +++ b/arch/arm/src/rp2040/rp2040_start.c @@ -51,6 +51,14 @@ const uintptr_t g_idle_topstack = IDLE_STACK; +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +#ifdef CONFIG_STACK_COLORATION +static inline void go_nx_start(void *pv, unsigned int nbytes); +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -69,6 +77,51 @@ const uintptr_t g_idle_topstack = IDLE_STACK; # define showprogress(c) #endif +/**************************************************************************** + * Name: go_nx_start + ****************************************************************************/ + +#ifdef CONFIG_STACK_COLORATION +static inline void go_nx_start(void *pv, unsigned int nbytes) +{ + /* Set the IDLE stack to the stack coloration value then jump to + * nx_start(). We take extreme care here because were currently + * executing on this stack. + * + * We want to avoid sneak stack access generated by the compiler. + * NOTE: this function must be inlined so that SRAM boot can work. + */ + + __asm__ __volatile__ + ( + "\t.global nx_start\n" + "\tlsr %1, %1, #2\n" /* %1 = nwords = nbytes >> 2 */ + "\tcmp %1, #0\n" /* Check (nwords == 0) */ + "\tbeq 2f\n" /* (should not happen) */ + + "\tmov r2, #3\n" + "\tadd %0, %0, #3\n" + "\tbic %0, r2\n" /* %0 = Aligned stackptr */ + "\tldr r2, =0xdeadbeef\n" /* R2 = STACK_COLOR = 0xdeadbeef */ + + "1:\n" /* Top of the loop */ + "\tstr r2, [%0, #0]\n" /* Save stack color word */ + "\tadd %0, %0, #4\n" /* Increment stackptr */ + "\tsub %1, %1, #1\n" /* %1 nwords-- */ + "\tcmp %1, #0\n" /* Check (nwords == 0) */ + "\tbne 1b\n" /* Bottom of the loop */ + + "2:\n" + "\tmov r2, #0\n" + "\tmov r14, r2\n" /* LR = return address (none) */ + "\tbl nx_start\n" /* Branch to nx_start */ + : + : "r" (pv), "r" (nbytes) + : "r2" + ); +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -169,7 +222,14 @@ void __start(void) showprogress('\r'); showprogress('\n'); + +#ifdef CONFIG_STACK_COLORATION + /* Set the IDLE stack to the coloration value and jump into nx_start() */ + + go_nx_start((FAR void *)&_ebss, CONFIG_IDLETHREAD_STACKSIZE); +#else nx_start(); +#endif /* Shouldn't get here */