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 <mholden@fb.com>
This commit is contained in:
Mark Holden 2022-04-15 10:16:26 -07:00 committed by Anas Nashif
commit df6b8c3cc4
2 changed files with 40 additions and 4 deletions

View file

@ -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 */
}

View file

@ -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)