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

xiaoxiang pushed a commit to branch releases/12.7
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ee818235464207d4de87722f7e0d54fc30c34ea7
Author: hujun5 <[email protected]>
AuthorDate: Fri Jul 5 19:39:58 2024 +0800

    arm: g_current_regs is only used to determine if we are in irq, with other 
functionalities removed.
    
    reason:
    by doing this we can reduce context switch time,
    When we exit from an interrupt handler, we directly use tcb->xcp.regs
    
    before
    size nuttx
       text    data     bss     dec     hex filename
     225920     409   30925  257254   3ece6 nuttx
    
    after
       text    data     bss     dec     hex filename
     225604     409   30925  256938   3ebaa nuttx
    
     szie change -316
    
    Signed-off-by: hujun5 <[email protected]>
---
 arch/arm/src/arm/arm_doirq.c                      |  10 +-
 arch/arm/src/arm/arm_schedulesigaction.c          |  67 +----
 arch/arm/src/arm/arm_syscall.c                    |  22 +-
 arch/arm/src/armv6-m/arm_doirq.c                  |  11 +-
 arch/arm/src/armv6-m/arm_schedulesigaction.c      | 308 +++-----------------
 arch/arm/src/armv6-m/arm_svcall.c                 |  26 +-
 arch/arm/src/armv7-a/arm_cpupause.c               |  12 +-
 arch/arm/src/armv7-a/arm_cpustart.c               |  12 +-
 arch/arm/src/armv7-a/arm_doirq.c                  |  23 +-
 arch/arm/src/armv7-a/arm_schedulesigaction.c      | 280 ++----------------
 arch/arm/src/armv7-a/arm_syscall.c                |  25 +-
 arch/arm/src/armv7-m/arm_doirq.c                  |  11 +-
 arch/arm/src/armv7-m/arm_schedulesigaction.c      | 328 +++-------------------
 arch/arm/src/armv7-m/arm_svcall.c                 |  27 +-
 arch/arm/src/armv7-r/arm_cpupause.c               |  12 +-
 arch/arm/src/armv7-r/arm_cpustart.c               |   6 +-
 arch/arm/src/armv7-r/arm_doirq.c                  |  23 +-
 arch/arm/src/armv7-r/arm_schedulesigaction.c      | 288 ++-----------------
 arch/arm/src/armv7-r/arm_syscall.c                |  16 +-
 arch/arm/src/armv8-m/arm_doirq.c                  |  11 +-
 arch/arm/src/armv8-m/arm_schedulesigaction.c      | 321 +++------------------
 arch/arm/src/armv8-m/arm_svcall.c                 |  25 +-
 arch/arm/src/armv8-r/arm_doirq.c                  |  19 +-
 arch/arm/src/armv8-r/arm_schedulesigaction.c      | 302 ++------------------
 arch/arm/src/armv8-r/arm_syscall.c                |  15 +-
 arch/arm/src/common/arm_internal.h                |   5 -
 arch/arm/src/common/arm_switchcontext.c           |  12 -
 arch/arm/src/cxd56xx/cxd56_cpupause.c             |  12 +-
 arch/arm/src/dm320/dm320_decodeirq.c              |   7 +-
 arch/arm/src/imx1/imx_decodeirq.c                 |   6 +-
 arch/arm/src/lc823450/lc823450_cpupause.c         |  12 +-
 arch/arm/src/lpc214x/lpc214x_decodeirq.c          |   4 +
 arch/arm/src/lpc2378/lpc23xx_decodeirq.c          |   4 +
 arch/arm/src/lpc31xx/lpc31_decodeirq.c            |   8 +-
 arch/arm/src/moxart/moxart_irq.c                  |   2 +
 arch/arm/src/rp2040/rp2040_cpupause.c             |  12 +-
 arch/arm/src/sam34/sam4cm_cpupause.c              |  12 +-
 arch/arm/src/str71x/str71x_decodeirq.c            |   4 +
 arch/arm/src/tlsr82/tc32/tc32_doirq.c             |  13 +-
 arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c |  64 +----
 40 files changed, 404 insertions(+), 1973 deletions(-)

diff --git a/arch/arm/src/arm/arm_doirq.c b/arch/arm/src/arm/arm_doirq.c
index 9340eafb02..6cc7da46bd 100644
--- a/arch/arm/src/arm/arm_doirq.c
+++ b/arch/arm/src/arm/arm_doirq.c
@@ -58,6 +58,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -71,6 +73,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    */
 
   up_set_current_regs(regs);
+  tcb->xcp.regs = regs;
 
   /* Acknowledge the interrupt */
 
@@ -79,6 +82,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
+  tcb = this_task();
 
   /* Check for a context switch.  If a context switch occurred, then
    * current_regs will have a different value than it did on entry.  If an
@@ -87,7 +91,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
    * returning from the interrupt.
    */
 
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -104,9 +108,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
        * crashes.
        */
 
-      g_running_tasks[this_cpu()] = this_task();
+      g_running_tasks[this_cpu()] = tcb;
 
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/arm/src/arm/arm_schedulesigaction.c 
b/arch/arm/src/arm/arm_schedulesigaction.c
index d141a33a00..a0a4017bf4 100644
--- a/arch/arm/src/arm/arm_schedulesigaction.c
+++ b/arch/arm/src/arm/arm_schedulesigaction.c
@@ -89,70 +89,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
        * being delivered to the currently executing task.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and
-           * a task is signalling itself for some reason.
-           */
-
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now. */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the
-           * interrupted task is the same as the one that
-           * must receive the signal, then we will have to modify
-           * the return state as well as the state in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following
-           * logic would fail in the strange case where we are in an
-           * interrupt handler, the thread is signalling itself, but
-           * a context switch to another task has occurred so that
-           * current_regs does not refer to the thread of this_task()!
-           */
-
-          else
-            {
-              /* Save the return lr and cpsr and one scratch register
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              /* And make sure that the saved context in the TCB
-               * is the same as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
+          /* In this case just deliver the signal now. */
 
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP]    = (uint32_t)(up_current_regs() +
-                                                         XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
-
-              up_current_regs()[REG_PC]    = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_CPSR]  = PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT;
-#ifdef CONFIG_ARM_THUMB
-              up_current_regs()[REG_CPSR] |= PSR_T_BIT;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
 
       /* Otherwise, we are (1) signaling a task is not running
diff --git a/arch/arm/src/arm/arm_syscall.c b/arch/arm/src/arm/arm_syscall.c
index 867d33536c..be95d916ff 100644
--- a/arch/arm/src/arm/arm_syscall.c
+++ b/arch/arm/src/arm/arm_syscall.c
@@ -54,7 +54,7 @@
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb;
+  struct tcb_s *tcb = this_task();
   uint32_t cmd;
   int cpu;
 
@@ -66,6 +66,7 @@ uint32_t *arm_syscall(uint32_t *regs)
    * current_regs is also used to manage interrupt level context switches.
    */
 
+  tcb->xcp.regs = regs;
   up_set_current_regs(regs);
 
   /* The SYSCALL command is in R0 on entry.  Parameters follow in R1..R7 */
@@ -94,7 +95,7 @@ uint32_t *arm_syscall(uint32_t *regs)
            * set will determine the restored context.
            */
 
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
           DEBUGASSERT(up_current_regs());
         }
         break;
@@ -133,15 +134,9 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-#ifdef CONFIG_ARCH_ADDRENV
-  /* Check for a context switch.  If a context switch occurred, then
-   * current_regs will have a different value than it did on entry.  If an
-   * interrupt level context switch has occurred, then establish the correct
-   * address environment before returning from the interrupt.
-   */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
+#ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
        * running task is closed down gracefully (data caches dump,
        * MMU flushed) and set up the address environment for the new
@@ -149,13 +144,8 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       addrenv_switch(NULL);
-    }
 #endif
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
-    {
       /* Record the new "running" task.  g_running_tasks[] is only used by
        * assertion logic for reporting crashes.
        */
@@ -181,5 +171,5 @@ uint32_t *arm_syscall(uint32_t *regs)
    * SYS_context_switch system call.
    */
 
-  return regs;
+  return tcb->xcp.regs;
 }
diff --git a/arch/arm/src/armv6-m/arm_doirq.c b/arch/arm/src/armv6-m/arm_doirq.c
index b5a7af4e22..566d9390a0 100644
--- a/arch/arm/src/armv6-m/arm_doirq.c
+++ b/arch/arm/src/armv6-m/arm_doirq.c
@@ -42,6 +42,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -49,6 +51,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
+      tcb->xcp.regs = regs;
       up_set_current_regs(regs);
     }
 
@@ -68,17 +71,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
-      /* Restore the cpu lock */
+      tcb = this_task();
 
-      if (regs != up_current_regs())
+      if (regs != tcb->xcp.regs)
         {
           /* Record the new "running" task when context switch occurred.
            * g_running_tasks[] is only used by assertion logic for reporting
            * crashes.
            */
 
-          g_running_tasks[this_cpu()] = this_task();
-          regs = up_current_regs();
+          g_running_tasks[this_cpu()] = tcb;
+          regs = tcb->xcp.regs;
         }
 
       /* Update the current_regs to NULL. */
diff --git a/arch/arm/src/armv6-m/arm_schedulesigaction.c 
b/arch/arm/src/armv6-m/arm_schedulesigaction.c
index 3272dd4dc7..4e5da4c5ef 100644
--- a/arch/arm/src/armv6-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv6-m/arm_schedulesigaction.c
@@ -78,7 +78,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -94,158 +93,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
        * to the currently executing task.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handle will run in a critical section!
            */
 
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handle will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state in
-           * the TCB.
-           */
-
-          else
-            {
-              /* Save the return PC, CPSR and PRIMASK
-               * registers (and perhaps also the LR).  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
-                                                      XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled.  The kernel-space trampoline must run in
-               * privileged thread mode.
-               */
-
-              up_current_regs()[REG_PC]         = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_PRIMASK]    = 1;
-              up_current_regs()[REG_XPSR]       = ARMV6M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-              up_current_regs()[REG_LR]         = EXC_RETURN_THREAD;
-              up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
-              up_current_regs()[REG_CONTROL]    = getcontrol() &
-                                                   ~CONTROL_NPRIV;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling* some non-running task.
-       */
-
       else
         {
-          /* Save the return PC, CPSR and PRIMASK
-           * registers (and perhaps also the LR).  These will be restored
-           * by the signal trampoline after the signal has been delivered.
-           */
-
-          /* Save the current register context location */
-
-          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled.  We must already be in privileged thread mode to be
-           * here.
-           */
-
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-          tcb->xcp.regs[REG_PRIMASK] = 1;
-          tcb->xcp.regs[REG_XPSR]    = ARMV6M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-        }
-    }
-}
-#endif /* !CONFIG_SMP */
-
-#ifdef CONFIG_SMP
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
           /* CASE 2:  The task that needs to receive the signal is running.
            * This could happen if the task is running on another CPU OR if
            * we are in an interrupt handler and the task is running on this
@@ -254,122 +115,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
            * state as well as the state in the TCB.
            */
 
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                         XCPTCONTEXT_SIZE;
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  We must already be in privileged thread mode
-                   * to be here.
-                   */
-
-                  tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-                  tcb->xcp.regs[REG_PRIMASK] = 1;
-                  tcb->xcp.regs[REG_XPSR]    = ARMV6M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-                  tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These
-                   * will be restored by the signal trampoline after the
-                   * signal has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_PC]      = (uint32_t)arm_sigdeliver;
-                  up_current_regs()[REG_PRIMASK] = 1;
-                  up_current_regs()[REG_XPSR]    = ARMV6M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  up_current_regs()[REG_LR]      = EXC_RETURN_THREAD;
-                  up_current_regs()[REG_CONTROL] = getcontrol() &
-                                                    ~CONTROL_NPRIV;
-#endif
-                }
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
+           */
 
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-              /* RESUME the other CPU if it was PAUSED */
+          if (cpu != me)
+            {
+              /* Pause the CPU */
 
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
+              up_cpu_pause(cpu);
             }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
+#endif
 
-      else
-        {
           /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
            * registers (and perhaps also the LR).  These will be restored
            * by the signal trampoline after the signal has been delivered.
@@ -377,34 +138,43 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 
           /* Save the current register context location */
 
-          tcb->xcp.saved_regs        = tcb->xcp.regs;
+          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);
+          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
+          tcb->xcp.regs[REG_SP]         = (uint32_t)tcb->xcp.regs +
+                                                    XCPTCONTEXT_SIZE;
 
           /* Then set up to vector to the trampoline with interrupts
            * disabled.  We must already be in privileged thread mode to be
            * here.
            */
 
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-          tcb->xcp.regs[REG_PRIMASK] = 1;
-          tcb->xcp.regs[REG_XPSR]    = ARMV6M_XPSR_T;
+          tcb->xcp.regs[REG_PC]         = (uint32_t)arm_sigdeliver;
+          tcb->xcp.regs[REG_PRIMASK]    = 1;
+          tcb->xcp.regs[REG_XPSR]       = ARMV6M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
+          tcb->xcp.regs[REG_LR]         = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
+#endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
 #endif
         }
     }
 }
-#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv6-m/arm_svcall.c 
b/arch/arm/src/armv6-m/arm_svcall.c
index 408a40c249..62f57e302a 100644
--- a/arch/arm/src/armv6-m/arm_svcall.c
+++ b/arch/arm/src/armv6-m/arm_svcall.c
@@ -117,6 +117,7 @@ static void dispatch_syscall(void)
 
 int arm_svcall(int irq, void *context, void *arg)
 {
+  struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
   uint32_t cmd;
 
@@ -167,7 +168,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
 
@@ -192,7 +193,7 @@ int arm_svcall(int irq, void *context, void *arg)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -450,23 +451,20 @@ int arm_svcall(int irq, void *context, void *arg)
 #  ifndef CONFIG_DEBUG_SVCALL
   if (cmd > SYS_switch_context)
 #  else
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
 #  endif
     {
+      regs = (uint32_t *)tcb->xcp.regs;
+
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R0],  up_current_regs()[REG_R1],
-              up_current_regs()[REG_R2],  up_current_regs()[REG_R3],
-              up_current_regs()[REG_R4],  up_current_regs()[REG_R5],
-              up_current_regs()[REG_R6],  up_current_regs()[REG_R7]);
+              regs[REG_R0],  regs[REG_R1], regs[REG_R2],  regs[REG_R3],
+              regs[REG_R4],  regs[REG_R5], regs[REG_R6],  regs[REG_R7]);
       svcinfo("  R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R8],  up_current_regs()[REG_R9],
-              up_current_regs()[REG_R10], up_current_regs()[REG_R11],
-              up_current_regs()[REG_R12], up_current_regs()[REG_R13],
-              up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
-      svcinfo(" PSR: %08x PRIMASK: %08x EXC_RETURN: %08x\n",
-              up_current_regs()[REG_XPSR], up_current_regs()[REG_PRIMASK],
-              up_current_regs()[REG_EXC_RETURN]);
+              regs[REG_R8],  regs[REG_R9], regs[REG_R10], regs[REG_R11],
+              regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
+      svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
+              regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
     }
 #  ifdef CONFIG_DEBUG_SVCALL
   else
diff --git a/arch/arm/src/armv7-a/arm_cpupause.c 
b/arch/arm/src/armv7-a/arm_cpupause.c
index 7077d905a3..b36c6de7aa 100644
--- a/arch/arm/src/armv7-a/arm_cpupause.c
+++ b/arch/arm/src/armv7-a/arm_cpupause.c
@@ -117,11 +117,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -207,11 +203,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/armv7-a/arm_cpustart.c 
b/arch/arm/src/armv7-a/arm_cpustart.c
index 6e04f872db..e358d54b01 100644
--- a/arch/arm/src/armv7-a/arm_cpustart.c
+++ b/arch/arm/src/armv7-a/arm_cpustart.c
@@ -79,18 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Dump registers so that we can see what is going to happen on return */
+  UNUSED(tcb);
 
-#if 0
-  up_dump_register(tcb->xcp.regs);
-#endif
-
-  /* Then switch contexts. This instantiates the exception context of the
-   * tcb at the head of the assigned task list.  In this case, this should
-   * be the CPUs NULL task.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
   return OK;
 }
 
diff --git a/arch/arm/src/armv7-a/arm_doirq.c b/arch/arm/src/armv7-a/arm_doirq.c
index cb68f8b55a..460bb9a6c4 100644
--- a/arch/arm/src/armv7-a/arm_doirq.c
+++ b/arch/arm/src/armv7-a/arm_doirq.c
@@ -53,6 +53,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -61,6 +63,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  /* if irq == GIC_SMP_CPUSTART
+   * We are initiating the multi-core jumping state to up_idle,
+   * and we will use this_task(). Therefore, it cannot be overridden.
+   */
+
+#ifdef CONFIG_SMP
+  if (irq != GIC_SMP_CPUSTART)
+#endif
+    {
+      tcb->xcp.regs = regs;
+    }
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -70,10 +84,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
+  tcb = this_task();
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
 #ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
@@ -90,8 +103,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
        * crashes.
        */
 
-      g_running_tasks[this_cpu()] = this_task();
-      regs = up_current_regs();
+      g_running_tasks[this_cpu()] = tcb;
+      regs = tcb->xcp.regs;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/arm/src/armv7-a/arm_schedulesigaction.c 
b/arch/arm/src/armv7-a/arm_schedulesigaction.c
index b49534c4c6..187af9b18b 100644
--- a/arch/arm/src/armv7-a/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-a/arm_schedulesigaction.c
@@ -77,7 +77,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -92,157 +91,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
        * to task that is currently executing on this CPU.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handler will run in a critical section!
            */
 
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state
-           * in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following logic
-           * would fail in the strange case where we are in an interrupt
-           * handler, the thread is signaling itself, but a context switch
-           * to another task has occurred so that current_regs does not
-           * refer to the thread of this_task()!
-           */
-
-          else
-            {
-              /* Save the return lr and cpsr and one scratch register
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP]    = (uint32_t)(up_current_regs() +
-                                                         XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
-
-              up_current_regs()[REG_PC]    = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                               PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-              up_current_regs()[REG_CPSR] |= PSR_T_BIT;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
-
       else
         {
-          /* Save the return lr and cpsr and one scratch register.  These
-           * will be restored by the signal trampoline after the signals
-           * have been delivered.
-           */
-
-          /* Save the current register context location */
-
-          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_SP]    = (uint32_t)tcb->xcp.regs +
-                                               XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled
-           */
-
-          tcb->xcp.regs[REG_PC]    = (uint32_t)arm_sigdeliver;
-          tcb->xcp.regs[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT | PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-          tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
-#endif
-        }
-    }
-}
-#endif /* !CONFIG_SMP */
-
-#ifdef CONFIG_SMP
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
           /* CASE 2:  The task that needs to receive the signal is running.
            * This could happen if the task is running on another CPU OR if
            * we are in an interrupt handler and the task is running on this
@@ -251,118 +113,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
            * state as well as the state in the TCB.
            */
 
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]    = (uint32_t)tcb->xcp.regs +
-                                                       XCPTCONTEXT_SIZE;
-
-                  /* Then set up to vector to the trampoline with interrupts
-                   * disabled
-                   */
-
-                  tcb->xcp.regs[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  tcb->xcp.regs[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These will
-                   * be restored by the signal trampoline after the signal
-                   * has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  up_current_regs()[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                                   PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  up_current_regs()[REG_CPSR] |= PSR_T_BIT;
-#endif
-                }
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
+           */
 
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-              /* RESUME the other CPU if it was PAUSED */
+          if (cpu != me)
+            {
+              /* Pause the CPU */
 
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
+              up_cpu_pause(cpu);
             }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
+#endif
 
-      else
-        {
           /* Save the return lr and cpsr and one scratch register.  These
            * will be restored by the signal trampoline after the signals
            * have been delivered.
@@ -394,7 +160,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 #ifdef CONFIG_ARM_THUMB
           tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
+#endif
         }
     }
 }
-#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv7-a/arm_syscall.c 
b/arch/arm/src/armv7-a/arm_syscall.c
index feca24da09..9a8df57bdd 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -160,7 +160,7 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb;
+  struct tcb_s *tcb = this_task();
   uint32_t cmd;
   int cpu;
 #ifdef CONFIG_BUILD_KERNEL
@@ -171,6 +171,8 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  tcb->xcp.regs = regs;
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -272,7 +274,7 @@ uint32_t *arm_syscall(uint32_t *regs)
            * set will determine the restored context.
            */
 
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
           DEBUGASSERT(up_current_regs());
         }
         break;
@@ -298,7 +300,7 @@ uint32_t *arm_syscall(uint32_t *regs)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -565,15 +567,9 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-#ifdef CONFIG_ARCH_ADDRENV
-  /* Check for a context switch.  If a context switch occurred, then
-   * current_regs will have a different value than it did on entry.  If an
-   * interrupt level context switch has occurred, then establish the correct
-   * address environment before returning from the interrupt.
-   */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
+#ifdef CONFIG_ARCH_ADDRENV
       /* Make sure that the address environment for the previously
        * running task is closed down gracefully (data caches dump,
        * MMU flushed) and set up the address environment for the new
@@ -581,13 +577,8 @@ uint32_t *arm_syscall(uint32_t *regs)
        */
 
       addrenv_switch(NULL);
-    }
 #endif
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
-    {
       /* Record the new "running" task.  g_running_tasks[] is only used by
        * assertion logic for reporting crashes.
        */
@@ -599,7 +590,7 @@ uint32_t *arm_syscall(uint32_t *regs)
       /* Restore the cpu lock */
 
       restore_critical_section(tcb, cpu);
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Report what happened */
diff --git a/arch/arm/src/armv7-m/arm_doirq.c b/arch/arm/src/armv7-m/arm_doirq.c
index 66af948ef3..c1370659c9 100644
--- a/arch/arm/src/armv7-m/arm_doirq.c
+++ b/arch/arm/src/armv7-m/arm_doirq.c
@@ -42,6 +42,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -49,6 +51,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
+      tcb->xcp.regs = regs;
       up_set_current_regs(regs);
     }
 
@@ -68,17 +71,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (regs[REG_EXC_RETURN] & EXC_RETURN_THREAD_MODE)
     {
-      /* Restore the cpu lock */
+      tcb = this_task();
 
-      if (regs != up_current_regs())
+      if (regs != tcb->xcp.regs)
         {
           /* Record the new "running" task when context switch occurred.
            * g_running_tasks[] is only used by assertion logic for reporting
            * crashes.
            */
 
-          g_running_tasks[this_cpu()] = this_task();
-          regs = up_current_regs();
+          g_running_tasks[this_cpu()] = tcb;
+          regs = tcb->xcp.regs;
         }
 
       /* Update the current_regs to NULL. */
diff --git a/arch/arm/src/armv7-m/arm_schedulesigaction.c 
b/arch/arm/src/armv7-m/arm_schedulesigaction.c
index 1aea1dd908..531e295bbd 100644
--- a/arch/arm/src/armv7-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-m/arm_schedulesigaction.c
@@ -79,7 +79,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -95,167 +94,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
        * to the currently executing task.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handle will run in a critical section!
            */
 
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handle will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state in
-           * the TCB.
-           */
-
-          else
-            {
-              /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
-               * registers (and perhaps also the LR).  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
-                                                      XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled.  The kernel-space trampoline must run in
-               * privileged thread mode.
-               */
-
-              up_current_regs()[REG_PC]         = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV7M_USEBASEPRI
-              up_current_regs()[REG_BASEPRI]    =
-                                                  NVIC_SYSH_DISABLE_PRIORITY;
-#else
-              up_current_regs()[REG_PRIMASK]    = 1;
-#endif
-              up_current_regs()[REG_XPSR]       = ARMV7M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-              up_current_regs()[REG_LR]         = EXC_RETURN_THREAD;
-              up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
-              up_current_regs()[REG_CONTROL]    = getcontrol() &
-                                                   ~CONTROL_NPRIV;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling* some non-running task.
-       */
-
       else
         {
-          /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
-           * registers (and perhaps also the LR).  These will be restored
-           * by the signal trampoline after the signal has been delivered.
-           */
-
-          /* Save the current register context location */
-
-          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled.  We must already be in privileged thread mode to be
-           * here.
-           */
-
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV7M_USEBASEPRI
-          tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
-#else
-          tcb->xcp.regs[REG_PRIMASK] = 1;
-#endif
-          tcb->xcp.regs[REG_XPSR]    = ARMV7M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-        }
-    }
-}
-#endif /* !CONFIG_SMP */
-
-#ifdef CONFIG_SMP
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
           /* CASE 2:  The task that needs to receive the signal is running.
            * This could happen if the task is running on another CPU OR if
            * we are in an interrupt handler and the task is running on this
@@ -264,131 +116,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
            * state as well as the state in the TCB.
            */
 
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                         XCPTCONTEXT_SIZE;
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  We must already be in privileged thread mode
-                   * to be here.
-                   */
-
-                  tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV7M_USEBASEPRI
-                  tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
-#else
-                  tcb->xcp.regs[REG_PRIMASK] = 1;
-#endif
-                  tcb->xcp.regs[REG_XPSR]    = ARMV7M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-                  tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These
-                   * will be restored by the signal trampoline after the
-                   * signal has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV7M_USEBASEPRI
-                  up_current_regs()[REG_BASEPRI] =
-                  NVIC_SYSH_DISABLE_PRIORITY;
-#else
-                  up_current_regs()[REG_PRIMASK] = 1;
-#endif
-                  up_current_regs()[REG_XPSR]    = ARMV7M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  up_current_regs()[REG_LR]      = EXC_RETURN_THREAD;
-                  up_current_regs()[REG_CONTROL] = getcontrol() &
-                                                    ~CONTROL_NPRIV;
-#endif
-                }
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
+           */
 
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-              /* RESUME the other CPU if it was PAUSED */
+          if (cpu != me)
+            {
+              /* Pause the CPU */
 
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
+              up_cpu_pause(cpu);
             }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
+#endif
 
-      else
-        {
           /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
            * registers (and perhaps also the LR).  These will be restored
            * by the signal trampoline after the signal has been delivered.
@@ -396,38 +139,47 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 
           /* Save the current register context location */
 
-          tcb->xcp.saved_regs        = tcb->xcp.regs;
+          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);
+          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
+          tcb->xcp.regs[REG_SP]         = (uint32_t)tcb->xcp.regs +
+                                                    XCPTCONTEXT_SIZE;
 
           /* Then set up to vector to the trampoline with interrupts
            * disabled.  We must already be in privileged thread mode to be
            * here.
            */
 
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
+          tcb->xcp.regs[REG_PC]         = (uint32_t)arm_sigdeliver;
 #ifdef CONFIG_ARMV7M_USEBASEPRI
-          tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
+          tcb->xcp.regs[REG_BASEPRI]    = NVIC_SYSH_DISABLE_PRIORITY;
 #else
-          tcb->xcp.regs[REG_PRIMASK] = 1;
+          tcb->xcp.regs[REG_PRIMASK]    = 1;
 #endif
-          tcb->xcp.regs[REG_XPSR]    = ARMV7M_XPSR_T;
+          tcb->xcp.regs[REG_XPSR]       = ARMV7M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
+          tcb->xcp.regs[REG_LR]         = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
+#endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
 #endif
         }
     }
 }
-#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv7-m/arm_svcall.c 
b/arch/arm/src/armv7-m/arm_svcall.c
index a025681c53..6c6f507aec 100644
--- a/arch/arm/src/armv7-m/arm_svcall.c
+++ b/arch/arm/src/armv7-m/arm_svcall.c
@@ -125,6 +125,7 @@ static void dispatch_syscall(void)
 
 int arm_svcall(int irq, void *context, void *arg)
 {
+  struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
   uint32_t cmd;
 
@@ -176,7 +177,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
 
@@ -201,7 +202,7 @@ int arm_svcall(int irq, void *context, void *arg)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -459,24 +460,20 @@ int arm_svcall(int irq, void *context, void *arg)
 #  ifndef CONFIG_DEBUG_SVCALL
   if (cmd > SYS_switch_context)
 #  else
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
 #  endif
     {
+      regs = (uint32_t *)tcb->xcp.regs;
+
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R0],  up_current_regs()[REG_R1],
-              up_current_regs()[REG_R2],  up_current_regs()[REG_R3],
-              up_current_regs()[REG_R4],  up_current_regs()[REG_R5],
-              up_current_regs()[REG_R6],  up_current_regs()[REG_R7]);
+              regs[REG_R0],  regs[REG_R1], regs[REG_R2],  regs[REG_R3],
+              regs[REG_R4],  regs[REG_R5], regs[REG_R6],  regs[REG_R7]);
       svcinfo("  R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R8],  up_current_regs()[REG_R9],
-              up_current_regs()[REG_R10], up_current_regs()[REG_R11],
-              up_current_regs()[REG_R12], up_current_regs()[REG_R13],
-              up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
-      svcinfo(" PSR: %08x EXC_RETURN: %08x, CONTROL: %08x\n",
-              up_current_regs()[REG_XPSR],
-              up_current_regs()[REG_EXC_RETURN],
-              up_current_regs()[REG_CONTROL]);
+              regs[REG_R8],  regs[REG_R9], regs[REG_R10], regs[REG_R11],
+              regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
+      svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
+              regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
     }
 #  ifdef CONFIG_DEBUG_SVCALL
   else
diff --git a/arch/arm/src/armv7-r/arm_cpupause.c 
b/arch/arm/src/armv7-r/arm_cpupause.c
index b51b98e539..a466d963eb 100644
--- a/arch/arm/src/armv7-r/arm_cpupause.c
+++ b/arch/arm/src/armv7-r/arm_cpupause.c
@@ -117,11 +117,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -207,11 +203,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/armv7-r/arm_cpustart.c 
b/arch/arm/src/armv7-r/arm_cpustart.c
index fe93836e5b..15d0ec1ac0 100644
--- a/arch/arm/src/armv7-r/arm_cpustart.c
+++ b/arch/arm/src/armv7-r/arm_cpustart.c
@@ -79,12 +79,8 @@ int arm_start_handler(int irq, void *context, void *arg)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts. This instantiates the exception context of the
-   * tcb at the head of the assigned task list.  In this case, this should
-   * be the CPUs NULL task.
-   */
+  UNUSED(tcb);
 
-  arm_restorestate(tcb->xcp.regs);
   return OK;
 }
 
diff --git a/arch/arm/src/armv7-r/arm_doirq.c b/arch/arm/src/armv7-r/arm_doirq.c
index 61adb183b6..7b08a7dd56 100644
--- a/arch/arm/src/armv7-r/arm_doirq.c
+++ b/arch/arm/src/armv7-r/arm_doirq.c
@@ -41,6 +41,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
@@ -50,6 +52,18 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  /* if irq == GIC_SMP_CPUSTART
+   * We are initiating the multi-core jumping state to up_idle,
+   * and we will use this_task(). Therefore, it cannot be overridden.
+   */
+
+#ifdef CONFIG_SMP
+  if (irq != GIC_SMP_CPUSTART)
+#endif
+    {
+      tcb->xcp.regs = regs;
+    }
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -59,18 +73,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
+  tcb = this_task();
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
       /* Record the new "running" task when context switch occurred.
        * g_running_tasks[] is only used by assertion logic for reporting
        * crashes.
        */
 
-      g_running_tasks[this_cpu()] = this_task();
-      regs = up_current_regs();
+      g_running_tasks[this_cpu()] = tcb;
+      regs = tcb->xcp.regs;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/arm/src/armv7-r/arm_schedulesigaction.c 
b/arch/arm/src/armv7-r/arm_schedulesigaction.c
index e24fc8de3b..b21a0c9188 100644
--- a/arch/arm/src/armv7-r/arm_schedulesigaction.c
+++ b/arch/arm/src/armv7-r/arm_schedulesigaction.c
@@ -75,7 +75,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -87,284 +86,39 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
       tcb->xcp.sigdeliver = sigdeliver;
 
       /* First, handle some special cases when the signal is being delivered
-       * to the currently executing task.
+       * to task that is currently executing on any CPU.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signalling itself for some reason.
-           */
-
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now. */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state
-           * in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following logic
-           * would fail in the strange case where we are in an interrupt
-           * handler, the thread is signalling itself, but a context switch
-           * to another task has occurred so that current_regs does not
-           * refer to the thread of this_task()!
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handler will run in a critical section!
            */
 
-          else
-            {
-              /* Save the return lr and cpsr and one scratch register
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP]  = (uint32_t)(up_current_regs() +
-                                                       XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
-
-              up_current_regs()[REG_PC]   = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-              up_current_regs()[REG_CPSR] |= PSR_T_BIT;
-#endif
-
-#ifdef CONFIG_ENDIAN_BIG
-              up_current_regs()[REG_CPSR] |= PSR_E_BIT;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signalling some non-running task.
-       */
-
       else
         {
-          /* Save the return lr and cpsr and one scratch register.  These
-           * will be restored by the signal trampoline after the signals
-           * have been delivered.
-           */
-
-          /* Save the current register context location */
-
-          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
            */
 
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-          tcb->xcp.regs[REG_CPSR]    = (PSR_MODE_SYS | PSR_I_BIT |
-                                        PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-          tcb->xcp.regs[REG_CPSR]   |= PSR_T_BIT;
-#endif
-
-#ifdef CONFIG_ENDIAN_BIG
-          tcb->xcp.regs[REG_CPSR]   |= PSR_E_BIT;
-#endif
-        }
-    }
-}
-#else
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
+          if (cpu != me)
             {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
+              /* Pause the CPU */
 
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
+              up_cpu_pause(cpu);
             }
-
-          /* CASE 2:  The task that needs to receive the signal is running.
-           * This could happen if the task is running on another CPU OR if
-           * we are in an interrupt handler and the task is running on this
-           * CPU.  In the former case, we will have to PAUSE the other CPU
-           * first.  But in either case, we will have to modify the return
-           * state as well as the state in the TCB.
-           */
-
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]    = (uint32_t)tcb->xcp.regs +
-                                                       XCPTCONTEXT_SIZE;
-
-                  /* Then set up to vector to the trampoline with interrupts
-                   * disabled
-                   */
-
-                  tcb->xcp.regs[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  tcb->xcp.regs[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These will
-                   * be restored by the signal trampoline after the signal
-                   * has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  up_current_regs()[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                                  PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  up_current_regs()[REG_CPSR] |= PSR_T_BIT;
 #endif
-                }
-
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
-
-              /* RESUME the other CPU if it was PAUSED */
 
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
-            }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
-
-      else
-        {
           /* Save the return lr and cpsr and one scratch register.  These
            * will be restored by the signal trampoline after the signals
            * have been delivered.
@@ -396,7 +150,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 #ifdef CONFIG_ARM_THUMB
           tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
+#endif
         }
     }
 }
-#endif
diff --git a/arch/arm/src/armv7-r/arm_syscall.c 
b/arch/arm/src/armv7-r/arm_syscall.c
index f1e149e749..66d2181618 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -156,7 +156,8 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb;
+  struct tcb_s *tcb = this_task();
+
   uint32_t cmd;
   int cpu;
 #ifdef CONFIG_BUILD_PROTECTED
@@ -167,6 +168,8 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  tcb->xcp.regs = regs;
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -268,7 +271,7 @@ uint32_t *arm_syscall(uint32_t *regs)
            * set will determine the restored context.
            */
 
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
           DEBUGASSERT(up_current_regs());
         }
         break;
@@ -294,7 +297,7 @@ uint32_t *arm_syscall(uint32_t *regs)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -561,22 +564,19 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
       /* Record the new "running" task.  g_running_tasks[] is only used by
        * assertion logic for reporting crashes.
        */
 
       cpu = this_cpu();
-      tcb = current_task(cpu);
       g_running_tasks[cpu] = tcb;
 
       /* Restore the cpu lock */
 
       restore_critical_section(tcb, cpu);
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Report what happened */
diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c
index 198261961d..e35cbb0eef 100644
--- a/arch/arm/src/armv8-m/arm_doirq.c
+++ b/arch/arm/src/armv8-m/arm_doirq.c
@@ -91,6 +91,8 @@ static inline bool arm_from_thread(uint32_t excret)
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -98,6 +100,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (arm_from_thread(regs[REG_EXC_RETURN]))
     {
+      tcb->xcp.regs = regs;
       up_set_current_regs(regs);
     }
 
@@ -117,17 +120,17 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (arm_from_thread(regs[REG_EXC_RETURN]))
     {
-      /* Restore the cpu lock */
+      tcb = this_task();
 
-      if (regs != up_current_regs())
+      if (regs != tcb->xcp.regs)
         {
           /* Record the new "running" task when context switch occurred.
            * g_running_tasks[] is only used by assertion logic for reporting
            * crashes.
            */
 
-          g_running_tasks[this_cpu()] = this_task();
-          regs = up_current_regs();
+          g_running_tasks[this_cpu()] = tcb;
+          regs = tcb->xcp.regs;
         }
 
       /* Update the current_regs to NULL. */
diff --git a/arch/arm/src/armv8-m/arm_schedulesigaction.c 
b/arch/arm/src/armv8-m/arm_schedulesigaction.c
index f96309538e..42b0ccfb06 100644
--- a/arch/arm/src/armv8-m/arm_schedulesigaction.c
+++ b/arch/arm/src/armv8-m/arm_schedulesigaction.c
@@ -79,7 +79,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -95,167 +94,20 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
        * to the currently executing task.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handle will run in a critical section!
            */
 
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handle will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state in
-           * the TCB.
-           */
-
-          else
-            {
-              /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
-               * registers (and perhaps also the LR).  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
-                                                      XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled.  The kernel-space trampoline must run in
-               * privileged thread mode.
-               */
-
-              up_current_regs()[REG_PC]         = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV8M_USEBASEPRI
-              up_current_regs()[REG_BASEPRI]    =
-                                                  NVIC_SYSH_DISABLE_PRIORITY;
-#else
-              up_current_regs()[REG_PRIMASK]    = 1;
-#endif
-              up_current_regs()[REG_XPSR]       = ARMV8M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-              up_current_regs()[REG_LR]         = EXC_RETURN_THREAD;
-              up_current_regs()[REG_EXC_RETURN] = EXC_RETURN_THREAD;
-              up_current_regs()[REG_CONTROL]    = getcontrol() &
-                                                   ~CONTROL_NPRIV;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling* some non-running task.
-       */
-
       else
         {
-          /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
-           * registers (and perhaps also the LR).  These will be restored
-           * by the signal trampoline after the signal has been delivered.
-           */
-
-          /* Save the current register context location */
-
-          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled.  We must already be in privileged thread mode to be
-           * here.
-           */
-
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV8M_USEBASEPRI
-          tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
-#else
-          tcb->xcp.regs[REG_PRIMASK] = 1;
-#endif
-          tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-        }
-    }
-}
-#endif /* !CONFIG_SMP */
-
-#ifdef CONFIG_SMP
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
-            {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
           /* CASE 2:  The task that needs to receive the signal is running.
            * This could happen if the task is running on another CPU OR if
            * we are in an interrupt handler and the task is running on this
@@ -264,124 +116,22 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
            * state as well as the state in the TCB.
            */
 
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                         XCPTCONTEXT_SIZE;
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  We must already be in privileged thread mode
-                   * to be here.
-                   */
-
-                  tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV8M_USEBASEPRI
-                  tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
-#else
-                  tcb->xcp.regs[REG_PRIMASK] = 1;
-#endif
-                  tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-                  tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These
-                   * will be restored by the signal trampoline after the
-                   * signal has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                        + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
+           */
 
-                  up_current_regs()[REG_PC]      = (uint32_t)arm_sigdeliver;
-#ifdef CONFIG_ARMV8M_USEBASEPRI
-                  up_current_regs()[REG_BASEPRI] =
-                  NVIC_SYSH_DISABLE_PRIORITY;
-#else
-                  up_current_regs()[REG_PRIMASK] = 1;
-#endif
-                  up_current_regs()[REG_XPSR]    = ARMV8M_XPSR_T;
-#ifdef CONFIG_BUILD_PROTECTED
-                  up_current_regs()[REG_LR]      = EXC_RETURN_THREAD;
-                  up_current_regs()[REG_CONTROL] = getcontrol() &
-                                                    ~CONTROL_NPRIV;
-#endif
-                }
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-              /* RESUME the other CPU if it was PAUSED */
+          if (cpu != me)
+            {
+              /* Pause the CPU */
 
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
+              up_cpu_pause(cpu);
             }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
+#endif
 
-      else
-        {
           /* Save the return PC, CPSR and either the BASEPRI or PRIMASK
            * registers (and perhaps also the LR).  These will be restored
            * by the signal trampoline after the signal has been delivered.
@@ -389,38 +139,47 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 
           /* Save the current register context location */
 
-          tcb->xcp.saved_regs        = tcb->xcp.regs;
+          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);
+          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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
+          tcb->xcp.regs[REG_SP]         = (uint32_t)tcb->xcp.regs +
+                                                    XCPTCONTEXT_SIZE;
 
           /* Then set up to vector to the trampoline with interrupts
            * disabled.  We must already be in privileged thread mode to be
            * here.
            */
 
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
+          tcb->xcp.regs[REG_PC]         = (uint32_t)arm_sigdeliver;
 #ifdef CONFIG_ARMV8M_USEBASEPRI
-          tcb->xcp.regs[REG_BASEPRI] = NVIC_SYSH_DISABLE_PRIORITY;
+          tcb->xcp.regs[REG_BASEPRI]    = NVIC_SYSH_DISABLE_PRIORITY;
 #else
-          tcb->xcp.regs[REG_PRIMASK] = 1;
+          tcb->xcp.regs[REG_PRIMASK]    = 1;
 #endif
-          tcb->xcp.regs[REG_XPSR]    = ARMV8M_XPSR_T;
+          tcb->xcp.regs[REG_XPSR]       = ARMV8M_XPSR_T;
 #ifdef CONFIG_BUILD_PROTECTED
-          tcb->xcp.regs[REG_LR]      = EXC_RETURN_THREAD;
-          tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
+          tcb->xcp.regs[REG_LR]         = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_EXC_RETURN] = EXC_RETURN_THREAD;
+          tcb->xcp.regs[REG_CONTROL]    = getcontrol() & ~CONTROL_NPRIV;
+#endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
 #endif
         }
     }
 }
-#endif /* CONFIG_SMP */
diff --git a/arch/arm/src/armv8-m/arm_svcall.c 
b/arch/arm/src/armv8-m/arm_svcall.c
index 9df396b6c4..aeb427322c 100644
--- a/arch/arm/src/armv8-m/arm_svcall.c
+++ b/arch/arm/src/armv8-m/arm_svcall.c
@@ -124,6 +124,7 @@ static void dispatch_syscall(void)
 
 int arm_svcall(int irq, void *context, void *arg)
 {
+  struct tcb_s *tcb = this_task();
   uint32_t *regs = (uint32_t *)context;
   uint32_t cmd;
 
@@ -175,7 +176,7 @@ int arm_svcall(int irq, void *context, void *arg)
       case SYS_restore_context:
         {
           DEBUGASSERT(regs[REG_R1] != 0);
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
         }
         break;
 
@@ -200,7 +201,7 @@ int arm_svcall(int irq, void *context, void *arg)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -460,24 +461,20 @@ int arm_svcall(int irq, void *context, void *arg)
 #  ifndef CONFIG_DEBUG_SVCALL
   if (cmd > SYS_switch_context)
 #  else
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
 #  endif
     {
+      regs = (uint32_t *)tcb->xcp.regs;
+
       svcinfo("SVCall Return:\n");
       svcinfo("  R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R0],  up_current_regs()[REG_R1],
-              up_current_regs()[REG_R2],  up_current_regs()[REG_R3],
-              up_current_regs()[REG_R4],  up_current_regs()[REG_R5],
-              up_current_regs()[REG_R6],  up_current_regs()[REG_R7]);
+              regs[REG_R0],  regs[REG_R1], regs[REG_R2],  regs[REG_R3],
+              regs[REG_R4],  regs[REG_R5], regs[REG_R6],  regs[REG_R7]);
       svcinfo("  R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-              up_current_regs()[REG_R8],  up_current_regs()[REG_R9],
-              up_current_regs()[REG_R10], up_current_regs()[REG_R11],
-              up_current_regs()[REG_R12], up_current_regs()[REG_R13],
-              up_current_regs()[REG_R14], up_current_regs()[REG_R15]);
+              regs[REG_R8],  regs[REG_R9], regs[REG_R10], regs[REG_R11],
+              regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
       svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
-              up_current_regs()[REG_XPSR],
-              up_current_regs()[REG_EXC_RETURN],
-              up_current_regs()[REG_CONTROL]);
+              regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
     }
 #  ifdef CONFIG_DEBUG_SVCALL
   else
diff --git a/arch/arm/src/armv8-r/arm_doirq.c b/arch/arm/src/armv8-r/arm_doirq.c
index 982795fe13..2863292052 100644
--- a/arch/arm/src/armv8-r/arm_doirq.c
+++ b/arch/arm/src/armv8-r/arm_doirq.c
@@ -42,6 +42,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
@@ -51,6 +53,16 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  /* if irq == GIC_SMP_CPUSTART
+   * We are initiating the multi-core jumping state to up_idle,
+   * and we will use this_task(). Therefore, it cannot be overridden.
+   */
+
+  if (irq != GIC_SMP_CPUSTART)
+    {
+      tcb->xcp.regs = regs;
+    }
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -60,10 +72,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, regs);
+  tcb = this_task();
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
       /* Record the new "running" task when context switch occurred.
        * g_running_tasks[] is only used by assertion logic for reporting
@@ -71,7 +82,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
        */
 
       g_running_tasks[this_cpu()] = this_task();
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Set current_regs to NULL to indicate that we are no longer in an
diff --git a/arch/arm/src/armv8-r/arm_schedulesigaction.c 
b/arch/arm/src/armv8-r/arm_schedulesigaction.c
index 400dbc339d..1ceba997f7 100644
--- a/arch/arm/src/armv8-r/arm_schedulesigaction.c
+++ b/arch/arm/src/armv8-r/arm_schedulesigaction.c
@@ -75,7 +75,6 @@
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SMP
 void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
 {
   sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
@@ -87,291 +86,39 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
       tcb->xcp.sigdeliver = sigdeliver;
 
       /* First, handle some special cases when the signal is being delivered
-       * to the currently executing task.
+       * to task that is currently executing on any CPU.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signalling itself for some reason.
-           */
-
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now. */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the interrupted
-           * task is the same as the one that must receive the signal, then
-           * we will have to modify the return state as well as the state
-           * in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following logic
-           * would fail in the strange case where we are in an interrupt
-           * handler, the thread is signalling itself, but a context switch
-           * to another task has occurred so that current_regs does not
-           * refer to the thread of this_task()!
+          /* In this case just deliver the signal now.
+           * REVISIT:  Signal handler will run in a critical section!
            */
 
-          else
-            {
-              /* Save the return lr and cpsr and one scratch register
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              /* And make sure that the saved context in the TCB is the same
-               * as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
-                                                      XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
-
-              up_current_regs()[REG_PC]   = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_CPSR] = (PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-              up_current_regs()[REG_CPSR] |= PSR_T_BIT;
-#endif
-
-#ifdef CONFIG_ENDIAN_BIG
-              up_current_regs()[REG_CPSR] |= PSR_E_BIT;
-#endif
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signalling some non-running task.
-       */
-
       else
         {
-          /* Save the return lr and cpsr and one scratch register.  These
-           * will be restored by the signal trampoline after the signals
-           * have been delivered.
+          /* If we signaling a task running on the other CPU, we have
+           * to PAUSE the other CPU.
            */
 
-          /* Save the current register context location */
-
-          tcb->xcp.saved_regs        = tcb->xcp.regs;
+#ifdef CONFIG_SMP
+          int cpu = tcb->cpu;
+          int me  = this_cpu();
 
-          /* 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_SP]      = (uint32_t)tcb->xcp.regs +
-                                                 XCPTCONTEXT_SIZE;
-
-          /* Then set up to vector to the trampoline with interrupts
-           * disabled
-           */
-
-          tcb->xcp.regs[REG_PC]      = (uint32_t)arm_sigdeliver;
-          tcb->xcp.regs[REG_CPSR]    = (PSR_MODE_SYS | PSR_I_BIT |
-                                        PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-          tcb->xcp.regs[REG_CPSR]   |= PSR_T_BIT;
-#endif
-
-#ifdef CONFIG_ENDIAN_BIG
-          tcb->xcp.regs[REG_CPSR]   |= PSR_E_BIT;
-#endif
-        }
-    }
-}
-#else
-void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
-{
-  int cpu;
-  int me;
-
-  sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver);
-
-  /* Refuse to handle nested signal actions */
-
-  if (!tcb->xcp.sigdeliver)
-    {
-      tcb->xcp.sigdeliver = sigdeliver;
-
-      /* First, handle some special cases when the signal is being delivered
-       * to task that is currently executing on any CPU.
-       */
-
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
-
-      if (tcb->task_state == TSTATE_TASK_RUNNING)
-        {
-          me  = this_cpu();
-          cpu = tcb->cpu;
-
-          /* CASE 1:  We are not in an interrupt handler and a task is
-           * signaling itself for some reason.
-           */
-
-          if (cpu == me && !up_current_regs())
+          if (cpu != me)
             {
-              /* In this case just deliver the signal now.
-               * REVISIT:  Signal handler will run in a critical section!
-               */
+              /* Pause the CPU */
 
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
+              up_cpu_pause(cpu);
             }
-
-          /* CASE 2:  The task that needs to receive the signal is running.
-           * This could happen if the task is running on another CPU OR if
-           * we are in an interrupt handler and the task is running on this
-           * CPU.  In the former case, we will have to PAUSE the other CPU
-           * first.  But in either case, we will have to modify the return
-           * state as well as the state in the TCB.
-           */
-
-          else
-            {
-              /* If we signaling a task running on the other CPU, we have
-               * to PAUSE the other CPU.
-               */
-
-              if (cpu != me)
-                {
-                  /* Pause the CPU */
-
-                  up_cpu_pause(cpu);
-
-                  /* Now tcb on the other CPU can be accessed safely */
-
-                  /* Copy tcb->xcp.regs to tcp.xcp.saved. These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  /* Save the current register context location */
-
-                  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_SP]    = (uint32_t)tcb->xcp.regs +
-                                                       XCPTCONTEXT_SIZE;
-
-                  /* Then set up to vector to the trampoline with interrupts
-                   * disabled
-                   */
-
-                  tcb->xcp.regs[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  tcb->xcp.regs[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                              PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
-#endif
-                }
-              else
-                {
-                  /* tcb is running on the same CPU */
-
-                  /* Save the return PC, CPSR and either the BASEPRI or
-                   * PRIMASK registers (and perhaps also the LR).  These will
-                   * be restored by the signal trampoline after the signal
-                   * has been delivered.
-                   */
-
-                  /* And make sure that the saved context in the TCB is the
-                   * same as the interrupt return context.
-                   */
-
-                  arm_savestate(tcb->xcp.saved_regs);
-
-                  /* Duplicate the register context.  These will be
-                   * restored by the signal trampoline after the signal has
-                   * been delivered.
-                   */
-
-                  up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-                  memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                         XCPTCONTEXT_SIZE);
-
-                  up_current_regs()[REG_SP] = (uint32_t)(up_current_regs()
-                                                         + XCPTCONTEXT_REGS);
-
-                  /* Then set up vector to the trampoline with interrupts
-                   * disabled.  The kernel-space trampoline must run in
-                   * privileged thread mode.
-                   */
-
-                  up_current_regs()[REG_PC]    = (uint32_t)arm_sigdeliver;
-                  up_current_regs()[REG_CPSR]  = (PSR_MODE_SYS | PSR_I_BIT |
-                                                   PSR_F_BIT);
-#ifdef CONFIG_ARM_THUMB
-                  up_current_regs()[REG_CPSR] |= PSR_T_BIT;
 #endif
-                }
-
-              /* Increment the IRQ lock count so that when the task is
-               * restarted, it will hold the IRQ spinlock.
-               */
-
-              DEBUGASSERT(tcb->irqcount < INT16_MAX);
-              tcb->irqcount++;
-
-              /* NOTE: If the task runs on another CPU(cpu), adjusting
-               * global IRQ controls will be done in the pause handler
-               * on the CPU(cpu) by taking a critical section.
-               * If the task is scheduled on this CPU(me), do nothing
-               * because this CPU already took a critical section
-               */
-
-              /* RESUME the other CPU if it was PAUSED */
-
-              if (cpu != me)
-                {
-                  up_cpu_resume(cpu);
-                }
-            }
-        }
-
-      /* Otherwise, we are (1) signaling a task is not running from an
-       * interrupt handler or (2) we are not in an interrupt handler and the
-       * running task is signaling some other non-running task.
-       */
 
-      else
-        {
           /* Save the return lr and cpsr and one scratch register.  These
            * will be restored by the signal trampoline after the signals
            * have been delivered.
@@ -394,13 +141,6 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
           tcb->xcp.regs[REG_SP]    = (uint32_t)tcb->xcp.regs +
                                                XCPTCONTEXT_SIZE;
 
-          /* Increment the IRQ lock count so that when the task is restarted,
-           * it will hold the IRQ spinlock.
-           */
-
-          DEBUGASSERT(tcb->irqcount < INT16_MAX);
-          tcb->irqcount++;
-
           /* Then set up to vector to the trampoline with interrupts
            * disabled
            */
@@ -410,7 +150,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, 
sig_deliver_t sigdeliver)
 #ifdef CONFIG_ARM_THUMB
           tcb->xcp.regs[REG_CPSR] |= PSR_T_BIT;
 #endif
+
+#ifdef CONFIG_SMP
+          /* RESUME the other CPU if it was PAUSED */
+
+          if (cpu != me)
+            {
+              up_cpu_resume(cpu);
+            }
+#endif
         }
     }
 }
-#endif
diff --git a/arch/arm/src/armv8-r/arm_syscall.c 
b/arch/arm/src/armv8-r/arm_syscall.c
index ffc57ee1f2..1f82dc20e7 100644
--- a/arch/arm/src/armv8-r/arm_syscall.c
+++ b/arch/arm/src/armv8-r/arm_syscall.c
@@ -156,7 +156,7 @@ static void dispatch_syscall(void)
 
 uint32_t *arm_syscall(uint32_t *regs)
 {
-  struct tcb_s *tcb;
+  struct tcb_s *tcb = this_task();
   uint32_t cmd;
   int cpu;
 #ifdef CONFIG_BUILD_PROTECTED
@@ -167,6 +167,8 @@ uint32_t *arm_syscall(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
 
+  tcb->xcp.regs = regs;
+
   /* Current regs non-zero indicates that we are processing an interrupt;
    * current_regs is also used to manage interrupt level context switches.
    */
@@ -268,7 +270,7 @@ uint32_t *arm_syscall(uint32_t *regs)
            * set will determine the restored context.
            */
 
-          up_set_current_regs((uint32_t *)regs[REG_R1]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R1];
           DEBUGASSERT(up_current_regs());
         }
         break;
@@ -294,7 +296,7 @@ uint32_t *arm_syscall(uint32_t *regs)
         {
           DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
           *(uint32_t **)regs[REG_R1] = regs;
-          up_set_current_regs((uint32_t *)regs[REG_R2]);
+          tcb->xcp.regs = (uint32_t *)regs[REG_R2];
         }
         break;
 
@@ -561,22 +563,19 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
     }
 
-  /* Restore the cpu lock */
-
-  if (regs != up_current_regs())
+  if (regs != tcb->xcp.regs)
     {
       /* Record the new "running" task.  g_running_tasks[] is only used by
        * assertion logic for reporting crashes.
        */
 
       cpu = this_cpu();
-      tcb = current_task(cpu);
       g_running_tasks[cpu] = tcb;
 
       /* Restore the cpu lock */
 
       restore_critical_section(tcb, cpu);
-      regs = up_current_regs();
+      regs = tcb->xcp.regs;
     }
 
   /* Report what happened */
diff --git a/arch/arm/src/common/arm_internal.h 
b/arch/arm/src/common/arm_internal.h
index c5c02a8927..e7ace0d52e 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -96,11 +96,6 @@
 
 #define INTSTACK_SIZE (CONFIG_ARCH_INTERRUPTSTACK & ~STACK_ALIGN_MASK)
 
-/* Macros to handle saving and restoring interrupt state. */
-
-#define arm_savestate(regs)    (regs = up_current_regs())
-#define arm_restorestate(regs) up_set_current_regs(regs)
-
 /* Toolchain dependent, linker defined section addresses */
 
 #if defined(__ICCARM__)
diff --git a/arch/arm/src/common/arm_switchcontext.c 
b/arch/arm/src/common/arm_switchcontext.c
index 51fe498e0c..f342da9ebc 100644
--- a/arch/arm/src/common/arm_switchcontext.c
+++ b/arch/arm/src/common/arm_switchcontext.c
@@ -63,21 +63,9 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
 
   if (up_current_regs())
     {
-      /* Yes, then we have to do things differently.
-       * Just copy the current_regs into the OLD rtcb.
-       */
-
-      arm_savestate(rtcb->xcp.regs);
-
       /* Update scheduler parameters */
 
       nxsched_resume_scheduler(tcb);
-
-      /* Then switch contexts.  Any necessary address environment
-       * changes will be made when the interrupt returns.
-       */
-
-      arm_restorestate(tcb->xcp.regs);
     }
 
   /* No, then we will need to perform the user context switch */
diff --git a/arch/arm/src/cxd56xx/cxd56_cpupause.c 
b/arch/arm/src/cxd56xx/cxd56_cpupause.c
index d02a51b8a2..3857728f45 100644
--- a/arch/arm/src/cxd56xx/cxd56_cpupause.c
+++ b/arch/arm/src/cxd56xx/cxd56_cpupause.c
@@ -199,11 +199,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -290,11 +286,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/dm320/dm320_decodeirq.c 
b/arch/arm/src/dm320/dm320_decodeirq.c
index 0fc6b0b39d..3cdec04c05 100644
--- a/arch/arm/src/dm320/dm320_decodeirq.c
+++ b/arch/arm/src/dm320/dm320_decodeirq.c
@@ -34,6 +34,7 @@
 
 #include "chip.h"
 #include "arm_internal.h"
+#include "sched/sched.h"
 
 /****************************************************************************
  * Public Functions
@@ -41,6 +42,8 @@
 
 uint32_t *arm_decodeirq(uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   up_set_current_regs(regs);
   err("ERROR: Unexpected IRQ\n");
@@ -78,11 +81,13 @@ uint32_t *arm_decodeirq(uint32_t *regs)
            */
 
           DEBUGASSERT(up_current_regs() == NULL);
+          tcb->xcp.regs = regs;
           up_set_current_regs(regs);
 
           /* Deliver the IRQ */
 
           irq_dispatch(irq, regs);
+          tcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Check for a context switch.  If a context switch occurred, then
@@ -92,7 +97,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
            * from the interrupt.
            */
 
-          if (regs != up_current_regs())
+          if (regs != tcb->xcp.regs)
             {
               /* Make sure that the address environment for the previously
                * running task is closed down gracefully (data caches dump,
diff --git a/arch/arm/src/imx1/imx_decodeirq.c 
b/arch/arm/src/imx1/imx_decodeirq.c
index b164e5adbe..43f7c8e1ed 100644
--- a/arch/arm/src/imx1/imx_decodeirq.c
+++ b/arch/arm/src/imx1/imx_decodeirq.c
@@ -57,6 +57,8 @@
 
 uint32_t *arm_decodeirq(uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   up_set_current_regs(regs);
   err("ERROR: Unexpected IRQ\n");
@@ -74,6 +76,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
   up_set_current_regs(regs);
+  tcb->xcp.regs = regs;
 
   /* Loop while there are pending interrupts to be processed */
 
@@ -99,6 +102,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
           /* Deliver the IRQ */
 
           irq_dispatch(irq, regs);
+          tcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Check for a context switch.  If a context switch occurred, then
@@ -108,7 +112,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
            * from the interrupt.
            */
 
-          if (regs != up_current_regs())
+          if (regs != tcb->xcp.regs)
             {
               /* Make sure that the address environment for the previously
                * running task is closed down gracefully (data caches dump,
diff --git a/arch/arm/src/lc823450/lc823450_cpupause.c 
b/arch/arm/src/lc823450/lc823450_cpupause.c
index 31957f8ad2..c75abbae17 100644
--- a/arch/arm/src/lc823450/lc823450_cpupause.c
+++ b/arch/arm/src/lc823450/lc823450_cpupause.c
@@ -127,11 +127,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -211,11 +207,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/lpc214x/lpc214x_decodeirq.c 
b/arch/arm/src/lpc214x/lpc214x_decodeirq.c
index ecf0294b25..08662be3b5 100644
--- a/arch/arm/src/lpc214x/lpc214x_decodeirq.c
+++ b/arch/arm/src/lpc214x/lpc214x_decodeirq.c
@@ -33,6 +33,7 @@
 #include "chip.h"
 #include "arm_internal.h"
 #include "lpc214x_vic.h"
+#include "sched/sched.h"
 
 /****************************************************************************
  * Private Data
@@ -81,6 +82,8 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 static uint32_t *lpc214x_decodeirq(uint32_t *regs)
 #endif
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   up_set_current_regs(regs);
   err("ERROR: Unexpected IRQ\n");
@@ -125,6 +128,7 @@ static uint32_t *lpc214x_decodeirq(uint32_t *regs)
 
       savestate = up_current_regs();
       up_set_current_regs(regs);
+      tcb->xcp.regs = regs;
 
       /* Deliver the IRQ */
 
diff --git a/arch/arm/src/lpc2378/lpc23xx_decodeirq.c 
b/arch/arm/src/lpc2378/lpc23xx_decodeirq.c
index 0affc82eba..9a2d253dea 100644
--- a/arch/arm/src/lpc2378/lpc23xx_decodeirq.c
+++ b/arch/arm/src/lpc2378/lpc23xx_decodeirq.c
@@ -56,6 +56,7 @@
 #include "arm_internal.h"
 #include "lpc2378.h"
 #include "lpc23xx_vic.h"
+#include "sched/sched.h"
 
 /****************************************************************************
  * Public Functions
@@ -91,6 +92,8 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 static uint32_t *lpc23xx_decodeirq(uint32_t *regs)
 #endif
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   err("ERROR: Unexpected IRQ\n");
   up_set_current_regs(regs);
@@ -124,6 +127,7 @@ static uint32_t *lpc23xx_decodeirq(uint32_t *regs)
 
       savestate = up_current_regs();
       up_set_current_regs(regs);
+      tcb->xcp.regs = regs;
 
       /* Acknowledge the interrupt */
 
diff --git a/arch/arm/src/lpc31xx/lpc31_decodeirq.c 
b/arch/arm/src/lpc31xx/lpc31_decodeirq.c
index 517761d9ce..64e603ce30 100644
--- a/arch/arm/src/lpc31xx/lpc31_decodeirq.c
+++ b/arch/arm/src/lpc31xx/lpc31_decodeirq.c
@@ -34,7 +34,7 @@
 
 #include "chip.h"
 #include "arm_internal.h"
-
+#include "sched/sched.h"
 #include "lpc31_intc.h"
 
 /****************************************************************************
@@ -43,6 +43,8 @@
 
 uint32_t *arm_decodeirq(uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   up_set_current_regs(regs);
   err("ERROR: Unexpected IRQ\n");
@@ -84,10 +86,12 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 
           DEBUGASSERT(up_current_regs() == NULL);
           up_set_current_regs(regs);
+          tcb->xcp.regs = regs;
 
           /* Deliver the IRQ */
 
           irq_dispatch(irq, regs);
+          tcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Check for a context switch.  If a context switch occurred, then
@@ -97,7 +101,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
            * from the interrupt.
            */
 
-          if (regs != up_current_regs())
+          if (regs != tcb->xcp.regs)
             {
               /* Make sure that the address environment for the previously
                * running task is closed down gracefully (data caches dump,
diff --git a/arch/arm/src/moxart/moxart_irq.c b/arch/arm/src/moxart/moxart_irq.c
index 0fcb8c4348..029582c0e0 100644
--- a/arch/arm/src/moxart/moxart_irq.c
+++ b/arch/arm/src/moxart/moxart_irq.c
@@ -260,6 +260,7 @@ void arm_ack_irq(int irq)
 
 uint32_t *arm_decodeirq(uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
   uint32_t num;
   uint32_t status;
 
@@ -278,6 +279,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 
   DEBUGASSERT(up_current_regs() == NULL);
   up_set_current_regs(regs);
+  tcb->xcp.regs = regs;
 
   irq_dispatch(num, regs);
   up_set_current_regs(NULL);
diff --git a/arch/arm/src/rp2040/rp2040_cpupause.c 
b/arch/arm/src/rp2040/rp2040_cpupause.c
index 06edbadef2..b5a4e8f820 100644
--- a/arch/arm/src/rp2040/rp2040_cpupause.c
+++ b/arch/arm/src/rp2040/rp2040_cpupause.c
@@ -167,11 +167,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -251,11 +247,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/sam34/sam4cm_cpupause.c 
b/arch/arm/src/sam34/sam4cm_cpupause.c
index 5ad0adb410..4abd9068de 100644
--- a/arch/arm/src/sam34/sam4cm_cpupause.c
+++ b/arch/arm/src/sam34/sam4cm_cpupause.c
@@ -129,11 +129,7 @@ int up_cpu_paused_save(void)
   sched_note_cpu_paused(tcb);
 #endif
 
-  /* Save the current context at current_regs into the TCB at the head
-   * of the assigned task list for this CPU.
-   */
-
-  arm_savestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
@@ -213,11 +209,7 @@ int up_cpu_paused_restore(void)
 
   nxsched_resume_scheduler(tcb);
 
-  /* Then switch contexts.  Any necessary address environment changes
-   * will be made when the interrupt returns.
-   */
-
-  arm_restorestate(tcb->xcp.regs);
+  UNUSED(tcb);
 
   return OK;
 }
diff --git a/arch/arm/src/str71x/str71x_decodeirq.c 
b/arch/arm/src/str71x/str71x_decodeirq.c
index 44e8fe9478..f3098e76b8 100644
--- a/arch/arm/src/str71x/str71x_decodeirq.c
+++ b/arch/arm/src/str71x/str71x_decodeirq.c
@@ -35,6 +35,7 @@
 
 #include "chip.h"
 #include "arm_internal.h"
+#include "sched/sched.h"
 
 /****************************************************************************
  * Public Functions
@@ -53,6 +54,8 @@
 
 uint32_t *arm_decodeirq(uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   board_autoled_on(LED_INIRQ);
   up_set_current_regs(regs);
@@ -82,6 +85,7 @@ uint32_t *arm_decodeirq(uint32_t *regs)
 
       savestate = up_current_regs();
       up_set_current_regs(regs);
+      tcb->xcp.regs = regs;
 
       /* Acknowledge the interrupt */
 
diff --git a/arch/arm/src/tlsr82/tc32/tc32_doirq.c 
b/arch/arm/src/tlsr82/tc32/tc32_doirq.c
index 82fcd63710..aa301a3669 100644
--- a/arch/arm/src/tlsr82/tc32/tc32_doirq.c
+++ b/arch/arm/src/tlsr82/tc32/tc32_doirq.c
@@ -36,7 +36,7 @@
 #include <arch/board/board.h>
 
 #include "arm_internal.h"
-
+#include "sched/sched.h"
 #include "hardware/tlsr82_irq.h"
 
 /****************************************************************************
@@ -57,6 +57,8 @@
 
 uint32_t *arm_doirq(int irq, uint32_t *regs)
 {
+  struct tcb_s *tcb = this_task();
+
   board_autoled_on(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC();
@@ -78,6 +80,8 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
       regs         = NULL;
     }
 
+  tcb->xcp.regs = regs;
+
   /* Acknowledge the interrupt */
 
   arm_ack_irq(irq);
@@ -85,6 +89,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
   /* Deliver the IRQ */
 
   irq_dispatch(irq, up_current_regs());
+  tcb = this_task();
 
   /* If a context switch occurred while processing the interrupt then
    * current_regs may have change value.  If we return any value different
@@ -94,11 +99,9 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
 
   if (regs == NULL)
     {
-      /* Restore the cpu lock */
-
-      if (regs != up_current_regs())
+      if (regs != tcb->xcp.regs)
         {
-          regs = up_current_regs();
+          regs = tcb->xcp.regs;
         }
 
       /* Update the current_regs to NULL. */
diff --git a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c 
b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c
index 73fd332278..4e90afee3a 100644
--- a/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c
+++ b/arch/arm/src/tlsr82/tc32/tc32_schedulesigaction.c
@@ -89,67 +89,15 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t 
sigdeliver)
        * being delivered to the currently executing task.
        */
 
-      sinfo("rtcb=%p current_regs=%p\n", this_task(), up_current_regs());
+      sinfo("rtcb=%p current_regs=%p\n", this_task(),
+            this_task()->xcp.regs);
 
-      if (tcb == this_task())
+      if (tcb == this_task() && !up_interrupt_context())
         {
-          /* CASE 1:  We are not in an interrupt handler and
-           * a task is signalling itself for some reason.
-           */
-
-          if (!up_current_regs())
-            {
-              /* In this case just deliver the signal now. */
-
-              sigdeliver(tcb);
-              tcb->xcp.sigdeliver = NULL;
-            }
-
-          /* CASE 2:  We are in an interrupt handler AND the
-           * interrupted task is the same as the one that
-           * must receive the signal, then we will have to modify
-           * the return state as well as the state in the TCB.
-           *
-           * Hmmm... there looks like a latent bug here: The following
-           * logic would fail in the strange case where we are in an
-           * interrupt handler, the thread is signalling itself, but
-           * a context switch to another task has occurred so that
-           * current_regs does not refer to the thread of this_task()!
-           */
-
-          else
-            {
-              /* Save the return lr and cpsr and one scratch register
-               * These will be restored by the signal trampoline after
-               * the signals have been delivered.
-               */
-
-              /* And make sure that the saved context in the TCB
-               * is the same as the interrupt return context.
-               */
-
-              arm_savestate(tcb->xcp.saved_regs);
-
-              /* Duplicate the register context.  These will be
-               * restored by the signal trampoline after the signal has been
-               * delivered.
-               */
-
-              up_set_current_regs(up_current_regs() - XCPTCONTEXT_REGS);
-              memcpy(up_current_regs(), tcb->xcp.saved_regs,
-                     XCPTCONTEXT_SIZE);
-
-              up_current_regs()[REG_SP] = (uint32_t)(up_current_regs() +
-                                                      XCPTCONTEXT_REGS);
-
-              /* Then set up to vector to the trampoline with interrupts
-               * disabled
-               */
+          /* In this case just deliver the signal now. */
 
-              up_current_regs()[REG_LR]     = (uint32_t)arm_sigdeliver;
-              up_current_regs()[REG_CPSR]   = PSR_MODE_SVC | PSR_I_BIT;
-              up_current_regs()[REG_IRQ_EN] = 0;
-            }
+          sigdeliver(tcb);
+          tcb->xcp.sigdeliver = NULL;
         }
 
       /* Otherwise, we are (1) signaling a task is not running

Reply via email to