diff --git a/core/thread.c b/core/thread.c index 4332cb9e91..6ce6042e2d 100644 --- a/core/thread.c +++ b/core/thread.c @@ -285,7 +285,7 @@ kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority, thread->sp = thread_stack_init(function, arg, stack, stacksize); #if defined(DEVELHELP) || IS_ACTIVE(SCHED_TEST_STACK) || \ - defined(MODULE_MPU_STACK_GUARD) + defined(MODULE_MPU_STACK_GUARD) || defined(MODULE_CORTEXM_STACK_LIMIT) thread->stack_start = stack; #endif diff --git a/cpu/cortexm_common/Makefile.features b/cpu/cortexm_common/Makefile.features index 6a6ca14f8e..d264693a9d 100644 --- a/cpu/cortexm_common/Makefile.features +++ b/cpu/cortexm_common/Makefile.features @@ -36,6 +36,7 @@ else ifeq ($(CPU_CORE),cortex-m3) RUST_TARGET = thumbv7m-none-eabi else ifeq ($(CPU_CORE),cortex-m33) CPU_ARCH := armv8m + FEATURES_PROVIDED += cortexm_stack_limit #RUST_TARGET = thumbv8m.main-none-eabi else ifeq ($(CPU_CORE),cortex-m4) CPU_ARCH := armv7m diff --git a/cpu/cortexm_common/thread_arch.c b/cpu/cortexm_common/thread_arch.c index be0188df45..3a762f43da 100644 --- a/cpu/cortexm_common/thread_arch.c +++ b/cpu/cortexm_common/thread_arch.c @@ -297,6 +297,13 @@ void NORETURN cpu_switch_context_exit(void) UNREACHABLE(); } +#ifdef MODULE_CORTEXM_STACK_LIMIT +static void* __attribute__((used)) _get_new_stacksize(unsigned int *args) { + thread_t* t = (thread_t*) args; + return thread_get_stackstart(t); +} +#endif + #if CPU_CORE_CORTEXM_FULL_THUMB void __attribute__((naked)) __attribute__((used)) isr_pendsv(void) { __asm__ volatile ( @@ -337,8 +344,14 @@ void __attribute__((naked)) __attribute__((used)) isr_pendsv(void) { /* current thread context is now saved */ "restore_context: \n" /* Label to skip thread state saving */ - - "ldr r0, [r0] \n" /* load tcb->sp to register 1 */ +#ifdef MODULE_CORTEXM_STACK_LIMIT + "mov r4, r0 \n" /* Save content of R0 into R4*/ + "bl _get_new_stacksize \n" /* Get the new lower limit stack in R0 */ + "msr psplim, r0 \n" /* Set the PSP lower limit stack */ + "ldr r0, [r4] \n" /* Load tcb->sp to register 0 */ +#else + "ldr r0, [r0] \n" /* load tcb->sp to register 0 */ +#endif "ldmia r0!, {r4-r11,lr} \n" /* restore other registers, including lr */ #ifdef MODULE_CORTEXM_FPU "tst lr, #0x10 \n" diff --git a/cpu/cortexm_common/vectors_cortexm.c b/cpu/cortexm_common/vectors_cortexm.c index 35e6cddcf4..e06ffdfca3 100644 --- a/cpu/cortexm_common/vectors_cortexm.c +++ b/cpu/cortexm_common/vectors_cortexm.c @@ -99,6 +99,11 @@ void reset_handler_default(void) uint32_t *dst; const uint32_t *src = &_etext; +#ifdef __ARM_ARCH_8M_MAIN__ + /* Set the lower limit of the exception stack into MSPLIM register */ + __set_MSPLIM((uint32_t)&_sstack); +#endif + cortexm_init_fpu(); #ifdef MODULE_PUF_SRAM diff --git a/makefiles/features_existing.inc.mk b/makefiles/features_existing.inc.mk index 66fdfb684f..17c6a8cc1e 100644 --- a/makefiles/features_existing.inc.mk +++ b/makefiles/features_existing.inc.mk @@ -46,6 +46,7 @@ FEATURES_EXISTING := \ can_rx_mailbox \ cortexm_fpu \ cortexm_mpu \ + cortexm_stack_limit \ cortexm_svc \ cpp \ cpu_arm7tdmi_gba \ diff --git a/makefiles/features_modules.inc.mk b/makefiles/features_modules.inc.mk index a0a6d64ac5..49bd2b9ccb 100644 --- a/makefiles/features_modules.inc.mk +++ b/makefiles/features_modules.inc.mk @@ -78,6 +78,10 @@ ifneq (,$(filter periph_rtc,$(USEMODULE))) USEMODULE += rtc_utils endif +# select cortexm_stack_limit pseudomodule if the corresponding +# feature is used +USEMODULE += $(filter cortexm_stack_limit, $(FEATURES_USED)) + # select cortexm_svc pseudomodule if the corresponding feature is used USEMODULE += $(filter cortexm_svc, $(FEATURES_USED)) diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 6b66fcca95..80b32fdf9c 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -35,6 +35,16 @@ PSEUDOMODULES += board_software_reset PSEUDOMODULES += arduino_pwm PSEUDOMODULES += arduino_serial_stdio +## @defgroup pseudomodule_arm_stack_limit arm_stack_limit +## @{ +## @brief Set MSP/PSP stack lower limit +## +## Use PSPLIM and MSPLIM ARM registers to set the lower limit of a stack +## This is a protection mechanism to catch stack overflow early before it +## can corrupt adjacent memory. Only available on ARMv8-M architecture. +PSEUDOMODULES += cortexm_stack_limit +## @} + PSEUDOMODULES += can_mbox PSEUDOMODULES += can_pm PSEUDOMODULES += can_raw