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 <[email protected]>
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 <[email protected]>
---
 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 */

Reply via email to