You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/04/28 18:51:46 UTC

[incubator-nuttx] branch master updated: arch/xtensa: Replace the xcp context with stack context to improve context switching

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new da273fce0b arch/xtensa: Replace the xcp context with stack context to improve context switching
da273fce0b is described below

commit da273fce0b312fecfc139d5df5a73f8f3068b1b1
Author: Abdelatif Guettouche <ab...@espressif.com>
AuthorDate: Wed Apr 20 23:50:12 2022 +0200

    arch/xtensa: Replace the xcp context with stack context to improve context switching
    
    Signed-off-by: Abdelatif Guettouche <ab...@espressif.com>
---
 arch/xtensa/include/irq.h                       |   5 +-
 arch/xtensa/include/syscall.h                   |   6 +-
 arch/xtensa/src/common/xtensa.h                 |  11 +--
 arch/xtensa/src/common/xtensa_blocktask.c       |   2 +-
 arch/xtensa/src/common/xtensa_copystate.c       |  58 -------------
 arch/xtensa/src/common/xtensa_dumpstate.c       |   5 +-
 arch/xtensa/src/common/xtensa_exit.c            |   2 +-
 arch/xtensa/src/common/xtensa_initialstate.c    |  15 +++-
 arch/xtensa/src/common/xtensa_int_handlers.S    |  13 +++
 arch/xtensa/src/common/xtensa_releasepending.c  |   2 +-
 arch/xtensa/src/common/xtensa_reprioritizertr.c |   2 +-
 arch/xtensa/src/common/xtensa_schedsigaction.c  | 105 ++++++++++++++++++------
 arch/xtensa/src/common/xtensa_sigdeliver.c      |  10 +--
 arch/xtensa/src/common/xtensa_swint.c           |   7 +-
 arch/xtensa/src/common/xtensa_unblocktask.c     |   2 +-
 arch/xtensa/src/esp32/Make.defs                 |   2 +-
 arch/xtensa/src/esp32/esp32_cpustart.c          |   5 +-
 arch/xtensa/src/esp32s2/Make.defs               |   2 +-
 arch/xtensa/src/esp32s3/Make.defs               |   2 +-
 arch/xtensa/src/esp32s3/esp32s3_cpustart.c      |   5 +-
 20 files changed, 134 insertions(+), 127 deletions(-)

diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h
index d21539b351..d0a6f2b92c 100644
--- a/arch/xtensa/include/irq.h
+++ b/arch/xtensa/include/irq.h
@@ -149,12 +149,11 @@ struct xcptcontext
    * another signal handler is executing will be ignored!
    */
 
-  uint32_t saved_pc;
-  uint32_t saved_ps;
+  uint32_t *saved_regs;
 
   /* Register save area */
 
-  uint32_t regs[XCPTCONTEXT_REGS];
+  uint32_t *regs;
 
 #if XCHAL_CP_NUM > 0
   /* Co-processor save area */
diff --git a/arch/xtensa/include/syscall.h b/arch/xtensa/include/syscall.h
index 2e96162157..2e82543d32 100644
--- a/arch/xtensa/include/syscall.h
+++ b/arch/xtensa/include/syscall.h
@@ -100,21 +100,21 @@
 
 /* SYS call 0:
  *
- * int xtensa_saveusercontext(uint32_t *saveregs);
+ * int up_saveusercontext(void *saveregs);
  */
 
 #define SYS_save_context          (0)
 
 /* SYS call 1:
  *
- * void xtensa_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
+ * void xtensa_context_restore(uint32_t **restoreregs) noreturn_function;
  */
 
 #define SYS_restore_context       (1)
 
 /* SYS call 2:
  *
- * void xtensa_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+ * void xtensa_switchcontext(uint32_t **saveregs, uint32_t *restoreregs);
  */
 
 #define SYS_switch_context        (2)
diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h
index 3828cbf527..99bd28646b 100644
--- a/arch/xtensa/src/common/xtensa.h
+++ b/arch/xtensa/src/common/xtensa.h
@@ -103,15 +103,12 @@
 #define IDLETHREAD_STACKSIZE  ((CONFIG_IDLETHREAD_STACKSIZE + 15) & ~15)
 #define IDLETHREAD_STACKWORDS (IDLETHREAD_STACKSIZE >> 2)
 
-/* In the XTENSA model, the state is copied from the stack to the TCB, but
- * only a referenced is passed to get the state from the TCB.
- *
- * REVISIT: It would not be too difficult to save only a pointer to the
- * state save area in the TCB and thus avoid the copy.
+/* In the Xtensa model, the state is saved in stack,
+ * only a reference stored in TCB.
  */
 
-#define xtensa_savestate(regs)    xtensa_copystate(regs, (uint32_t*)CURRENT_REGS)
-#define xtensa_restorestate(regs) do { CURRENT_REGS = regs; } while (0)
+#define xtensa_savestate(regs)    ((regs) = (uint32_t *)CURRENT_REGS)
+#define xtensa_restorestate(regs) (CURRENT_REGS = (regs))
 
 /* Context switching via system calls ***************************************/
 
diff --git a/arch/xtensa/src/common/xtensa_blocktask.c b/arch/xtensa/src/common/xtensa_blocktask.c
index f090994136..c62ad63064 100644
--- a/arch/xtensa/src/common/xtensa_blocktask.c
+++ b/arch/xtensa/src/common/xtensa_blocktask.c
@@ -140,7 +140,7 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state)
 
           /* Then switch contexts */
 
-          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+          xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
 
           /* xtensa_switchcontext forces a context switch to the task at the
            * head of the ready-to-run list.  It does not 'return' in the
diff --git a/arch/xtensa/src/common/xtensa_copystate.c b/arch/xtensa/src/common/xtensa_copystate.c
deleted file mode 100644
index e746b4759f..0000000000
--- a/arch/xtensa/src/common/xtensa_copystate.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************************
- * arch/xtensa/src/common/xtensa_copystate.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <stdint.h>
-#include <arch/irq.h>
-
-#include "xtensa.h"
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: xtensa_copystate
- ****************************************************************************/
-
-/* A little faster than most memcpy's */
-
-void xtensa_copystate(uint32_t *dest, uint32_t *src)
-{
-  int i;
-
-  /* In the XTENSA model, the state is copied from the stack to the TCB,
-   * but only a reference is passed to get the state from the TCB.  So the
-   * following check avoids copying the TCB save area onto itself:
-   */
-
-  if (src != dest)
-    {
-      for (i = 0; i < XCPTCONTEXT_REGS; i++)
-        {
-          *dest++ = *src++;
-        }
-    }
-}
diff --git a/arch/xtensa/src/common/xtensa_dumpstate.c b/arch/xtensa/src/common/xtensa_dumpstate.c
index d2aaec56e1..13dcf03123 100644
--- a/arch/xtensa/src/common/xtensa_dumpstate.c
+++ b/arch/xtensa/src/common/xtensa_dumpstate.c
@@ -295,12 +295,11 @@ void xtensa_dumpstate(void)
 
   if (CURRENT_REGS)
     {
-      memcpy(rtcb->xcp.regs,
-             (uintptr_t *)CURRENT_REGS, XCPTCONTEXT_SIZE);
+      rtcb->xcp.regs = (uint32_t *)CURRENT_REGS;
     }
   else
     {
-      up_saveusercontext(rtcb->xcp.regs);
+      up_saveusercontext(&rtcb->xcp.regs);
     }
 
   /* Dump the registers (if available) */
diff --git a/arch/xtensa/src/common/xtensa_exit.c b/arch/xtensa/src/common/xtensa_exit.c
index 66f529ff8c..f6e0ee3478 100644
--- a/arch/xtensa/src/common/xtensa_exit.c
+++ b/arch/xtensa/src/common/xtensa_exit.c
@@ -145,7 +145,7 @@ void up_exit(int status)
 
   /* Then switch contexts */
 
-  xtensa_context_restore(tcb->xcp.regs);
+  xtensa_context_restore(&tcb->xcp.regs);
 
   /* xtensa_context_restore() should not return but could if the
    * software interrupts are disabled.
diff --git a/arch/xtensa/src/common/xtensa_initialstate.c b/arch/xtensa/src/common/xtensa_initialstate.c
index b059d62cbd..554223ba15 100644
--- a/arch/xtensa/src/common/xtensa_initialstate.c
+++ b/arch/xtensa/src/common/xtensa_initialstate.c
@@ -58,6 +58,10 @@ void up_initial_state(struct tcb_s *tcb)
 {
   struct xcptcontext *xcp = &tcb->xcp;
 
+  /* Initialize the initial exception register context structure */
+
+  memset(xcp, 0, sizeof(struct xcptcontext));
+
   /* Initialize the idle thread stack */
 
   if (tcb->pid == IDLE_PROCESS_ID)
@@ -74,11 +78,18 @@ void up_initial_state(struct tcb_s *tcb)
 
       xtensa_stack_color(tcb->stack_alloc_ptr, 0);
 #endif /* CONFIG_STACK_COLORATION */
+      return;
     }
 
-  /* Initialize the initial exception register context structure */
+  /* Initialize the context registers to stack top */
 
-  memset(xcp, 0, sizeof(struct xcptcontext));
+  xcp->regs = (void *)((uint32_t)tcb->stack_base_ptr +
+                                 tcb->adj_stack_size -
+                                 XCPTCONTEXT_SIZE);
+
+  /* Initialize the xcp registers */
+
+  memset(xcp->regs, 0, XCPTCONTEXT_SIZE);
 
   /* Set initial values of registers */
 
diff --git a/arch/xtensa/src/common/xtensa_int_handlers.S b/arch/xtensa/src/common/xtensa_int_handlers.S
index bc5d141b49..c1d2d94850 100644
--- a/arch/xtensa/src/common/xtensa_int_handlers.S
+++ b/arch/xtensa/src/common/xtensa_int_handlers.S
@@ -137,6 +137,15 @@ g_intstacktop:
 
 	.macro	dispatch_c_isr	level mask tmp
 
+	/* If the interrupt stack is disabled, reserve xcpcontext to ensure
+	 * that signal processing can have a separate xcpcontext to handle
+	 * signal context (ref: xtensa_schedulesigaction.c):
+	 */
+
+#if CONFIG_ARCH_INTERRUPTSTACK < 15
+	addi	sp, sp, -XCPTCONTEXT_SIZE
+#endif
+
 	/* Set up PS for C, enable interrupts above this level and clear EXCM. */
 
 	ps_setup	\level \tmp
@@ -217,6 +226,10 @@ g_intstacktop:
 	mov		a12, a6						/* Switch to the save area of the new thread */
 #endif
 
+#if CONFIG_ARCH_INTERRUPTSTACK < 15
+	addi	sp, sp, XCPTCONTEXT_SIZE
+#endif
+
 	/* Done */
 
 1:
diff --git a/arch/xtensa/src/common/xtensa_releasepending.c b/arch/xtensa/src/common/xtensa_releasepending.c
index 3d8f9c801b..f88e8051aa 100644
--- a/arch/xtensa/src/common/xtensa_releasepending.c
+++ b/arch/xtensa/src/common/xtensa_releasepending.c
@@ -109,7 +109,7 @@ void up_release_pending(void)
            * ready to run list.
            */
 
-          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+          xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
 
           /* xtensa_switchcontext forces a context switch to the task at the
            * head of the ready-to-run list.  It does not 'return' in the
diff --git a/arch/xtensa/src/common/xtensa_reprioritizertr.c b/arch/xtensa/src/common/xtensa_reprioritizertr.c
index 624b73e4e3..5360f7fff4 100644
--- a/arch/xtensa/src/common/xtensa_reprioritizertr.c
+++ b/arch/xtensa/src/common/xtensa_reprioritizertr.c
@@ -163,7 +163,7 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority)
                * ready to run list.
                */
 
-              xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+              xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
 
               /* xtensa_switchcontext forces a context switch to the task at
                * the head of the ready-to-run list. It does not 'return' in
diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c
index fc5f399424..7b376e3c44 100644
--- a/arch/xtensa/src/common/xtensa_schedsigaction.c
+++ b/arch/xtensa/src/common/xtensa_schedsigaction.c
@@ -81,6 +81,7 @@
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver);
+  DEBUGASSERT(tcb != NULL && sigdeliver != NULL);
 
   /* Refuse to handle nested signal actions */
 
@@ -121,20 +122,30 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
           else
             {
-              /* Save the return pc and ps.  These will be restored by the
+              /* Save the context registers.  These will be restored by the
                * signal trampoline after the signals have been delivered.
                *
                * NOTE: that hi-priority interrupts are not disabled.
                */
 
-              tcb->xcp.sigdeliver  = sigdeliver;
-              tcb->xcp.saved_pc    = CURRENT_REGS[REG_PC];
-              tcb->xcp.saved_ps    = CURRENT_REGS[REG_PS];
+              xtensa_savestate(tcb->xcp.saved_regs);
+
+              /* Duplicate the register context.  These will be
+               * restored by the signal trampoline after the signal has
+               * been delivered.
+               */
+
+              CURRENT_REGS = (void *)((uint32_t)CURRENT_REGS -
+                                            XCPTCONTEXT_SIZE);
+
+              memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
+                     XCPTCONTEXT_SIZE);
 
               /* Then set up to vector to the trampoline with interrupts
                * disabled
                */
 
+              tcb->xcp.sigdeliver  = sigdeliver;
               CURRENT_REGS[REG_PC] = (uint32_t)_xtensa_sig_trampoline;
 #ifdef __XTENSA_CALL0_ABI__
               CURRENT_REGS[REG_PS] = (uint32_t)
@@ -144,11 +155,8 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
                   (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE);
 #endif
 
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              xtensa_savestate(tcb->xcp.regs);
+              CURRENT_REGS[REG_A1] = (uint32_t)CURRENT_REGS +
+                                      XCPTCONTEXT_SIZE;
             }
         }
 
@@ -159,16 +167,26 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
       else
         {
-          /* Save the return pc and ps.  These will be restored by the
+          /* Save the context registers.  These will be restored by the
            * signal trampoline after the signals have been delivered.
            *
            * NOTE: that hi-priority interrupts are not disabled.
            */
 
           tcb->xcp.sigdeliver   = sigdeliver;
-          tcb->xcp.saved_pc     = tcb->xcp.regs[REG_PC];
-          tcb->xcp.saved_ps     = tcb->xcp.regs[REG_PS];
+          tcb->xcp.saved_regs   = tcb->xcp.regs;
 
+          /* Duplicate the register context.  These will be
+           * restored by the signal trampoline after the signal has been
+           * delivered.
+           */
+
+          tcb->xcp.regs = (void *)((uint32_t)tcb->xcp.regs -
+                                         XCPTCONTEXT_SIZE);
+          memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
+
+          tcb->xcp.regs[REG_A1]       = (uint32_t)tcb->xcp.regs +
+                                          XCPTCONTEXT_SIZE;
           /* Then set up to vector to the trampoline with interrupts
            * disabled
            */
@@ -250,7 +268,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
                   /* Now tcb on the other CPU can be accessed safely */
 
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
+                  /* Copy tcb->xcp.regs to tcp.xcp.saved_regs. These will be
                    * restored by the signal trampoline after the signal has
                    * been delivered.
                    *
@@ -258,8 +276,21 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
                    */
 
                   tcb->xcp.sigdeliver  = sigdeliver;
-                  tcb->xcp.saved_pc    = tcb->xcp.regs[REG_PC];
-                  tcb->xcp.saved_ps    = tcb->xcp.regs[REG_PS];
+                  tcb->xcp.saved_regs  = tcb->xcp.regs;
+
+                  /* Duplicate the register context.  These will be
+                   * restored by the signal trampoline after the signal has
+                   * been delivered.
+                   */
+
+                  tcb->xcp.regs          = (void *)
+                                            ((uint32_t)tcb->xcp.regs -
+                                            (uint32_t)XCPTCONTEXT_SIZE);
+                  memcpy(tcb->xcp.regs, tcb->xcp.saved_regs,
+                         XCPTCONTEXT_SIZE);
+
+                  tcb->xcp.regs[REG_A1]  = (uint32_t)tcb->xcp.regs +
+                                               (uint32_t)XCPTCONTEXT_SIZE;
 
                   /* Then set up to vector to the trampoline with interrupts
                    * disabled
@@ -278,7 +309,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
                 {
                   /* tcb is running on the same CPU */
 
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
+                  /* Copy tcb->xcp.regs to tcp.xcp.saved_regs. These will be
                    * restored by the signal trampoline after the signal has
                    * been delivered.
                    *
@@ -286,8 +317,21 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
                    */
 
                   tcb->xcp.sigdeliver  = sigdeliver;
-                  tcb->xcp.saved_pc    = CURRENT_REGS[REG_PC];
-                  tcb->xcp.saved_ps    = CURRENT_REGS[REG_PS];
+                  xtensa_savestate(tcb->xcp.saved_regs);
+
+                  /* Duplicate the register context.  These will be
+                   * restored by the signal trampoline after the signal has
+                   * been delivered.
+                   */
+
+                  CURRENT_REGS          = (void *)
+                                           ((uint32_t)CURRENT_REGS -
+                                           (uint32_t)XCPTCONTEXT_SIZE);
+                  memcpy((uint32_t *)CURRENT_REGS, tcb->xcp.saved_regs,
+                         XCPTCONTEXT_SIZE);
+
+                  CURRENT_REGS[REG_A1]  = (uint32_t)CURRENT_REGS +
+                                          (uint32_t)XCPTCONTEXT_SIZE;
 
                   /* Then set up to vector to the trampoline with interrupts
                    * disabled
@@ -301,11 +345,6 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
                   CURRENT_REGS[REG_PS] = (uint32_t)
                       (PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE);
 #endif
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  xtensa_savestate(tcb->xcp.regs);
                 }
 
               /* Increment the IRQ lock count so that when the task is
@@ -338,15 +377,27 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 
       else
         {
-          /* Save the return pc and ps.  These will be restored by the
+          /* Save the context registers.  These will be restored by the
            * signal trampoline after the signals have been delivered.
            *
            * NOTE: that hi-priority interrupts are not disabled.
            */
 
-          tcb->xcp.sigdeliver   = sigdeliver;
-          tcb->xcp.saved_pc     = tcb->xcp.regs[REG_PC];
-          tcb->xcp.saved_ps     = tcb->xcp.regs[REG_PS];
+          tcb->xcp.sigdeliver    = sigdeliver;
+          tcb->xcp.saved_regs    = tcb->xcp.regs;
+
+          /* Duplicate the register context.  These will be
+           * restored by the signal trampoline after the signal has been
+           * delivered.
+           */
+
+          tcb->xcp.regs          = (void *)
+                                    ((uint32_t)tcb->xcp.regs -
+                                    (uint32_t)XCPTCONTEXT_SIZE);
+          memcpy(tcb->xcp.regs, tcb->xcp.saved_regs, XCPTCONTEXT_SIZE);
+
+          tcb->xcp.regs[REG_A1]  = (uint32_t)tcb->xcp.regs +
+                                   (uint32_t)XCPTCONTEXT_SIZE;
 
           /* Increment the IRQ lock count so that when the task is restarted,
            * it will hold the IRQ spinlock.
diff --git a/arch/xtensa/src/common/xtensa_sigdeliver.c b/arch/xtensa/src/common/xtensa_sigdeliver.c
index b07f4fd4b2..9bc8013c30 100644
--- a/arch/xtensa/src/common/xtensa_sigdeliver.c
+++ b/arch/xtensa/src/common/xtensa_sigdeliver.c
@@ -54,7 +54,7 @@
 void xtensa_sig_deliver(void)
 {
   struct tcb_s *rtcb = this_task();
-  uint32_t regs[XCPTCONTEXT_REGS];
+  uint32_t *regs = rtcb->xcp.saved_regs;
 
 #ifdef CONFIG_SMP
   /* In the SMP case, we must terminate the critical section while the signal
@@ -71,10 +71,6 @@ void xtensa_sig_deliver(void)
         rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
   DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
 
-  /* Save the return state on the stack. */
-
-  xtensa_copystate(regs, rtcb->xcp.regs);
-
 #ifdef CONFIG_SMP
   /* In the SMP case, up_schedule_sigaction(0) will have incremented
    * 'irqcount' in order to force us into a critical section.  Save the
@@ -141,8 +137,6 @@ void xtensa_sig_deliver(void)
    * could be modified by a hostile program.
    */
 
-  regs[REG_PC]         = rtcb->xcp.saved_pc;
-  regs[REG_PS]         = rtcb->xcp.saved_ps;
   rtcb->xcp.sigdeliver = NULL;  /* Allows next handler to be scheduled */
 
   /* Issue:
@@ -184,5 +178,5 @@ void xtensa_sig_deliver(void)
    */
 
   board_autoled_off(LED_SIGNAL);
-  xtensa_context_restore(regs);
+  xtensa_context_restore(&regs);
 }
diff --git a/arch/xtensa/src/common/xtensa_swint.c b/arch/xtensa/src/common/xtensa_swint.c
index 42c0ef6aa7..d9a69927d7 100644
--- a/arch/xtensa/src/common/xtensa_swint.c
+++ b/arch/xtensa/src/common/xtensa_swint.c
@@ -103,7 +103,7 @@ int xtensa_swint(int irq, void *context, void *arg)
       case SYS_save_context:
         {
           DEBUGASSERT(regs[REG_A3] != 0);
-          memcpy((uint32_t *)regs[REG_A3], regs, (4 * XCPTCONTEXT_REGS));
+          memcpy(*(uint32_t **)regs[REG_A3], regs, XCPTCONTEXT_SIZE);
 #if XCHAL_CP_NUM > 0
           cpstate = (uintptr_t)regs[REG_A3] + cpstate_off;
           xtensa_coproc_savestate((struct xtensa_cpstate_s *)cpstate);
@@ -132,7 +132,7 @@ int xtensa_swint(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_A3] != 0);
-          CURRENT_REGS = (uint32_t *)regs[REG_A3];
+          CURRENT_REGS = *(uint32_t **)regs[REG_A3];
 #if XCHAL_CP_NUM > 0
           cpstate = (uintptr_t)regs[REG_A3] + cpstate_off;
           xtensa_coproc_restorestate((struct xtensa_cpstate_s *)cpstate);
@@ -161,8 +161,7 @@ int xtensa_swint(int irq, void *context, void *arg)
       case SYS_switch_context:
         {
           DEBUGASSERT(regs[REG_A3] != 0 && regs[REG_A4] != 0);
-
-          memcpy((uint32_t *)regs[REG_A3], regs, (4 * XCPTCONTEXT_REGS));
+          *(uint32_t **)regs[REG_A3] = regs;
           CURRENT_REGS = (uint32_t *)regs[REG_A4];
         }
 
diff --git a/arch/xtensa/src/common/xtensa_unblocktask.c b/arch/xtensa/src/common/xtensa_unblocktask.c
index 4d975fbbd1..c1bcf7afb5 100644
--- a/arch/xtensa/src/common/xtensa_unblocktask.c
+++ b/arch/xtensa/src/common/xtensa_unblocktask.c
@@ -125,7 +125,7 @@ void up_unblock_task(struct tcb_s *tcb)
            * ready to run list.
            */
 
-          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+          xtensa_switchcontext(&rtcb->xcp.regs, nexttcb->xcp.regs);
 
           /* xtensa_switchcontext forces a context switch to the task at the
            * head of the ready-to-run list.  It does not 'return' in the
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 3e084afa09..1161e8bfe4 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -31,7 +31,7 @@ HEAD_CSRC  = esp32_start.c esp32_wdt.c
 CMN_ASRCS  = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S xtensa_panic.S
 CMN_ASRCS += xtensa_sigtramp.S
 
-CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c
+CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c
 CMN_CSRCS += xtensa_cpenable.c xtensa_createstack.c xtensa_exit.c
 CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c xtensa_interruptcontext.c
 CMN_CSRCS += xtensa_irqdispatch.c xtensa_lowputs.c xtensa_mdelay.c
diff --git a/arch/xtensa/src/esp32/esp32_cpustart.c b/arch/xtensa/src/esp32/esp32_cpustart.c
index 6a9fe3ee40..bc54defc08 100644
--- a/arch/xtensa/src/esp32/esp32_cpustart.c
+++ b/arch/xtensa/src/esp32/esp32_cpustart.c
@@ -135,7 +135,8 @@ void IRAM_ATTR xtensa_appcpu_start(void)
    * is to switch to a well-known IDLE thread stack.
    */
 
-  sp = (uint32_t)tcb->stack_base_ptr + tcb->adj_stack_size;
+  sp = (uint32_t)tcb->stack_base_ptr + tcb->adj_stack_size -
+       XCPTCONTEXT_SIZE;
   __asm__ __volatile__("mov sp, %0\n" : : "r"(sp));
 
   sinfo("CPU%d Started\n", up_cpu_index());
@@ -208,7 +209,7 @@ void IRAM_ATTR xtensa_appcpu_start(void)
    * be the CPUs NULL task.
    */
 
-  xtensa_context_restore(tcb->xcp.regs);
+  xtensa_context_restore(&tcb->xcp.regs);
 }
 
 /****************************************************************************
diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs
index 5cb84c637d..6e40fa7b4d 100644
--- a/arch/xtensa/src/esp32s2/Make.defs
+++ b/arch/xtensa/src/esp32s2/Make.defs
@@ -31,7 +31,7 @@ HEAD_CSRC  = esp32s2_start.c esp32s2_wdt.c
 CMN_ASRCS  = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S xtensa_panic.S
 CMN_ASRCS += xtensa_sigtramp.S
 
-CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c
+CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c
 CMN_CSRCS += xtensa_cpenable.c xtensa_createstack.c xtensa_exit.c
 CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c xtensa_interruptcontext.c
 CMN_CSRCS += xtensa_irqdispatch.c xtensa_lowputs.c xtensa_mdelay.c
diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs
index cd5373e5c5..8987a2b6b9 100644
--- a/arch/xtensa/src/esp32s3/Make.defs
+++ b/arch/xtensa/src/esp32s3/Make.defs
@@ -31,7 +31,7 @@ HEAD_CSRC  = esp32s3_start.c
 CMN_ASRCS  = xtensa_context.S xtensa_coproc.S xtensa_cpuint.S xtensa_panic.S
 CMN_ASRCS += xtensa_sigtramp.S
 
-CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c
+CMN_CSRCS  = xtensa_assert.c xtensa_blocktask.c
 CMN_CSRCS += xtensa_cpenable.c xtensa_createstack.c xtensa_exit.c
 CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c xtensa_interruptcontext.c
 CMN_CSRCS += xtensa_irqdispatch.c xtensa_lowputs.c xtensa_mdelay.c
diff --git a/arch/xtensa/src/esp32s3/esp32s3_cpustart.c b/arch/xtensa/src/esp32s3/esp32s3_cpustart.c
index 6c424fb6b5..b907b06692 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_cpustart.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_cpustart.c
@@ -115,7 +115,8 @@ void xtensa_appcpu_start(void)
    * is to switch to a well-known IDLE thread stack.
    */
 
-  sp = (uint32_t)tcb->stack_base_ptr + tcb->adj_stack_size;
+  sp = (uint32_t)tcb->stack_base_ptr + tcb->adj_stack_size -
+       XCPTCONTEXT_SIZE;
   __asm__ __volatile__("mov sp, %0\n" : : "r"(sp));
 
   sinfo("CPU%d Started\n", up_cpu_index());
@@ -168,7 +169,7 @@ void xtensa_appcpu_start(void)
    * be the CPUs NULL task.
    */
 
-  xtensa_context_restore(tcb->xcp.regs);
+  xtensa_context_restore(&tcb->xcp.regs);
 }
 
 /****************************************************************************