diff --git a/arch/arm/core/aarch32/cortex_m/mpu/arm_core_mpu.c b/arch/arm/core/aarch32/cortex_m/mpu/arm_core_mpu.c index af57fae3b60..41b619fea21 100644 --- a/arch/arm/core/aarch32/cortex_m/mpu/arm_core_mpu.c +++ b/arch/arm/core/aarch32/cortex_m/mpu/arm_core_mpu.c @@ -46,6 +46,10 @@ LOG_MODULE_REGISTER(mpu); #define _MPU_DYNAMIC_REGIONS_AREA_SIZE ((uint32_t)&__kernel_ram_end - \ _MPU_DYNAMIC_REGIONS_AREA_START) +#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD) +extern K_THREAD_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE); +#endif + /** * @brief Use the HW-specific MPU driver to program * the static MPU regions. @@ -86,6 +90,21 @@ void z_arm_configure_static_mpu_regions(void) }; #endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */ +#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD) + /* Main stack MPU guard to detect overflow. + * Note: + * FPU_SHARING and USERSPACE are not supported features + * under CONFIG_MULTITHREADING=n, so the MPU guard (if + * exists) is reserved aside of CONFIG_MAIN_STACK_SIZE + * and there is no requirement for larger guard area (FP + * context is not stacked). + */ + const struct k_mem_partition main_stack_guard_region = { + .start = (uint32_t)z_main_stack, + .size = (uint32_t)MPU_GUARD_ALIGN_AND_SIZE, + .attr = K_MEM_PARTITION_P_RO_U_NA, + }; +#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */ /* Define a constant array of k_mem_partition objects * to hold the configuration of the respective static * MPU regions. @@ -97,6 +116,9 @@ void z_arm_configure_static_mpu_regions(void) #if defined(CONFIG_NOCACHE_MEMORY) &nocache_region, #endif /* CONFIG_NOCACHE_MEMORY */ +#if !defined(CONFIG_MULTITHREADING) && defined(CONFIG_MPU_STACK_GUARD) + &main_stack_guard_region, +#endif /* !CONFIG_MULTITHREADING && CONFIG_MPU_STACK_GUARD */ #if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT) &ramfunc_region #endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */ @@ -112,7 +134,8 @@ void z_arm_configure_static_mpu_regions(void) (uint32_t)&_image_ram_start, (uint32_t)&__kernel_ram_end); -#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) +#if defined(CONFIG_MPU_REQUIRES_NON_OVERLAPPING_REGIONS) && \ + defined(CONFIG_MULTITHREADING) /* Define a constant array of k_mem_partition objects that holds the * boundaries of the areas, inside which dynamic region programming * is allowed. The information is passed to the underlying driver at diff --git a/arch/arm/core/aarch32/thread.c b/arch/arm/core/aarch32/thread.c index 7005c2cf63f..bf6b9ed82d9 100644 --- a/arch/arm/core/aarch32/thread.c +++ b/arch/arm/core/aarch32/thread.c @@ -256,11 +256,13 @@ void configure_builtin_stack_guard(struct k_thread *thread) */ uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp) { +#if defined(CONFIG_MULTITHREADING) const struct k_thread *thread = _current; if (!thread) { return 0; } +#endif #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) uint32_t guard_len = (thread->base.user_options & K_FP_REGS) ? @@ -298,12 +300,21 @@ uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, const uint32_t psp } } #else /* CONFIG_USERSPACE */ +#if defined(CONFIG_MULTITHREADING) if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start - guard_len, guard_len, fault_addr, psp)) { /* Thread stack corruption */ return thread->stack_info.start; } +#else + if (IS_MPU_GUARD_VIOLATION((uint32_t)z_main_stack, + guard_len, + fault_addr, psp)) { + /* Thread stack corruption */ + return (uint32_t)Z_THREAD_STACK_BUFFER(z_main_stack); + } +#endif #endif /* CONFIG_USERSPACE */ return 0;