Commit 6fae891c authored by Yong Cong Sin's avatar Yong Cong Sin Committed by Anas Nashif
Browse files

arch: reorg the dependencies around (exception) stack trace



This commit introduces a new ARCH_STACKWALK Kconfig which
determines if the `arch_stack_walk()` is available should the
arch supports it.

Starting from RISCV, this will be able to converge the exception
stack trace implementation & stack walking features. Existing
exception stack trace implementation will be updated later.
Eventually we will end up with the following:

1. If an arch implements `arch_stack_walk()`
   `ARCH_HAS_STACKWALK` should be selected.
2. If the above is enabled, `ARCH_SUPPORTS_STACKWALK` indicates
   if the dependencies are met for arch to enable stack walking.
   This Kconfig replaces `<arch>_EXCEPTION_STACK_TRACE`
2. If the above is enabled, then, `ARCH_STACKWALK` determines
   if `arch_stack_walk()` should be compiled.
3. `EXCEPTION_STACK_TRACE` should build on top of the
   `ARCH_STACKWALK`, stack traces will be printed when it
   is enabled.
4. `ARCH_STACKWALK_MAX_FRAMES` will be removed as it is
   replaced by `ARCH_STACKWALK_MAX_FRAMES`

Signed-off-by: default avatarYong Cong Sin <ycsin@meta.com>
Signed-off-by: default avatarYong Cong Sin <yongcong.sin@gmail.com>
parent e0770d45
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@ config RISCV
	select ARCH_SUPPORTS_ROM_START if !SOC_FAMILY_ESPRESSIF_ESP32
	select ARCH_HAS_CODE_DATA_RELOCATION
	select ARCH_HAS_THREAD_LOCAL_STORAGE
	select ARCH_HAS_STACKWALK
	select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD
	select USE_SWITCH_SUPPORTED
	select USE_SWITCH
@@ -415,10 +414,17 @@ config FRAME_POINTER
	  Select Y here to gain precise stack traces at the expense of slightly
	  increased size and decreased speed.

config ARCH_STACKWALK
	bool "Compile the stack walking function"
	default y
	depends on ARCH_HAS_STACKWALK
	help
	  Select Y here to compile the `arch_stack_walk()` function

config ARCH_STACKWALK_MAX_FRAMES
	int "Max depth for stack walk function"
	default 8
	depends on ARCH_HAS_STACKWALK
	depends on ARCH_STACKWALK
	help
	  Depending on implementation, this can place a hard limit on the depths of the stack
	  for the stack walk function to examine.
@@ -671,11 +677,6 @@ config ARCH_HAS_EXTRA_EXCEPTION_INFO
config ARCH_HAS_GDBSTUB
	bool

config ARCH_HAS_STACKWALK
	bool
	help
	  This is selected when the architecture implemented the arch_stack_walk() API.

config ARCH_HAS_COHERENCE
	bool
	help
+8 −7
Original line number Diff line number Diff line
@@ -37,13 +37,6 @@ config RISCV_ALWAYS_SWITCH_THROUGH_ECALL
	  and most people should say n here to minimize context switching
	  overhead.

config RISCV_EXCEPTION_STACK_TRACE
	bool
	default y
	imply THREAD_STACK_INFO
	help
	  Internal config to enable runtime stack traces on fatal exceptions.

menu "RISCV Processor Options"

config INCLUDE_RESET_VECTOR
@@ -383,6 +376,14 @@ config GEN_IRQ_VECTOR_TABLE
config ARCH_HAS_SINGLE_THREAD_SUPPORT
	default y if !SMP

config ARCH_HAS_STACKWALK
	bool
	default y
	imply THREAD_STACK_INFO
	help
	  Internal config to indicate that the arch_stack_walk() API is implemented
	  and it can be enabled.

rsource "Kconfig.isa"

endmenu
+1 −1
Original line number Diff line number Diff line
@@ -25,5 +25,5 @@ zephyr_library_sources_ifdef(CONFIG_RISCV_PMP pmp.c pmp.S)
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c)
zephyr_library_sources_ifdef(CONFIG_EXCEPTION_STACK_TRACE stacktrace.c)
zephyr_library_sources_ifdef(CONFIG_ARCH_STACKWALK stacktrace.c)
zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld)
+4 −4
Original line number Diff line number Diff line
@@ -98,12 +98,12 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arc
#endif /* CONFIG_RISCV_ISA_RV32E */
		LOG_ERR("");
	}
#endif /* CONFIG_EXCEPTION_DEBUG */

	if (IS_ENABLED(CONFIG_EXCEPTION_STACK_TRACE)) {
#ifdef CONFIG_EXCEPTION_STACK_TRACE
	z_riscv_unwind_stack(esf, csf);
	}
#endif /* CONFIG_EXCEPTION_STACK_TRACE */

#endif /* CONFIG_EXCEPTION_DEBUG */
	z_fatal_error(reason, esf);
	CODE_UNREACHABLE;
}
+23 −22
Original line number Diff line number Diff line
@@ -14,8 +14,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);

uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf);

#define MAX_STACK_FRAMES                                                                           \
	MAX(CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES, CONFIG_ARCH_STACKWALK_MAX_FRAMES)
#define MAX_STACK_FRAMES CONFIG_ARCH_STACKWALK_MAX_FRAMES

struct stackframe {
	uintptr_t fp;
@@ -87,26 +86,6 @@ static bool in_stack_bound(uintptr_t addr, const struct k_thread *const thread,
	return in_kernel_thread_stack_bound(addr, thread);
}

static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const thread,
				 const struct arch_esf *esf)
{
	const uintptr_t align =
		COND_CODE_1(CONFIG_FRAME_POINTER, (ARCH_STACK_PTR_ALIGN), (sizeof(uintptr_t)));

	if (!IS_ALIGNED(addr, align)) {
		return false;
	}

	if ((thread == NULL) || arch_is_in_isr()) {
		/* We were servicing an interrupt */
		uint8_t cpu_id = IS_ENABLED(CONFIG_SMP) ? arch_curr_cpu()->id : 0U;

		return in_irq_stack_bound(addr, cpu_id);
	}

	return in_stack_bound(addr, thread, esf);
}

static inline bool in_text_region(uintptr_t addr)
{
	extern uintptr_t __text_region_start, __text_region_end;
@@ -242,6 +221,27 @@ void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie,
	walk_stackframe(callback_fn, cookie, thread, esf, in_stack_bound, &thread->callee_saved);
}

#ifdef CONFIG_EXCEPTION_STACK_TRACE
static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const thread,
				 const struct arch_esf *esf)
{
	const uintptr_t align =
		COND_CODE_1(CONFIG_FRAME_POINTER, (ARCH_STACK_PTR_ALIGN), (sizeof(uintptr_t)));

	if (!IS_ALIGNED(addr, align)) {
		return false;
	}

	if ((thread == NULL) || arch_is_in_isr()) {
		/* We were servicing an interrupt */
		uint8_t cpu_id = IS_ENABLED(CONFIG_SMP) ? arch_curr_cpu()->id : 0U;

		return in_irq_stack_bound(addr, cpu_id);
	}

	return in_stack_bound(addr, thread, esf);
}

#if __riscv_xlen == 32
#define PR_REG "%08" PRIxPTR
#elif __riscv_xlen == 64
@@ -276,3 +276,4 @@ void z_riscv_unwind_stack(const struct arch_esf *esf, const _callee_saved_t *csf
	walk_stackframe(print_trace_address, &i, _current, esf, in_fatal_stack_bound, csf);
	LOG_ERR("");
}
#endif /* CONFIG_EXCEPTION_STACK_TRACE */
Loading