platform: Store callee saved register in exception information
Store the callee saved registers in the exception information logging.
We store the current exception frame, which has the registers of the
caller saved registers when the exception occurs, but the callee saved
register information is lost during the exception handling.
This provides us with an incomplete picture of the state at the time
the exception occurred.
Change-Id: I3d15f9eccf1aa8c2c1b99e75e38229ab82420f36
Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
diff --git a/platform/ext/common/exception_info.c b/platform/ext/common/exception_info.c
index 11180be..c9cdc3b 100644
--- a/platform/ext/common/exception_info.c
+++ b/platform/ext/common/exception_info.c
@@ -117,6 +117,16 @@
SPMLOG_DBGMSGVAL(" PC: ", ctx->EXC_FRAME_COPY[6]);
SPMLOG_DBGMSGVAL(" xPSR: ", ctx->EXC_FRAME_COPY[7]);
+ SPMLOG_DBGMSG(" Callee saved register state:");
+ SPMLOG_DBGMSGVAL(" R4: ", ctx->CALLEE_SAVED_COPY[0]);
+ SPMLOG_DBGMSGVAL(" R5: ", ctx->CALLEE_SAVED_COPY[1]);
+ SPMLOG_DBGMSGVAL(" R6: ", ctx->CALLEE_SAVED_COPY[2]);
+ SPMLOG_DBGMSGVAL(" R7: ", ctx->CALLEE_SAVED_COPY[3]);
+ SPMLOG_DBGMSGVAL(" R8: ", ctx->CALLEE_SAVED_COPY[4]);
+ SPMLOG_DBGMSGVAL(" R9: ", ctx->CALLEE_SAVED_COPY[5]);
+ SPMLOG_DBGMSGVAL(" R10: ", ctx->CALLEE_SAVED_COPY[6]);
+ SPMLOG_DBGMSGVAL(" R11: ", ctx->CALLEE_SAVED_COPY[7]);
+
#ifdef FAULT_STATUS_PRESENT
SPMLOG_DBGMSGVAL(" CFSR: ", ctx->CFSR);
SPMLOG_DBGMSGVAL(" BFSR: ",
@@ -196,7 +206,8 @@
memcpy(ctx, &exception_info, sizeof(exception_info));
}
-void store_and_dump_context(uint32_t LR_in, uint32_t MSP_in, uint32_t PSP_in)
+void store_and_dump_context(uint32_t MSP_in, uint32_t PSP_in, uint32_t LR_in,
+ uint32_t *callee_saved)
{
struct exception_info_t *ctx = &exception_info;
@@ -208,6 +219,10 @@
ctx->EXC_FRAME = get_exception_frame(ctx->EXC_RETURN, ctx->MSP, ctx->PSP);
memcpy(ctx->EXC_FRAME_COPY, ctx->EXC_FRAME, sizeof(ctx->EXC_FRAME_COPY));
+ if (callee_saved) {
+ memcpy(ctx->CALLEE_SAVED_COPY, callee_saved, sizeof(ctx->CALLEE_SAVED_COPY));
+ }
+
#ifdef FAULT_STATUS_PRESENT
ctx->CFSR = SCB->CFSR;
ctx->HFSR = SCB->HFSR;
diff --git a/platform/include/exception_info.h b/platform/include/exception_info.h
index e2d115f..9502008 100644
--- a/platform/include/exception_info.h
+++ b/platform/include/exception_info.h
@@ -40,6 +40,7 @@
uint32_t PSP; /* (Secure) PSP. */
uint32_t *EXC_FRAME; /* Exception frame on stack. */
uint32_t EXC_FRAME_COPY[8]; /* Copy of the basic exception frame. */
+ uint32_t CALLEE_SAVED_COPY[8]; /* Copy of the callee saved registers. */
uint32_t xPSR; /* Program Status Registers. */
#ifdef FAULT_STATUS_PRESENT
@@ -68,20 +69,54 @@
/* Store context for an exception, then print the info.
* Call EXCEPTION_INFO() instead of calling this directly.
*/
-void store_and_dump_context(uint32_t LR_in, uint32_t MSP_in, uint32_t PSP_in);
+void store_and_dump_context(uint32_t MSP_in, uint32_t PSP_in, uint32_t LR_in,
+ uint32_t *callee_saved);
/* IAR Specific */
#if defined(__ICCARM__)
#pragma required = store_and_dump_context
#endif
-#define EXCEPTION_INFO() \
- __ASM volatile( \
- "MOV r0, lr\n" \
- "MRS r1, MSP\n" \
- "MRS r2, PSP\n" \
- "BL store_and_dump_context\n" \
+#if defined(__ARM_ARCH_8M_BASE__) || defined(__ARCM_ARCH_V6_M__)
+#define EXCEPTION_INFO() \
+ __ASM volatile( \
+ "MRS R0, MSP\n" \
+ "MRS R1, PSP\n" \
+ "MOV R2, R11\n" \
+ "MOV R3, R10\n" \
+ "PUSH {R2, R3}\n" \
+ "MOV R2, R9\n" \
+ "MOV R3, R8\n" \
+ "PUSH {R2, R3}\n" \
+ "PUSH {R4-R7}\n" \
+ "MOV R3, SP\n" \
+ "MOV R2, LR\n" \
+ "BL store_and_dump_context\n" \
+ "ADD SP, #32\n" \
)
+#elif defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__) || \
+ defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
+#define EXCEPTION_INFO() \
+ __ASM volatile( \
+ "MRS R0, MSP\n" \
+ "MRS R1, PSP\n" \
+ "PUSH {R4-R11}\n" \
+ "MOV R3, SP\n" \
+ "MOV R2, LR\n" \
+ "BL store_and_dump_context\n" \
+ "ADD SP, #32\n" \
+ )
+#else
+/* Unhandled arch, call store_and_dump_context with callee_saved = NULL */
+#define EXCEPTION_INFO() \
+ __ASM volatile( \
+ "MRS R0, MSP\n" \
+ "MRS R1, PSP\n" \
+ "MOV R2, LR\n" \
+ "MOV R3, #0\n" \
+ "BL store_and_dump_context\n" \
+ )
+#endif
#else /* TFM_EXCEPTION_INFO_DUMP */
#define EXCEPTION_INFO()