From df6b8c3cc40495893da8213171e2f699da16eeee Mon Sep 17 00:00:00 2001 From: Mark Holden Date: Fri, 15 Apr 2022 10:16:26 -0700 Subject: [PATCH] coredump: arm: Capture callee registers during k_panic() / k_oops Ensure callee registers included in coredump. Push callee registers onto stack and pass as param to z_do_kernel_oops for CONFIG_ARMV7_M_ARMV8_M_MAINLINE when CONFIG_EXTRA_EXCEPTION_INFO enabled. Signed-off-by: Mark Holden --- arch/arm/core/aarch32/fatal.c | 23 +++++++++++++++++++---- arch/arm/core/aarch32/swap_helper.S | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/arch/arm/core/aarch32/fatal.c b/arch/arm/core/aarch32/fatal.c index 81b0eace4e7..67364f047ee 100644 --- a/arch/arm/core/aarch32/fatal.c +++ b/arch/arm/core/aarch32/fatal.c @@ -77,9 +77,13 @@ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) * fault handler will executed instead of the SVC. * * @param esf exception frame + * @param callee_regs Callee-saved registers (R4-R11) */ -void z_do_kernel_oops(const z_arch_esf_t *esf) +void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) { +#if !(defined(CONFIG_EXTRA_EXCEPTION_INFO) && defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)) + ARG_UNUSED(callee_regs); +#endif /* Stacked R0 holds the exception reason. */ unsigned int reason = esf->basic.r0; @@ -102,15 +106,26 @@ void z_do_kernel_oops(const z_arch_esf_t *esf) #if !defined(CONFIG_EXTRA_EXCEPTION_INFO) z_arm_fatal_error(reason, esf); +#else + z_arch_esf_t esf_copy; + + memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* extra exception info is collected in callee_reg param + * on CONFIG_ARMV7_M_ARMV8_M_MAINLINE + */ + + esf_copy.extra_info = (struct __extra_esf_info) { + .callee = callee_regs, + }; #else /* extra exception info is not collected for kernel oops * path today so we make a copy of the ESF and zero out * that information */ - z_arch_esf_t esf_copy; - - memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); esf_copy.extra_info = (struct __extra_esf_info) { 0 }; +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ + z_arm_fatal_error(reason, &esf_copy); #endif /* CONFIG_EXTRA_EXCEPTION_INFO */ } diff --git a/arch/arm/core/aarch32/swap_helper.S b/arch/arm/core/aarch32/swap_helper.S index 426e35ade3e..119bd986128 100644 --- a/arch/arm/core/aarch32/swap_helper.S +++ b/arch/arm/core/aarch32/swap_helper.S @@ -556,8 +556,29 @@ _stack_frame_endif: _oops: push {r0, lr} +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* Build _callee_saved_t. To match the struct + * definition we push the psp & then r11-r4 + */ + mrs r1, PSP + push {r1, r2} + push {r4-r11} + mov r1, sp /* pointer to _callee_saved_t */ +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ bl z_do_kernel_oops /* return from SVC exception is done here */ +#if defined(CONFIG_EXTRA_EXCEPTION_INFO) +#if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + /* We do not need to restore any register state here + * because we did not use any callee-saved registers + * in this routine. Therefore, we can just reset + * the MSP to its value prior to entering the function + */ + add sp, #40 +#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */ +#endif /* CONFIG_EXTRA_EXCEPTION_INFO */ pop {r0, pc} #if defined(CONFIG_USERSPACE)