You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/12/09 12:44:22 UTC
[incubator-nuttx] 05/06: arch/xtensa: Add a pseudo save area to be
able to backtrace from interrupts
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 7075c989781d7a058d9bbc456c1507475fa57790
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Tue Dec 1 16:53:57 2020 +0000
arch/xtensa: Add a pseudo save area to be able to backtrace from
interrupts
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/Kconfig | 7 +++
arch/xtensa/src/common/xtensa_int_handlers.S | 69 +++++++++++++++++++++++-----
arch/xtensa/src/common/xtensa_user_handler.S | 25 ++++++++--
3 files changed, 86 insertions(+), 15 deletions(-)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 1986457..6253c77 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -108,6 +108,13 @@ config XTENSA_BTDEPTH
---help---
This is the depth of the backtrace.
+config XTENSA_INTBACKTRACE
+ bool "Full backtrace from interrupts"
+ default n
+ depends on XTENSA_DUMPBT_ON_ASSERT
+ ---help---
+ Add necessary logic to be able to have a full backtrace from an interrupt context.
+
config XTENSA_USE_SEPARATE_IMEM
bool "Use a separate heap for internal memory"
default n
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index 16b4a0f..c75fefa 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -187,6 +187,29 @@ g_intstackbase:
and a6, a6, a3 /* a6 = Set of pending, enabled interrupts for this level */
beqz a6, 1f /* Nothing to do */
+ /* At this point, the exception frame should have been allocated and filled,
+ * and current sp points to the interrupt stack (if enabled). Copy the
+ * pre-exception's base save area below the current SP.
+ */
+
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ rsr a0, EXCSAVE_1 + \level - 1 /* Get exception frame pointer stored in EXCSAVE_x */
+ l32i a3, a0, (4 * REG_A0) /* Copy pre-exception a0 (return address) */
+ s32e a3, sp, -16
+ l32i a3, a0, (4 * REG_A1) /* Copy pre-exception a1 (stack pointer) */
+ s32e a3, sp, -12
+
+ /* Backtracing only needs a0 and a1, no need to create full base save area.
+ * Also need to change current frame's return address to point to pre-exception's
+ * last run instruction.
+ */
+
+ rsr a0, EPC_1 + \level - 1 /* return address */
+ movi a4, 0xc0000000 /* constant with top 2 bits set (call size) */
+ or a0, a0, a4 /* set top 2 bits */
+ addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */
+#endif
+
/* Call xtensa_int_decode passing the address of the register save area
* as a parameter (A7).
*/
@@ -270,7 +293,7 @@ g_intstackbase:
_xtensa_level1_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, PS /* Save interruptee's PS */
@@ -280,6 +303,10 @@ _xtensa_level1_handler:
rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_1
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -369,7 +396,7 @@ _xtensa_level1_handler:
_xtensa_level2_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_2 /* Save interruptee's PS */
@@ -379,6 +406,10 @@ _xtensa_level2_handler:
rsr a0, EXCSAVE_2 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_2
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -430,7 +461,7 @@ _xtensa_level2_handler:
_xtensa_level3_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_3 /* Save interruptee's PS */
@@ -440,6 +471,10 @@ _xtensa_level3_handler:
rsr a0, EXCSAVE_3 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_3
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -491,7 +526,7 @@ _xtensa_level3_handler:
_xtensa_level4_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_4 /* Save interruptee's PS */
@@ -501,6 +536,10 @@ _xtensa_level4_handler:
rsr a0, EXCSAVE_4 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_4
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -552,7 +591,7 @@ _xtensa_level4_handler:
_xtensa_level5_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_5 /* Save interruptee's PS */
@@ -562,6 +601,10 @@ _xtensa_level5_handler:
rsr a0, EXCSAVE_5 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_5
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -613,7 +656,7 @@ _xtensa_level5_handler:
_xtensa_level6_handler:
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_6 /* Save interruptee's PS */
@@ -623,6 +666,10 @@ _xtensa_level6_handler:
rsr a0, EXCSAVE_6 /* Save interruptee's a0 */
s32i a0, sp, (4 * REG_A0)
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ wsr sp, EXCSAVE_6
+#endif
+
/* Save rest of interrupt context. */
s32i a2, sp, (4 * REG_A2)
@@ -713,7 +760,7 @@ _xtensa_level2_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_2 /* Save interruptee's PS */
@@ -747,7 +794,7 @@ _xtensa_level3_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_3 /* Save interruptee's PS */
@@ -783,7 +830,7 @@ _xtensa_level4_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_4 /* Save interruptee's PS */
@@ -819,7 +866,7 @@ _xtensa_level5_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_5 /* Save interruptee's PS */
@@ -855,7 +902,7 @@ _xtensa_level6_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, EPS_6 /* Save interruptee's PS */
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index bc01f53..5fb94f6 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -193,7 +193,7 @@ _xtensa_user_handler:
/* Allocate exception frame and save minimal context. */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, PS /* Save interruptee's PS */
@@ -224,7 +224,24 @@ _xtensa_user_handler:
movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
#endif
wsr a0, PS
- rsync
+
+ /* Create pseudo base save area. At this point, sp is still pointing to the
+ * allocated and filled exception stack frame.
+ */
+
+#ifdef CONFIG_XTENSA_INTBACKTRACE
+ l32i a3, sp, (4 * REG_A0) /* Copy pre-exception a0 (return address) */
+ s32e a3, sp, -16
+ l32i a3, sp, (4 * REG_A1) /* Copy pre-exception a1 (stack pointer) */
+ s32e a3, sp, -12
+ rsr a0, EPC_1 /* return address for debug backtrace */
+ movi a4, 0xc0000000 /* constant with top 2 bits set (call size) */
+ rsync /* wait for WSR.PS to complete */
+ or a0, a0, a4 /* set top 2 bits */
+ addx2 a0, a4, a0 /* clear top bit -- thus simulating call4 size */
+#else
+ rsync /* wait for WSR.PS to complete */
+#endif
/* Call xtensa_user, passing both the EXCCAUSE and a pointer to the
* beginning of the register save area.
@@ -284,7 +301,7 @@ _xtensa_syscall_handler:
/* Allocate stack frame and save A0, A1, and PS */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, PS /* Save interruptee's PS */
@@ -451,7 +468,7 @@ _xtensa_coproc_handler:
/* For now, just panic */
- mov a0, sp /* sp == a1 */
+ mov a0, sp /* Save SP in A0 */
addi sp, sp, -(4 * XCPTCONTEXT_SIZE) /* Allocate interrupt stack frame */
s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
rsr a0, PS /* Save interruptee's PS */