You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/06/15 15:07:56 UTC
[incubator-nuttx] branch master updated (e75c88df5b -> 9bac291236)
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
from e75c88df5b wireless/bcm43xxx: load nvram from file system
new 05d412f6b5 arch/xtensa/xtensa_user_handler.S: Use the ps_setup macro when possible.
new fc22eddc38 arch/xtensa: Refactor the code that's used to get the pre-exception backtrace.
new 48f20af8bc arch/xtensa/xtensa_int_handlers.S: Remove unused macro.
new 1c94cb5324 arch/xtensa: Refactor the differences in ABI calls.
new 73a1e0fc58 arch/xtensa: Refactor exceptions' entry and exit.
new 5ab888692e arch/xtensa/xtensa_context: Place the functions in EXCEPTION_HANDLER section (IRAM for ESP32xx chips).
new fe8fa4ff75 arch/xtensa: Move the new saving area directly to A2.
new 9bac291236 arch/xtensa/*.S: Remove some old comments and fix others.
The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
arch/xtensa/include/xtensa/xtensa_abi.h | 27 +-
arch/xtensa/src/common/xtensa_context.S | 7 +-
arch/xtensa/src/common/xtensa_int_handlers.S | 377 +++++++--------------------
arch/xtensa/src/common/xtensa_macros.S | 113 ++++++++
arch/xtensa/src/common/xtensa_panic.S | 20 +-
arch/xtensa/src/common/xtensa_user_handler.S | 126 +++------
arch/xtensa/src/common/xtensa_vectors.S | 41 +--
7 files changed, 281 insertions(+), 430 deletions(-)
[incubator-nuttx] 08/08: arch/xtensa/*.S: Remove some old comments and fix others.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 9bac29123640352f4f2f797b1544396f63e77175
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Tue Jun 14 11:20:05 2022 +0200
arch/xtensa/*.S: Remove some old comments and fix others.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_context.S | 2 -
arch/xtensa/src/common/xtensa_int_handlers.S | 81 +++++++++++++---------------
arch/xtensa/src/common/xtensa_macros.S | 2 +-
3 files changed, 38 insertions(+), 47 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_context.S b/arch/xtensa/src/common/xtensa_context.S
index b74970abed..287a457dca 100644
--- a/arch/xtensa/src/common/xtensa_context.S
+++ b/arch/xtensa/src/common/xtensa_context.S
@@ -91,13 +91,11 @@
*
* Entry Conditions:
* - A0 = Return address to caller.
- * - A2 = Pointer to the processor state save area
* - Other processor state except PC, PS, A0, A1 (SP), A2 and A3 are as at
* the point of interruption.
*
* Exit conditions:
* - A0 = Return address in caller.
- * - A2, A12-A15 as at entry (preserved).
*
* Assumptions:
* - Caller is expected to have saved PC, PS, A0, A1 (SP), and A2.
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index 0d23f6d114..e4f40f7551 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -110,9 +110,8 @@ g_intstacktop:
* a12 - register save area
*
* Exit Conditions:
- * This macro will use registers a0 and a2-a5 and a2.
- * a1 - May point to the new thread's SP
- * a2 - Points to the register save area (which may not be on the stack).
+ * This macro will use registers a2, a3 and a4.
+ * a2 - Points to the, possbily, new register save area.
*
****************************************************************************/
@@ -131,7 +130,7 @@ g_intstacktop:
ps_setup \level \tmp
- /* Get mask of pending, enabled interrupts at this level into a2. */
+ /* Get the mask of pending, enabled interrupts at this level. */
rsr ARG1, INTENABLE
rsr a3, INTERRUPT
@@ -156,7 +155,7 @@ g_intstacktop:
* a context switch, it will instead refer to the TCB register save area.
*/
- mov a2, RETVAL /* Switch to the save area of the new thread */
+ mov a2, RETVAL
#if CONFIG_ARCH_INTERRUPTSTACK < 15
addi sp, sp, XCPTCONTEXT_SIZE
@@ -187,7 +186,7 @@ _xtensa_level1_handler:
exception_entry 1
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -207,15 +206,14 @@ _xtensa_level1_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
@@ -226,7 +224,7 @@ _xtensa_level1_handler:
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
*/
- rfe /* And return from "exception" */
+ rfe
/****************************************************************************
* MEDIUM PRIORITY (LEVEL 2+) INTERRUPT LOW LEVEL HANDLERS.
@@ -266,7 +264,7 @@ _xtensa_level2_handler:
exception_entry 2
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -286,21 +284,20 @@ _xtensa_level2_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
exception_exit 2
- /* Return from interrupt. RFI restores the PS from EPS_2 and jumps to
+ /* Return from interrupt. RFI restores the PS from EPS_2 and jumps to
* the address in EPC_2.
*/
@@ -316,11 +313,11 @@ _xtensa_level2_handler:
_xtensa_level3_handler:
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 3
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -340,21 +337,20 @@ _xtensa_level3_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
exception_exit 3
- /* Return from interrupt. RFI restores the PS from EPS_3 and jumps to
+ /* Return from interrupt. RFI restores the PS from EPS_3 and jumps to
* the address in EPC_3.
*/
@@ -370,11 +366,11 @@ _xtensa_level3_handler:
_xtensa_level4_handler:
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 4
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -394,21 +390,20 @@ _xtensa_level4_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
exception_exit 4
- /* Return from interrupt. RFI restores the PS from EPS_4 and jumps to
+ /* Return from interrupt. RFI restores the PS from EPS_4 and jumps to
* the address in EPC_4.
*/
@@ -424,11 +419,11 @@ _xtensa_level4_handler:
_xtensa_level5_handler:
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 5
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -448,21 +443,20 @@ _xtensa_level5_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
exception_exit 5
- /* Return from interrupt. RFI restores the PS from EPS_5 and jumps to
+ /* Return from interrupt. RFI restores the PS from EPS_5 and jumps to
* the address in EPC_5.
*/
@@ -478,11 +472,11 @@ _xtensa_level5_handler:
_xtensa_level6_handler:
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 6
- /* Save rest of interrupt context. */
+ /* Save the rest of the state context. */
call0 _xtensa_context_save
@@ -502,21 +496,20 @@ _xtensa_level6_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a2. NOTE that the state save area may or may not lie
- * in the new thread's stack.
+ * area in a2.
*/
dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK a0
/* Restore registers in preparation to return from interrupt */
- call0 _xtensa_context_restore /* (preserves a2) */
+ call0 _xtensa_context_restore /* Preserves a2 */
/* Restore only level-specific regs (the rest were already restored) */
exception_exit 6
- /* Return from interrupt. RFI restores the PS from EPS_6 and jumps to
+ /* Return from interrupt. RFI restores the PS from EPS_6 and jumps to
* the address in EPC_6.
*/
@@ -571,7 +564,7 @@ _xtensa_level2_handler:
#if 1
/* For now, just panic */
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 2
@@ -599,7 +592,7 @@ _xtensa_level3_handler:
#if 1
/* For now, just panic */
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 3
@@ -629,7 +622,7 @@ _xtensa_level4_handler:
#if 1
/* For now, just panic */
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 4
@@ -659,7 +652,7 @@ _xtensa_level5_handler:
#if 1
/* For now, just panic */
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 5
@@ -689,7 +682,7 @@ _xtensa_level6_handler:
#if 1
/* For now, just panic */
- /* Create interrupt frame and save minimal context. */
+ /* Create an interrupt frame and save minimal context. */
exception_entry 6
diff --git a/arch/xtensa/src/common/xtensa_macros.S b/arch/xtensa/src/common/xtensa_macros.S
index 3ebf0391e6..b101c8b843 100644
--- a/arch/xtensa/src/common/xtensa_macros.S
+++ b/arch/xtensa/src/common/xtensa_macros.S
@@ -131,7 +131,7 @@
.endm
/****************************************************************************
- * Name: exceptin_backtrace
+ * Name: exception_backtrace
*
* Description:
* Populate the base save area with the pre-exception A0 and SP to be able
[incubator-nuttx] 06/08: arch/xtensa/xtensa_context: Place the functions in EXCEPTION_HANDLER section (IRAM for ESP32xx chips).
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 5ab888692e849cc0ca0412c3bd0d091467fc5a19
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Mon Jun 13 14:55:54 2022 +0200
arch/xtensa/xtensa_context: Place the functions in EXCEPTION_HANDLER
section (IRAM for ESP32xx chips).
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_context.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_context.S b/arch/xtensa/src/common/xtensa_context.S
index 99b4bd7cfb..b74970abed 100644
--- a/arch/xtensa/src/common/xtensa_context.S
+++ b/arch/xtensa/src/common/xtensa_context.S
@@ -66,6 +66,7 @@
#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
+#include "chip.h"
#include "syscall.h"
#include "xtensa_asm_utils.h"
#include "xtensa_coproc.S"
@@ -74,8 +75,6 @@
* Public Functions
****************************************************************************/
- .text
-
/****************************************************************************
* Name: _xtensa_context_save
*
@@ -106,6 +105,7 @@
*
****************************************************************************/
+ .section HANDLER_SECTION, "ax"
.global _xtensa_context_save
.type _xtensa_context_save, @function
@@ -235,6 +235,7 @@ _xtensa_context_save:
*
****************************************************************************/
+ .section HANDLER_SECTION, "ax"
.global _xtensa_context_restore
.type _xtensa_context_restore,@function
[incubator-nuttx] 02/08: arch/xtensa: Refactor the code that's used to get the pre-exception backtrace.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit fc22eddc382336f1c1099a68e60bc8996a50619e
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Fri Jun 10 13:57:09 2022 +0200
arch/xtensa: Refactor the code that's used to get the pre-exception
backtrace.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_int_handlers.S | 17 +---------------
arch/xtensa/src/common/xtensa_macros.S | 29 ++++++++++++++++++++++++++++
arch/xtensa/src/common/xtensa_user_handler.S | 12 +-----------
3 files changed, 31 insertions(+), 27 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index c1d2d94850..d8bfc9de25 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -192,22 +192,7 @@ g_intstacktop:
* before getting here.
*/
-#ifdef CONFIG_XTENSA_INTBACKTRACE
- l32i a3, a12, (4 * REG_A0) /* Copy pre-exception a0 (return address) */
- s32e a3, sp, -16
- l32i a3, a12, (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
+ exception_backtrace a12 \level
/* Call xtensa_int_decode passing the address of the register save area
* as a parameter (A7).
diff --git a/arch/xtensa/src/common/xtensa_macros.S b/arch/xtensa/src/common/xtensa_macros.S
index cb57846d1c..5adb3633aa 100644
--- a/arch/xtensa/src/common/xtensa_macros.S
+++ b/arch/xtensa/src/common/xtensa_macros.S
@@ -92,3 +92,32 @@
.endm
+/****************************************************************************
+ * Name: exceptin_backtrace
+ *
+ * Description:
+ * Populate the base save area with the pre-exception A0 and SP to be able
+ * to backtrace from it.
+ *
+ ****************************************************************************/
+
+ .macro exception_backtrace sa level
+
+#if !defined(__XTENSA_CALL0_ABI__) && defined(CONFIG_XTENSA_INTBACKTRACE)
+ l32i a3, \sa, (4 * REG_A0) /* Copy pre-exception a0 (return address) */
+ s32e a3, sp, -16
+ l32i a3, \sa, (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 for debug backtrace */
+ 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 to simulate a call4 size */
+#endif
+
+ .endm
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index c2bf3458a3..47adb53634 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -189,17 +189,7 @@ _xtensa_user_handler:
* an interrupt stack).
*/
-#ifdef CONFIG_XTENSA_INTBACKTRACE
- l32i a3, a12, (4 * REG_A0) /* Copy pre-exception a0 (return address) */
- s32e a3, sp, -16
- l32i a3, a12, (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) */
- or a0, a0, a4 /* set top 2 bits */
- addx2 a0, a4, a0 /* clear top bit -- thus simulating call4 size */
-#endif
+ exception_backtrace a12 1
/* Call xtensa_user, passing both the EXCCAUSE and a pointer to the
* beginning of the register save area.
[incubator-nuttx] 01/08: arch/xtensa/xtensa_user_handler.S: Use the ps_setup macro when possible.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 05d412f6b56297409c7a0a9820fc0f1f37839ed9
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Fri Jun 10 11:41:50 2022 +0200
arch/xtensa/xtensa_user_handler.S: Use the ps_setup macro when possible.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_user_handler.S | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index 10b787d6e4..c2bf3458a3 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -451,12 +451,7 @@ _xtensa_coproc_handler:
/* Set up PS for C, re-enable hi-pri interrupts, and clear EXCM. */
-#ifdef __XTENSA_CALL0_ABI__
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
-#else
- movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
-#endif
- wsr a0, PS
+ ps_setup 1 a0
/* Call xtensa_user_panic, passing both the EXCCAUSE and a pointer to the
* beginning of the register save area.
[incubator-nuttx] 03/08: arch/xtensa/xtensa_int_handlers.S: Remove unused macro.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 48f20af8bcd5b870f974c30adb6afed0e1edb96c
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Fri Jun 10 14:16:14 2022 +0200
arch/xtensa/xtensa_int_handlers.S: Remove unused macro.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_int_handlers.S | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index d8bfc9de25..28946006f9 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -91,25 +91,6 @@ g_intstacktop:
* Assembly Language Macros
****************************************************************************/
-/****************************************************************************
- * Macro extract_msb - return the input with only the highest bit set.
- *
- * Entry Conditions/Side Effects:
- * Input : "ain" - Input value, clobbered.
- * Output : "aout" - Output value, has only one bit set, MSB of "ain".
- *
- * The two arguments must be different AR registers.
- *
- ****************************************************************************/
-
- .macro extract_msb aout ain
-1:
- addi \aout, \ain, -1 /* aout = ain - 1 */
- and \ain, \ain, \aout /* ain = ain & aout */
- bnez \ain, 1b /* Repeat until ain == 0 */
- addi \aout, \aout, 1 /* Return aout + 1 */
- .endm
-
/****************************************************************************
* Macro dispatch_c_isr level mask tmp
*
[incubator-nuttx] 05/08: arch/xtensa: Refactor exceptions' entry and exit.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 73a1e0fc581ae12ea0ad284bf4ee0daa4123baa6
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Mon Jun 13 14:19:46 2022 +0200
arch/xtensa: Refactor exceptions' entry and exit.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_int_handlers.S | 220 +++++++--------------------
arch/xtensa/src/common/xtensa_macros.S | 84 ++++++++++
arch/xtensa/src/common/xtensa_panic.S | 4 +-
arch/xtensa/src/common/xtensa_user_handler.S | 48 ++----
arch/xtensa/src/common/xtensa_vectors.S | 41 ++---
5 files changed, 160 insertions(+), 237 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index 052cce6e0c..10dc7391a7 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -133,12 +133,12 @@ g_intstacktop:
/* Get mask of pending, enabled interrupts at this level into a2. */
- rsr ARG1, INTENABLE
- rsr a3, INTERRUPT
- movi a4, \mask
- and ARG1, ARG1, a3
- and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
- beqz ARG1, 1f /* Nothing to do */
+ rsr ARG1, INTENABLE
+ rsr a3, INTERRUPT
+ movi a4, \mask
+ and ARG1, ARG1, a3
+ and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
+ beqz ARG1, 1f /* Nothing to do */
/* Link the pre-exception frame for debugging. At this point, a12 points to the
* allocated and filled exception stack frame (old value of SP in case of
@@ -148,8 +148,8 @@ g_intstacktop:
exception_backtrace a12 \level
/* Argument 1: Set of CPU interrupt to dispatch */
- mov ARG2, a12 /* Argument 2: Top of stack = register save area */
- CALL xtensa_int_decode
+ mov ARG2, a12 /* Argument 2: Top of stack = register save area */
+ CALL xtensa_int_decode
/* xtensa_int_decode returns the address of the new register save area.
* Usually this would be the same as the current SP. But in the event of
@@ -183,16 +183,9 @@ g_intstacktop:
_xtensa_level1_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, PS /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_1 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create an interrupt frame and save minimal context. */
+
+ exception_entry 1
/* Save rest of interrupt context. */
@@ -202,7 +195,7 @@ _xtensa_level1_handler:
* area. This value will be used later by dispatch_c_isr to retrieve the
* register save area.
*/
-
+
mov a12, sp
/* Switch to an interrupt stack if we have one */
@@ -222,26 +215,19 @@ _xtensa_level1_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
- call0 _xtensa_context_restore /* (preserves a2) */
+ mov a2, a12 /* a2 = address of new state save area */
+ call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure PS and EPC written */
+ exception_exit 1
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
*/
- rfe /* And return from "exception" */
+ rfe /* And return from "exception" */
/****************************************************************************
* MEDIUM PRIORITY (LEVEL 2+) INTERRUPT LOW LEVEL HANDLERS.
@@ -277,16 +263,9 @@ _xtensa_level1_handler:
_xtensa_level2_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_2 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_2 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_2 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create an interrupt frame and save minimal context. */
+
+ exception_entry 2
/* Save rest of interrupt context. */
@@ -321,14 +300,7 @@ _xtensa_level2_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, EPS_2
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_2
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure EPS and EPC written */
+ exception_exit 2
/* Return from interrupt. RFI restores the PS from EPS_2 and jumps to
* the address in EPC_2.
@@ -346,16 +318,9 @@ _xtensa_level2_handler:
_xtensa_level3_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_3 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_3 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_3 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 3
/* Save rest of interrupt context. */
@@ -390,14 +355,7 @@ _xtensa_level3_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, EPS_3
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_3
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure EPS and EPC written */
+ exception_exit 3
/* Return from interrupt. RFI restores the PS from EPS_3 and jumps to
* the address in EPC_3.
@@ -415,16 +373,9 @@ _xtensa_level3_handler:
_xtensa_level4_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_4 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_4 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_4 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 4
/* Save rest of interrupt context. */
@@ -455,18 +406,11 @@ _xtensa_level4_handler:
/* Restore registers in preparation to return from interrupt */
mov a2, a12 /* a2 = address of new state save area */
- call0 _xtensa_context_restore /* (presevers a2) */
+ call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, EPS_4
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_4
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure EPS and EPC written */
+ exception_exit 4
/* Return from interrupt. RFI restores the PS from EPS_4 and jumps to
* the address in EPC_4.
@@ -484,16 +428,9 @@ _xtensa_level4_handler:
_xtensa_level5_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_5 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_5 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_5 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 5
/* Save rest of interrupt context. */
@@ -528,14 +465,7 @@ _xtensa_level5_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, EPS_5
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_5
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure EPS and EPC written */
+ exception_exit 5
/* Return from interrupt. RFI restores the PS from EPS_5 and jumps to
* the address in EPC_5.
@@ -553,20 +483,13 @@ _xtensa_level5_handler:
_xtensa_level6_handler:
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_6 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_6 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_6 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 6
/* Save rest of interrupt context. */
- call0 _xtensa_context_save /* Save full register state */
+ call0 _xtensa_context_save
/* Save current SP before (possibly) overwriting it, it's the register save
* area. This value will be used later by dispatch_c_isr to retrieve the
@@ -597,14 +520,7 @@ _xtensa_level6_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, EPS_6
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_6
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure EPS and EPC written */
+ exception_exit 6
/* Return from interrupt. RFI restores the PS from EPS_6 and jumps to
* the address in EPC_6.
@@ -661,15 +577,9 @@ _xtensa_level2_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_2 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_2 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_2 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 2
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_LEVEL2_EXCEPTION /* Address of state save on stack */
@@ -695,15 +605,9 @@ _xtensa_level3_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_3 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_3 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_3 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 3
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_LEVEL3_EXCEPTION /* Address of state save on stack */
@@ -731,15 +635,9 @@ _xtensa_level4_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_4 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_4 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_4 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 4
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_LEVEL4_EXCEPTION /* Address of state save on stack */
@@ -767,15 +665,9 @@ _xtensa_level5_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_5 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_5 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_5 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 5
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_LEVEL5_EXCEPTION /* Address of state save on stack */
@@ -803,15 +695,9 @@ _xtensa_level6_handler:
#if 1
/* For now, just panic */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS_6 /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_6 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_6 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ /* Create interrupt frame and save minimal context. */
+
+ exception_entry 6
s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_LEVEL6_EXCEPTION /* Address of state save on stack */
diff --git a/arch/xtensa/src/common/xtensa_macros.S b/arch/xtensa/src/common/xtensa_macros.S
index 5adb3633aa..3ebf0391e6 100644
--- a/arch/xtensa/src/common/xtensa_macros.S
+++ b/arch/xtensa/src/common/xtensa_macros.S
@@ -92,6 +92,44 @@
.endm
+/****************************************************************************
+ * Name: ps_excp_read
+ *
+ * Description:
+ * Read from the correct PS register corresponding to the current interrupt
+ * level.
+ *
+ ****************************************************************************/
+
+ .macro ps_excp_read tmp level
+
+ .ifeq \level - 1
+ rsr \tmp, PS
+ .else
+ rsr \tmp, EPS_2 + \level - 2
+ .endif
+
+ .endm
+
+/****************************************************************************
+ * Name: ps_excp_write
+ *
+ * Description:
+ * Write to the correct PS register corresponding to the current interrupt
+ * level.
+ *
+ ****************************************************************************/
+
+ .macro ps_excp_write tmp level
+
+ .ifeq \level - 1
+ wsr \tmp, PS
+ .else
+ wsr \tmp, EPS_2 + \level - 2
+ .endif
+
+ .endm
+
/****************************************************************************
* Name: exceptin_backtrace
*
@@ -121,3 +159,49 @@
#endif
.endm
+
+/****************************************************************************
+ * Name: exception_entry
+ *
+ * Description:
+ * Create an interrupt frame and save level specific registers. The rest of
+ * registers will be saved by xtensa_context_save.
+ *
+ ****************************************************************************/
+
+ .macro exception_entry level
+
+ mov a0, sp /* Save SP in A0 */
+ addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
+ s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
+ ps_excp_read a0 \level /* Save interruptee's PS */
+ s32i a0, sp, (4 * REG_PS)
+ rsr a0, EPC_1 + \level - 1 /* Save interruptee's PC */
+ s32i a0, sp, (4 * REG_PC)
+ rsr a0, EXCSAVE_1 + \level - 1 /* Save interruptee's a0 */
+ s32i a0, sp, (4 * REG_A0)
+ s32i a2, sp, (4 * REG_A2)
+
+ .endm
+
+/****************************************************************************
+ * Name: exception_exit
+ *
+ * Description:
+ * Restore level specific registers, the rest should have been restored
+ * before calling this macro.
+ *
+ ****************************************************************************/
+
+ .macro exception_exit level
+
+ l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
+ ps_excp_write a0 \level
+ l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
+ wsr a0, EPC_1 + \level - 1
+ l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
+ l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
+ l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
+ rsync /* Ensure PS and EPC written */
+
+ .endm
diff --git a/arch/xtensa/src/common/xtensa_panic.S b/arch/xtensa/src/common/xtensa_panic.S
index 05eef85e6e..ccb70e22d5 100644
--- a/arch/xtensa/src/common/xtensa_panic.S
+++ b/arch/xtensa/src/common/xtensa_panic.S
@@ -133,8 +133,8 @@ _xtensa_panic:
ps_setup XCHAL_EXCM_LEVEL a0
/* Call C panic handler:
- * Arg1 = Exception code.
- * Arg 2 = Start of the register save area.
+ * Arg1 = Exception code.
+ * Arg2 = Start of the register save area.
*/
rsr ARG1, EXCSAVE_1
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index dd5cd26da1..8695409c3a 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -145,18 +145,9 @@ _xtensa_user_handler:
/* Handle all other exceptions. All can have user-defined handlers. */
/* NOTE: we'll stay on the user stack for exception handling. */
- /* Allocate exception frame and save minimal context. */
+ /* Create interrupt frame and save minimal context. */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, PS /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_1 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ exception_entry 1
/* Save EXCCAUSE and EXCVADDR into the user frame */
@@ -207,14 +198,7 @@ _xtensa_user_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure PS and EPC written */
+ exception_exit 1
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
@@ -242,22 +226,17 @@ _xtensa_user_handler:
_xtensa_syscall_handler:
- /* Allocate stack frame and save A0, A1, and PS */
+ /* Create interrupt frame and save minimal context. */
- mov a0, sp /* Save SP in A0 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, PS /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ exception_entry 1
/* Save rest of interrupt context. */
call0 _xtensa_context_save
- /* Save EPC */
+ /* Save EPC (note that this will overwrite the PC saved by the exception
+ * entry with the correct value skipping the syscall instruction.)
+ */
#if XCHAL_HAVE_LOOPS != 0
/* Get the interruptee's PC and skip over the 'syscall' instruction.
@@ -292,7 +271,7 @@ _xtensa_syscall_handler:
s32i a0, sp, (4 * REG_PC)
#endif
- /* Dispatch the sycall as with other interrupts. */
+ /* Dispatch the syscall as with other interrupts. */
mov a12, sp /* a12 = address of register save area */
@@ -323,14 +302,7 @@ _xtensa_syscall_handler:
/* Restore only level-specific regs (the rest were already restored) */
- l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
- wsr a0, PS
- l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
- wsr a0, EPC_1
- l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
- l32i sp, a2, (4 * REG_A1) /* Retrieve interrupt stack frame */
- l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
- rsync /* Ensure PS and EPC written */
+ exception_exit 1
/* Return from exception. RFE returns from either the UserExceptionVector
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
diff --git a/arch/xtensa/src/common/xtensa_vectors.S b/arch/xtensa/src/common/xtensa_vectors.S
index e0ef459b01..2b4ae27004 100644
--- a/arch/xtensa/src/common/xtensa_vectors.S
+++ b/arch/xtensa/src/common/xtensa_vectors.S
@@ -43,6 +43,7 @@
#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
+#include "xtensa_macros.S"
#include "xtensa.h"
/****************************************************************************
@@ -192,17 +193,8 @@ _xtensa_nmi_vector:
wsr a0, EXCSAVE + XCHAL_NMILEVEL /* Preserve a0 */
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS + XCHAL_NMILEVEL /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_2 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE + XCHAL_NMILEVEL /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ exception_entry XCHAL_NMILEVEL
- s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_NMI_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
@@ -234,17 +226,9 @@ _xtensa_nmi_vector:
_debug_exception_vector:
wsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* Preserve a0 */
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, EPS + XCHAL_DEBUGLEVEL /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC + XCHAL_DEBUGLEVEL /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
- s32i a2, sp, (4 * REG_A2)
+ exception_entry XCHAL_DEBUGLEVEL
+
movi a2, XTENSA_DEBUG_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
@@ -273,6 +257,12 @@ _double_exception_vector:
break 1, 4 /* Unhandled double exception */
#endif
+ /* Can't use excetpion_entry because there is no relationship between EPC1
+ * DEPC and the current level. This can be handled by a separate ifeq
+ * block in the macro, however this part is not used, so let's not add
+ * this special case until we have an application for it.
+ */
+
wsr a0, EXCSAVE_1 /* Preserve a0 */
mov a0, sp /* sp == a1 */
@@ -319,17 +309,8 @@ _kernel_exception_vector:
wsr a0, EXCSAVE_1 /* Preserve a0 */
- mov a0, sp /* sp == a1 */
- addi sp, sp, -XCPTCONTEXT_SIZE /* Allocate interrupt stack frame */
- s32i a0, sp, (4 * REG_A1) /* Save pre-interrupt SP */
- rsr a0, PS /* Save interruptee's PS */
- s32i a0, sp, (4 * REG_PS)
- rsr a0, EPC_1 /* Save interruptee's PC */
- s32i a0, sp, (4 * REG_PC)
- rsr a0, EXCSAVE_1 /* Save interruptee's a0 */
- s32i a0, sp, (4 * REG_A0)
+ exception_entry 1
- s32i a2, sp, (4 * REG_A2)
movi a2, XTENSA_KERNEL_EXCEPTION /* Argument 1: Error code */
call0 _xtensa_panic /* Does not return */
[incubator-nuttx] 04/08: arch/xtensa: Refactor the differences in ABI calls.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 1c94cb5324e9d91e0ed4611bf21ff4cff3230041
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Sat Jun 11 16:05:19 2022 +0200
arch/xtensa: Refactor the differences in ABI calls.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/include/xtensa/xtensa_abi.h | 27 +++++++++-
arch/xtensa/src/common/xtensa_int_handlers.S | 78 ++++++++--------------------
arch/xtensa/src/common/xtensa_panic.S | 20 +++----
arch/xtensa/src/common/xtensa_user_handler.S | 56 ++++++--------------
4 files changed, 71 insertions(+), 110 deletions(-)
diff --git a/arch/xtensa/include/xtensa/xtensa_abi.h b/arch/xtensa/include/xtensa/xtensa_abi.h
index 123b003326..e3b7177a86 100644
--- a/arch/xtensa/include/xtensa/xtensa_abi.h
+++ b/arch/xtensa/include/xtensa/xtensa_abi.h
@@ -112,9 +112,10 @@
* Pre-processor Definitions
****************************************************************************/
-/* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
+/* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION CALL, ENTRY AND RETURN
*
* Convenient where the frame size requirements are the same for both ABIs.
+ * CALL, ARGx are used to make a call to a C function.
* ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
* ENTRY0, RET0 are for frameless functions (no locals, no calls).
*
@@ -149,6 +150,15 @@
# define RET(sz) ret1 sz
# define RET0 ret
+# define CALL call0
+# define ARG1 a2
+# define ARG2 a3
+# define ARG3 a4
+# define ARG4 a5
+# define ARG5 a6
+# define ARG6 a7
+# define RETVAL a2
+
#else
/* Windowed */
@@ -157,6 +167,21 @@
# define RET(sz) retw
# define RET0 retw
+/* These macros are used only in assembly code when calling C functions
+ * with CALL4. This is to help refactor common code with the CALL0 ABI.
+ * call0 can still be used to call assembly function not conforming to the
+ * windowed ABI.
+ */
+
+# define CALL call4
+# define ARG1 a6
+# define ARG2 a7
+# define ARG3 a8
+# define ARG4 a9
+# define ARG5 a10
+# define ARG6 a11
+# define RETVAL a6
+
#endif
/* Index into stack frame.
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index 28946006f9..052cce6e0c 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -131,66 +131,32 @@ g_intstacktop:
ps_setup \level \tmp
-#ifdef __XTENSA_CALL0_ABI__
/* Get mask of pending, enabled interrupts at this level into a2. */
- rsr a2, INTENABLE
+ rsr ARG1, INTENABLE
rsr a3, INTERRUPT
movi a4, \mask
- and a2, a2, a3
- and a2, a2, a4 /* a2 = Set of pending, enabled interrupts for this level */
- beqz a2, 1f /* Nothing to do */
+ and ARG1, ARG1, a3
+ and ARG1, ARG1, a4 /* Set of pending, enabled interrupts for this level */
+ beqz ARG1, 1f /* Nothing to do */
- /* Call xtensa_int_decode passing the address of the register save area
- * as a parameter (A3).
- */
-
- /* Argument 1: Set of CPU interrupt to dispatch */
- mov a3, a12 /* Argument 2: Top of stack = register save area */
- call0 xtensa_int_decode /* Call xtensa_int_decode */
-
- /* On return from xtensa_int_decode, a2 will contain the address of the new
- * register save area. Usually this would be the same as the current SP.
- * But in the event of a context switch, a2 will instead refer to the TCB
- * register save area. This may or may not reside on a stack.
- */
-
- mov a12, a2 /* Switch to the save area of the new thread */
-
-#else
- /* Get mask of pending, enabled interrupts at this level into a6. */
-
- rsr a6, INTENABLE
- rsr a2, INTERRUPT
- movi a3, \mask
- and a6, a6, a2
- 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. We saved the SP in A12
- * before getting here.
+ /* Link the pre-exception frame for debugging. At this point, a12 points to the
+ * allocated and filled exception stack frame (old value of SP in case of
+ * an interrupt stack).
*/
exception_backtrace a12 \level
- /* Call xtensa_int_decode passing the address of the register save area
- * as a parameter (A7).
- */
-
- /* Argument 1: Set of CPU interrupt to dispatch */
- mov a7, a12 /* Argument 2: Top of stack = register save area */
- call4 xtensa_int_decode /* Call xtensa_int_decode */
+ /* Argument 1: Set of CPU interrupt to dispatch */
+ mov ARG2, a12 /* Argument 2: Top of stack = register save area */
+ CALL xtensa_int_decode
- /* On return from xtensa_int_decode, a6 will contain the address of the new
- * register save area. Usually this would be the same as the current SP.
- * But in the event of a context switch, a6 will instead refer to the TCB
- * register save area. This may or may not reside on a stack.
+ /* xtensa_int_decode returns the address of the new register save area.
+ * Usually this would be the same as the current SP. But in the event of
+ * a context switch, it will instead refer to the TCB register save area.
*/
- mov a12, a6 /* Switch to the save area of the new thread */
-#endif
+ mov a12, RETVAL /* Switch to the save area of the new thread */
#if CONFIG_ARCH_INTERRUPTSTACK < 15
addi sp, sp, XCPTCONTEXT_SIZE
@@ -232,17 +198,17 @@ _xtensa_level1_handler:
call0 _xtensa_context_save
- /* Save current SP before (possibly) overwriting it, it's the register save
- * area. This value will be used later by dispatch_c_isr to retrieve the
- * register save area.
- */
-
- mov a12, sp
+ /* Save current SP before (possibly) overwriting it, it's the register save
+ * area. This value will be used later by dispatch_c_isr to retrieve the
+ * register save area.
+ */
+
+ mov a12, sp
- /* Switch to an interrupt stack if we have one */
+ /* Switch to an interrupt stack if we have one */
#if CONFIG_ARCH_INTERRUPTSTACK > 15
- setintstack a13 a14
+ setintstack a13 a14
#endif
/* Decode and dispatch the interrupt. In the event of an interrupt
diff --git a/arch/xtensa/src/common/xtensa_panic.S b/arch/xtensa/src/common/xtensa_panic.S
index dbd2ce7099..05eef85e6e 100644
--- a/arch/xtensa/src/common/xtensa_panic.S
+++ b/arch/xtensa/src/common/xtensa_panic.S
@@ -62,6 +62,7 @@
#include <arch/irq.h>
#include <arch/xtensa/core.h>
+#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa_macros.S"
@@ -129,21 +130,16 @@ _xtensa_panic:
/* Set up PS for C, re-enable hi-pri interrupts, and clear EXCM. */
- ps_setup XCHAL_EXCM_LEVEL a0
+ ps_setup XCHAL_EXCM_LEVEL a0
- /* Call C panic handler: Arg1 (A2) = Exception code; Arg 2 (A3) = start
- * of the register save area.
+ /* Call C panic handler:
+ * Arg1 = Exception code.
+ * Arg 2 = Start of the register save area.
*/
-#ifdef __XTENSA_CALL0_ABI__
- rsr a2, EXCSAVE_1
- mov a3, a12
- call0 xtensa_panic /* Call xtensa_panic. Should not return */
-#else
- rsr a6, EXCSAVE_1
- mov a7, a12
- call4 xtensa_panic /* Call xtensa_panic. Should not return */
-#endif
+ rsr ARG1, EXCSAVE_1
+ mov ARG2, a12
+ CALL xtensa_panic /* Call xtensa_panic. Should not return */
1: j 1b /* loop infinitely */
retw
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index 47adb53634..dd5cd26da1 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -62,6 +62,7 @@
#include <arch/irq.h>
#include <arch/xtensa/core.h>
+#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_specregs.h>
#include "xtensa_macros.S"
@@ -184,7 +185,7 @@ _xtensa_user_handler:
ps_setup 1 a0
- /* Create pseudo base save area. At this point, a12 points to the
+ /* Link the pre-exception frame for debugging. At this point, a12 points to the
* allocated and filled exception stack frame (old value of SP in case of
* an interrupt stack).
*/
@@ -195,16 +196,9 @@ _xtensa_user_handler:
* beginning of the register save area.
*/
-#ifdef __XTENSA_CALL0_ABI__
- rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
- mov a3, a12 /* Argument 2 (a3) = pointer to register save area */
- calx0 xtensa_user /* Call xtensa_user */
-#else
- rsr a6, EXCCAUSE /* Argument 1 (a6) = EXCCAUSE */
- mov a7, a12 /* Argument 2 (a7) = pointer to register save area */
- call4 xtensa_user /* Call xtensa_user */
- mov a12, a6
-#endif
+ rsr ARG1, EXCCAUSE /* Argument 1 = EXCCAUSE */
+ mov ARG2, a12 /* Argument 2 = pointer to register save area */
+ CALL xtensa_user /* Call xtensa_user */
/* Restore registers in preparation to return from interrupt */
@@ -312,30 +306,16 @@ _xtensa_syscall_handler:
ps_setup 1 a0
-#ifdef __XTENSA_CALL0_ABI__
- movi a2, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
- mov a3, a12 /* Argument 2: Top of stack = register save area */
- call0 xtensa_irq_dispatch /* Call xtensa_int_decode */
-
- /* On return from xtensa_irq_dispatch, A2 will contain the address of the new
- * register save area. Usually this would be the same as the current SP.
- * But in the event of a context switch, A2 will instead refer to the TCB
- * register save area.
- */
+ movi ARG1, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
+ mov ARG2, a12 /* Argument 2: Top of stack = register save area */
+ CALL xtensa_irq_dispatch /* Call xtensa_int_decode */
-#else
- movi a6, XTENSA_IRQ_SYSCALL /* Argument 1: IRQ number */
- mov a7, a12 /* Argument 2: Top of stack = register save area */
- call4 xtensa_irq_dispatch /* Call xtensa_int_decode */
-
- /* On return from xtensa_irq_dispatch, A6 will contain the address of the new
- * register save area. Usually this would be the same as the current SP.
- * But in the event of a context switch, A6 will instead refer to the TCB
- * register save area.
+ /* xtensa_irq_dispatch returns the address of the new register save area.
+ * Usually this would be the same as the current SP. But in the event of
+ * a context switch, it will instead refer to the TCB register save area.
*/
- mov a2, a6 /* Switch to the new register save area */
-#endif
+ mov a2, RETVAL /* Switch to the new register save area */
/* Restore registers in preparation to return from interrupt */
@@ -447,15 +427,9 @@ _xtensa_coproc_handler:
* beginning of the register save area.
*/
-#ifdef __XTENSA_CALL0_ABI__
- rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
- mov a3, sp /* Argument 2 (a2) = pointer to register save area */
- calx0 xtensa_user_panic /* Call xtensa_user_panic */
-#else
- rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
- mov a7, sp /* Argument 2 (a2) = pointer to register save area */
- call4 xtensa_user_panic /* Call xtensa_user_panic */
-#endif
+ rsr ARG1, EXCCAUSE /* Argument 1 = EXCCAUSE */
+ mov ARG2, sp /* Argument 2 = pointer to register save area */
+ CALL xtensa_user_panic /* Call xtensa_user_panic */
/* xtensa_user_panic should not return */
[incubator-nuttx] 07/08: arch/xtensa: Move the new saving area directly to A2.
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit fe8fa4ff759f8d592c836b16e8f5d2e1a8e8b2e7
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Mon Jun 13 23:32:06 2022 +0200
arch/xtensa: Move the new saving area directly to A2.
Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
arch/xtensa/src/common/xtensa_int_handlers.S | 26 ++++++++++----------------
arch/xtensa/src/common/xtensa_user_handler.S | 3 ++-
2 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index 10dc7391a7..0d23f6d114 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -110,9 +110,9 @@ g_intstacktop:
* a12 - register save area
*
* Exit Conditions:
- * This macro will use registers a0 and a2-a5 and a12.
- * a1 - May point to the new thread's SP
- * a12 - Points to the register save area (which may not be on the stack).
+ * This macro will use registers a0 and a2-a5 and a2.
+ * a1 - May point to the new thread's SP
+ * a2 - Points to the register save area (which may not be on the stack).
*
****************************************************************************/
@@ -156,7 +156,7 @@ g_intstacktop:
* a context switch, it will instead refer to the TCB register save area.
*/
- mov a12, RETVAL /* Switch to the save area of the new thread */
+ mov a2, RETVAL /* Switch to the save area of the new thread */
#if CONFIG_ARCH_INTERRUPTSTACK < 15
addi sp, sp, XCPTCONTEXT_SIZE
@@ -207,7 +207,7 @@ _xtensa_level1_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -215,7 +215,6 @@ _xtensa_level1_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
@@ -287,7 +286,7 @@ _xtensa_level2_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -295,7 +294,6 @@ _xtensa_level2_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
@@ -342,7 +340,7 @@ _xtensa_level3_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -350,7 +348,6 @@ _xtensa_level3_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
@@ -397,7 +394,7 @@ _xtensa_level4_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -405,7 +402,6 @@ _xtensa_level4_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
@@ -452,7 +448,7 @@ _xtensa_level5_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -460,7 +456,6 @@ _xtensa_level5_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
@@ -507,7 +502,7 @@ _xtensa_level6_handler:
/* Decode and dispatch the interrupt. In the event of an interrupt
* level context dispatch_c_isr() will (1) switch stacks to the new
* thread's and (2) provide the address of the register state save
- * area in a12. NOTE that the state save area may or may not lie
+ * area in a2. NOTE that the state save area may or may not lie
* in the new thread's stack.
*/
@@ -515,7 +510,6 @@ _xtensa_level6_handler:
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */
diff --git a/arch/xtensa/src/common/xtensa_user_handler.S b/arch/xtensa/src/common/xtensa_user_handler.S
index 8695409c3a..0a3b837c52 100644
--- a/arch/xtensa/src/common/xtensa_user_handler.S
+++ b/arch/xtensa/src/common/xtensa_user_handler.S
@@ -191,9 +191,10 @@ _xtensa_user_handler:
mov ARG2, a12 /* Argument 2 = pointer to register save area */
CALL xtensa_user /* Call xtensa_user */
+ mov a2, RETVAL /* a2 = address of new state save area */
+
/* Restore registers in preparation to return from interrupt */
- mov a2, a12 /* a2 = address of new state save area */
call0 _xtensa_context_restore /* (Preserves a2) */
/* Restore only level-specific regs (the rest were already restored) */