riscv: fix crash resulting from touching the initial stack's guard area

The interrupt stack is used as the system stack during kernel
initialization while IRQs are not yet enabled. The sp register is
set to z_interrupt_stacks + CONFIG_ISR_STACK_SIZE.

CONFIG_ISR_STACK_SIZE only represents the desired usable stack size.
This does not take into account the added guard area. Result is a stack
whose pointer is much closer to the trigger zone than expected when
CONFIG_PMP_STACK_GUARD=y, and the SMP configuration in particular pushes
it over the edge during many CI test cases.

Worse: during early init we're not quite ready to handle exceptions
yet and complete havoc ensues with no meaningful debugging output.

Make sure the early assembly code locates the actual top of the stack
by generating a constant with its true size.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
Nicolas Pitre 2022-09-26 22:58:21 -04:00 committed by Fabio Baltieri
commit 1f362a81f1
2 changed files with 7 additions and 4 deletions

View file

@ -8,6 +8,7 @@
#include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h>
#include <zephyr/arch/cpu.h>
#include <offsets.h>
#include "asm_macros.inc"
/* exports */
@ -66,7 +67,7 @@ boot_first_core:
#ifdef CONFIG_INIT_STACKS
/* Pre-populate all bytes in z_interrupt_stacks with 0xAA */
la t0, z_interrupt_stacks
li t1, CONFIG_ISR_STACK_SIZE
li t1, __z_interrupt_stack_SIZEOF
add t1, t1, t0
/* Populate z_interrupt_stacks with 0xaaaaaaaa */
@ -79,10 +80,10 @@ aa_loop:
/*
* Initially, setup stack pointer to
* z_interrupt_stacks + CONFIG_ISR_STACK_SIZE
* z_interrupt_stacks + __z_interrupt_stack_SIZEOF
*/
la sp, z_interrupt_stacks
li t0, CONFIG_ISR_STACK_SIZE
li t0, __z_interrupt_stack_SIZEOF
add sp, sp, t0
#ifdef CONFIG_WDOG_INIT

View file

@ -4,8 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/pm/device.h>
#include "kernel_internal.h"
#ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_
#define ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_
@ -96,6 +96,8 @@ GEN_OFFSET_SYM(_thread_t, tls);
GEN_ABSOLUTE_SYM(K_THREAD_SIZEOF, sizeof(struct k_thread));
GEN_ABSOLUTE_SYM(__z_interrupt_stack_SIZEOF, sizeof(z_interrupt_stacks[0]));
/* size of the device structure. Used by linker scripts */
GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_SIZEOF, sizeof(const struct device));