You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2022/02/23 06:04:43 UTC

[incubator-nuttx] 03/04: arch/arm: unify switch context from software interrupt

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

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

commit 6cc0aaf5b9f133dd040991c02d789a75d394d34e
Author: chao.an <an...@xiaomi.com>
AuthorDate: Wed Feb 16 13:01:53 2022 +0800

    arch/arm: unify switch context from software interrupt
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/arm/src/a1x/Make.defs                |   1 +
 arch/arm/src/am335x/Make.defs             |   1 +
 arch/arm/src/arm/arm_blocktask.c          |  29 +++----
 arch/arm/src/arm/arm_fullcontextrestore.S |  39 +++------
 arch/arm/src/arm/arm_releasepending.c     |  30 +++----
 arch/arm/src/arm/arm_reprioritizertr.c    |  31 ++++----
 arch/arm/src/arm/arm_syscall.c            |  77 +++++++++++++++++-
 arch/arm/src/arm/arm_unblocktask.c        |  31 ++++----
 arch/arm/src/arm/svcall.h                 | 127 ++++++++++++++++++++++++++++++
 arch/arm/src/c5471/Make.defs              |   1 +
 arch/arm/src/common/arm_internal.h        |   2 +-
 arch/arm/src/dm320/Make.defs              |   2 +-
 arch/arm/src/imx1/Make.defs               |   2 +-
 arch/arm/src/imx6/Make.defs               |   1 +
 arch/arm/src/lpc214x/Make.defs            |   1 +
 arch/arm/src/lpc2378/Make.defs            |   1 +
 arch/arm/src/lpc31xx/Make.defs            |   2 +-
 arch/arm/src/moxart/Make.defs             |   2 +-
 arch/arm/src/sama5/Make.defs              |   1 +
 arch/arm/src/str71x/Make.defs             |   1 +
 arch/arm/src/tms570/Make.defs             |   1 +
 21 files changed, 284 insertions(+), 99 deletions(-)

diff --git a/arch/arm/src/a1x/Make.defs b/arch/arm/src/a1x/Make.defs
index 0f84c93..82af1ff 100644
--- a/arch/arm/src/a1x/Make.defs
+++ b/arch/arm/src/a1x/Make.defs
@@ -60,6 +60,7 @@ CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_mmu.c arm_prefetchabort.c
 CMN_CSRCS += arm_releasepending.c arm_reprioritizertr.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
 CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 # Use common heap allocation for now (may need to be customized later)
 
diff --git a/arch/arm/src/am335x/Make.defs b/arch/arm/src/am335x/Make.defs
index fa4ed3f..4423854 100644
--- a/arch/arm/src/am335x/Make.defs
+++ b/arch/arm/src/am335x/Make.defs
@@ -60,6 +60,7 @@ CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_mmu.c arm_prefetchabort.c
 CMN_CSRCS += arm_releasepending.c arm_reprioritizertr.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
 CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 # Use common heap allocation for now (may need to be customized later)
 
diff --git a/arch/arm/src/arm/arm_blocktask.c b/arch/arm/src/arm/arm_blocktask.c
index dd8378a..af41372 100644
--- a/arch/arm/src/arm/arm_blocktask.c
+++ b/arch/arm/src/arm/arm_blocktask.c
@@ -125,18 +125,11 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state)
           arm_restorestate(rtcb->xcp.regs);
         }
 
-      /* Copy the user C context into the TCB at the (old) head of the
-       * ready-to-run Task list. if arm_saveusercontext returns a non-zero
-       * value, then this is really the previously running task restarting!
-       */
+      /* No, then we will need to perform the user context switch */
 
-      else if (!arm_saveusercontext(rtcb->xcp.regs))
+      else
         {
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
+          struct tcb_s *nexttcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Make sure that the address environment for the previously
@@ -145,15 +138,23 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state)
            * thread at the head of the ready-to-run list.
            */
 
-          group_addrenv(rtcb);
+          group_addrenv(nexttcb);
 #endif
           /* Reset scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+          nxsched_resume_scheduler(nexttcb);
+
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
+           */
 
-          /* Then switch contexts */
+          arm_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
 
-          arm_fullcontextrestore(rtcb->xcp.regs);
+          /* arm_switchcontext forces a context switch to the task at the
+           * head of the ready-to-run list.  It does not 'return' in the
+           * normal sense.  When it does return, it is because the blocked
+           * task is again ready to run and has execution priority.
+           */
         }
     }
 }
diff --git a/arch/arm/src/arm/arm_fullcontextrestore.S b/arch/arm/src/arm/arm_fullcontextrestore.S
index 426098f..9c6f8e0 100644
--- a/arch/arm/src/arm/arm_fullcontextrestore.S
+++ b/arch/arm/src/arm/arm_fullcontextrestore.S
@@ -25,6 +25,9 @@
 #include <nuttx/config.h>
 #include <arch/irq.h>
 
+#include "svcall.h"
+#include "arm.h"
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -60,38 +63,14 @@
 	.type	arm_fullcontextrestore, function
 arm_fullcontextrestore:
 
-	/* On entry, a1 (r0) holds address of the register save area.  All other
-	 * registers are available for use.
-	 */
-
-	/* Recover all registers except for r0, r1, R15, and CPSR */
-
-	add	r1, r0, #(4*REG_R2)	/* Offset to REG_R2 storage */
-	ldmia	r1, {r2-r14}		/* Recover registers */
-
-	/* Create a stack frame to hold the some registers */
-
-	sub	sp, sp, #(3*4)		/* Frame for three registers */
-	ldr	r1, [r0, #(4*REG_R0)]	/* Fetch the stored r0 value */
-	str	r1, [sp]		/* Save it at the top of the stack */
-	ldr	r1, [r0, #(4*REG_R1)]	/* Fetch the stored r1 value */
-	str	r1, [sp, #4]		/* Save it in the stack */
-	ldr	r1, [r0, #(4*REG_PC)]	/* Fetch the stored pc value */
-	str	r1, [sp, #8]		/* Save it at the bottom of the frame */
-
-	/* Now we can restore the CPSR.  We wait until we are completely
-	 * finished with the context save data to do this. Restore the CPSR
-	 * may re-enable and interrupts and we could be in a context
-	 * where the save structure is only protected by interrupts being
-	 * disabled.
-	 */
-
-	ldr	r1, [r0, #(4*REG_CPSR)]	/* Fetch the stored CPSR value */
-	msr	spsr_cxsf, r1		/* Set the SPSR */
+	/* Perform the System call with R0=1 and R1=regs */
 
-	/* Now recover r0-r1, pc and cpsr, destroying the stack frame */
+	mov		r1, r0				/* R1: regs */
+	mov		r0, #SYS_restore_context	/* R0: restore context */
+	svc		#SYS_syscall			/* Force synchronous SVCall (or Hard Fault) */
 
-	ldmia	sp!, {r0-r1, r15}^
+	/* This call should not return */
 
+	bx		lr				/* Unnecessary ... will not return */
 	.size	arm_fullcontextrestore, .-arm_fullcontextrestore
 	.end
diff --git a/arch/arm/src/arm/arm_releasepending.c b/arch/arm/src/arm/arm_releasepending.c
index 656bbf3..5523098 100644
--- a/arch/arm/src/arm/arm_releasepending.c
+++ b/arch/arm/src/arm/arm_releasepending.c
@@ -93,19 +93,11 @@ void up_release_pending(void)
           arm_restorestate(rtcb->xcp.regs);
         }
 
-      /* Copy the exception context into the TCB of the task that
-       * was currently active. if arm_saveusercontext returns a non-zero
-       * value, then this is really the previously running task
-       * restarting!
-       */
+      /* No, then we will need to perform the user context switch */
 
-      else if (!arm_saveusercontext(rtcb->xcp.regs))
+      else
         {
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
+          struct tcb_s *nexttcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Make sure that the address environment for the previously
@@ -114,15 +106,23 @@ void up_release_pending(void)
            * thread at the head of the ready-to-run list.
            */
 
-          group_addrenv(rtcb);
+          group_addrenv(nexttcb);
 #endif
           /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+          nxsched_resume_scheduler(nexttcb);
 
-          /* Then switch contexts */
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
+           */
 
-          arm_fullcontextrestore(rtcb->xcp.regs);
+          arm_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+          /* arm_switchcontext forces a context switch to the task at the
+           * head of the ready-to-run list.  It does not 'return' in the
+           * normal sense.  When it does return, it is because the blocked
+           * task is again ready to run and has execution priority.
+           */
         }
     }
 }
diff --git a/arch/arm/src/arm/arm_reprioritizertr.c b/arch/arm/src/arm/arm_reprioritizertr.c
index 6d5cb0c..d916322 100644
--- a/arch/arm/src/arm/arm_reprioritizertr.c
+++ b/arch/arm/src/arm/arm_reprioritizertr.c
@@ -147,19 +147,11 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority)
               arm_restorestate(rtcb->xcp.regs);
             }
 
-          /* Copy the exception context into the TCB at the (old) head of
-           * the ready-to-run Task list. if arm_saveusercontext returns a
-           * non-zero value, then this is really the previously running task
-           * restarting!
-           */
+          /* No, then we will need to perform the user context switch */
 
-          else if (!arm_saveusercontext(rtcb->xcp.regs))
+          else
             {
-              /* Restore the exception context of the rtcb at the (new) head
-               * of the ready-to-run task list.
-               */
-
-              rtcb = this_task();
+              struct tcb_s *nexttcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
               /* Make sure that the address environment for the previously
@@ -168,15 +160,24 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority)
                * thread at the head of the ready-to-run list.
                */
 
-              group_addrenv(rtcb);
+              group_addrenv(nexttcb);
 #endif
               /* Update scheduler parameters */
 
-              nxsched_resume_scheduler(rtcb);
+              nxsched_resume_scheduler(nexttcb);
 
-              /* Then switch contexts */
+              /* Switch context to the context of the task at the head of the
+               * ready to run list.
+               */
 
-              arm_fullcontextrestore(rtcb->xcp.regs);
+              arm_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
+
+              /* arm_switchcontext forces a context switch to the task at the
+               * head of the ready-to-run list.  It does not 'return' in the
+               * normal sense.  When it does return, it is because the
+               * blocked task is again ready to run and has execution
+               * priority.
+               */
             }
         }
     }
diff --git a/arch/arm/src/arm/arm_syscall.c b/arch/arm/src/arm/arm_syscall.c
index 68f279d..074f333 100644
--- a/arch/arm/src/arm/arm_syscall.c
+++ b/arch/arm/src/arm/arm_syscall.c
@@ -32,6 +32,7 @@
 
 #include "arm_arch.h"
 #include "arm_internal.h"
+#include "svcall.h"
 
 /****************************************************************************
  * Public Functions
@@ -50,9 +51,77 @@
  *
  ****************************************************************************/
 
-void arm_syscall(uint32_t *regs)
+uint32_t *arm_syscall(uint32_t *regs)
 {
-  _alert("Syscall from 0x%" PRIx32 "\n", regs[REG_PC]);
-  CURRENT_REGS = regs;
-  PANIC();
+  uint32_t cmd;
+
+  DEBUGASSERT(regs);
+
+  cmd = regs[REG_R0];
+
+  switch (cmd)
+    {
+      /* R0=SYS_restore_context:  Restore task context
+       *
+       * void arm_fullcontextrestore(uint32_t *restoreregs)
+       *   noreturn_function;
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_restore_context
+       *   R1 = restoreregs
+       */
+
+      case SYS_restore_context:
+        {
+          /* Replace 'regs' with the pointer to the register set in
+           * regs[REG_R1].  On return from the system call, that register
+           * set will determine the restored context.
+           */
+
+          regs = (uint32_t *)regs[REG_R1];
+          DEBUGASSERT(regs);
+        }
+        break;
+
+      /* R0=SYS_switch_context:  This a switch context command:
+       *
+       *   void arm_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_switch_context
+       *   R1 = saveregs
+       *   R2 = restoreregs
+       *
+       * In this case, we do both: We save the context registers to the save
+       * register area reference by the saved contents of R1 and then set
+       * regs to the save register area referenced by the saved
+       * contents of R2.
+       */
+
+      case SYS_switch_context:
+        {
+          DEBUGASSERT(regs[REG_R1] != 0 && regs[REG_R2] != 0);
+          memcpy((uint32_t *)regs[REG_R1], regs, XCPTCONTEXT_SIZE);
+          regs = (uint32_t *)regs[REG_R2];
+        }
+        break;
+
+      default:
+        {
+          svcerr("ERROR: Bad SYS call: 0x%" PRIx32 "\n", regs[REG_R0]);
+          _alert("Syscall from 0x%" PRIx32 "\n", regs[REG_PC]);
+          CURRENT_REGS = regs;
+          PANIC();
+        }
+        break;
+    }
+
+  /* Return the last value of curent_regs.  This supports context switches
+   * on return from the exception.  That capability is only used with the
+   * SYS_context_switch system call.
+   */
+
+  return regs;
 }
diff --git a/arch/arm/src/arm/arm_unblocktask.c b/arch/arm/src/arm/arm_unblocktask.c
index 850018d..e15f35d 100644
--- a/arch/arm/src/arm/arm_unblocktask.c
+++ b/arch/arm/src/arm/arm_unblocktask.c
@@ -109,20 +109,11 @@ void up_unblock_task(struct tcb_s *tcb)
           arm_restorestate(rtcb->xcp.regs);
         }
 
-      /* We are not in an interrupt handler.  Copy the user C context
-       * into the TCB of the task that was previously active.  if
-       * arm_saveusercontext returns a non-zero value, then this is really
-       * the previously running task restarting!
-       */
+      /* No, then we will need to perform the user context switch */
 
-      else if (!arm_saveusercontext(rtcb->xcp.regs))
+      else
         {
-          /* Restore the exception context of the new task that is ready to
-           * run (probably tcb).  This is the new rtcb at the head of the
-           * ready-to-run task list.
-           */
-
-          rtcb = this_task();
+          struct tcb_s *nexttcb = this_task();
 
 #ifdef CONFIG_ARCH_ADDRENV
           /* Make sure that the address environment for the previously
@@ -131,15 +122,23 @@ void up_unblock_task(struct tcb_s *tcb)
            * thread at the head of the ready-to-run list.
            */
 
-          group_addrenv(rtcb);
+          group_addrenv(nexttcb);
 #endif
           /* Update scheduler parameters */
 
-          nxsched_resume_scheduler(rtcb);
+          nxsched_resume_scheduler(nexttcb);
+
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
+           */
 
-          /* Then switch contexts */
+          arm_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
 
-          arm_fullcontextrestore(rtcb->xcp.regs);
+          /* arm_switchcontext forces a context switch to the task at the
+           * head of the ready-to-run list.  It does not 'return' in the
+           * normal sense.  When it does return, it is because the blocked
+           * task is again ready to run and has execution priority.
+           */
         }
     }
 }
diff --git a/arch/arm/src/arm/svcall.h b/arch/arm/src/arm/svcall.h
new file mode 100644
index 0000000..a6bd67f
--- /dev/null
+++ b/arch/arm/src/arm/svcall.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * arch/arm/src/arm/svcall.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_ARM_SVCALL_H
+#define __ARCH_ARM_SRC_ARM_SVCALL_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* This logic uses one system call for the syscall return.  So a minimum of
+ * one syscall values must be reserved.  If CONFIG_BUILD_KERNEL is defined,
+ * then four more syscall values must be reserved.
+ */
+
+#ifdef CONFIG_LIB_SYSCALL
+#  ifdef CONFIG_BUILD_KERNEL
+#    ifndef CONFIG_SYS_RESERVED
+#      error "CONFIG_SYS_RESERVED must be defined to have the value 7"
+#    elif CONFIG_SYS_RESERVED != 7
+#      error "CONFIG_SYS_RESERVED must have the value 7"
+#    endif
+#  else
+#    ifndef CONFIG_SYS_RESERVED
+#      error "CONFIG_SYS_RESERVED must be defined to have the value 4"
+#    elif CONFIG_SYS_RESERVED != 4
+#      error "CONFIG_SYS_RESERVED must have the value 4"
+#    endif
+#  endif
+#endif
+
+/* Cortex-A system calls ****************************************************/
+
+/* SYS call 0:
+ *
+ * void arm_fullcontextrestore(uint32_t *restoreregs) noreturn_function;
+ */
+
+#define SYS_restore_context       (0)
+
+/* SYS call 1:
+ *
+ * void arm_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
+ */
+
+#define SYS_switch_context        (1)
+
+#ifdef CONFIG_LIB_SYSCALL
+/* SYS call 2:
+ *
+ * void arm_syscall_return(void);
+ */
+
+#define SYS_syscall_return        (2)
+
+#ifndef CONFIG_BUILD_FLAT
+#ifdef CONFIG_BUILD_KERNEL
+/* SYS call 3:
+ *
+ * void up_task_start(main_t taskentry, int argc, FAR char *argv[])
+ *        noreturn_function;
+ */
+
+#define SYS_task_start            (3)
+
+/* SYS call 5:
+ *
+ * void signal_handler(_sa_sigaction_t sighand,
+ *                     int signo, FAR siginfo_t *info,
+ *                     FAR void *ucontext);
+ */
+
+#define SYS_signal_handler        (5)
+
+/* SYS call 6:
+ *
+ * void signal_handler_return(void);
+ */
+
+#define SYS_signal_handler_return (6)
+
+#endif /* !CONFIG_BUILD_FLAT */
+
+/* SYS call 4:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (4)
+
+#endif /* CONFIG_BUILD_KERNEL */
+#endif /* CONFIG_LIB_SYSCALL */
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_ARM_SVCALL_H */
diff --git a/arch/arm/src/c5471/Make.defs b/arch/arm/src/c5471/Make.defs
index 6417377..5042ab9 100644
--- a/arch/arm/src/c5471/Make.defs
+++ b/arch/arm/src/c5471/Make.defs
@@ -29,6 +29,7 @@ CMN_CSRCS += arm_prefetchabort.c arm_releasepending.c arm_releasestack.c
 CMN_CSRCS += arm_reprioritizertr.c arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_stackframe.c arm_syscall.c arm_unblocktask.c arm_undefinedinsn.c
 CMN_CSRCS += arm_usestack.c arm_vfork.c arm_puts.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/common/arm_internal.h b/arch/arm/src/common/arm_internal.h
index ec1076d..f346159 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -390,7 +390,7 @@ void arm_dataabort(uint32_t *regs);
 /* Exception handlers */
 
 void arm_prefetchabort(uint32_t *regs);
-void arm_syscall(uint32_t *regs);
+uint32_t *arm_syscall(uint32_t *regs);
 void arm_undefinedinsn(uint32_t *regs);
 
 #endif /* CONFIG_ARCH_ARMV[6-8]M */
diff --git a/arch/arm/src/dm320/Make.defs b/arch/arm/src/dm320/Make.defs
index 352e9bb..cd12b2d 100644
--- a/arch/arm/src/dm320/Make.defs
+++ b/arch/arm/src/dm320/Make.defs
@@ -30,7 +30,7 @@ CMN_CSRCS += arm_prefetchabort.c arm_releasepending.c arm_releasestack.c
 CMN_CSRCS += arm_reprioritizertr.c arm_schedulesigaction.c
 CMN_CSRCS += arm_sigdeliver.c arm_stackframe.c arm_syscall.c arm_unblocktask.c
 CMN_CSRCS += arm_undefinedinsn.c arm_usestack.c arm_vfork.c arm_puts.c
-CMN_CSRCS += arm_tcbinfo.c
+CMN_CSRCS += arm_tcbinfo.c arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/imx1/Make.defs b/arch/arm/src/imx1/Make.defs
index 56119d7..b029236 100644
--- a/arch/arm/src/imx1/Make.defs
+++ b/arch/arm/src/imx1/Make.defs
@@ -29,7 +29,7 @@ CMN_CSRCS += arm_prefetchabort.c arm_releasepending.c arm_releasestack.c
 CMN_CSRCS += arm_reprioritizertr.c arm_schedulesigaction.c
 CMN_CSRCS += arm_sigdeliver.c arm_stackframe.c arm_syscall.c arm_unblocktask.c
 CMN_CSRCS += arm_undefinedinsn.c arm_usestack.c arm_vfork.c arm_puts.c
-CMN_CSRCS += arm_tcbinfo.c
+CMN_CSRCS += arm_tcbinfo.c arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/imx6/Make.defs b/arch/arm/src/imx6/Make.defs
index 70d9689..851c0c7 100644
--- a/arch/arm/src/imx6/Make.defs
+++ b/arch/arm/src/imx6/Make.defs
@@ -63,6 +63,7 @@ CMN_CSRCS += arm_doirq.c arm_gicv2.c arm_initialstate.c arm_mmu.c
 CMN_CSRCS += arm_prefetchabort.c arm_releasepending.c arm_reprioritizertr.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
 CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 ifeq ($(CONFIG_ARM_SEMIHOSTING_HOSTFS),y)
 CMN_CSRCS += arm_hostfs.c
diff --git a/arch/arm/src/lpc214x/Make.defs b/arch/arm/src/lpc214x/Make.defs
index 817a412..2b58faa 100644
--- a/arch/arm/src/lpc214x/Make.defs
+++ b/arch/arm/src/lpc214x/Make.defs
@@ -31,6 +31,7 @@ CMN_CSRCS += arm_releasestack.c arm_reprioritizertr.c arm_stackframe.c
 CMN_CSRCS += arm_syscall.c arm_unblocktask.c arm_undefinedinsn.c arm_usestack.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_lowputs.c arm_vfork.c arm_puts.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/lpc2378/Make.defs b/arch/arm/src/lpc2378/Make.defs
index fe42ce9..89ec926 100644
--- a/arch/arm/src/lpc2378/Make.defs
+++ b/arch/arm/src/lpc2378/Make.defs
@@ -30,6 +30,7 @@ CMN_CSRCS += arm_releasestack.c arm_reprioritizertr.c arm_stackframe.c
 CMN_CSRCS += arm_syscall.c arm_unblocktask.c arm_undefinedinsn.c
 CMN_CSRCS += arm_usestack.c arm_lowputs.c arm_vfork.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_puts.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/lpc31xx/Make.defs b/arch/arm/src/lpc31xx/Make.defs
index d0cfa81..04aa48f 100644
--- a/arch/arm/src/lpc31xx/Make.defs
+++ b/arch/arm/src/lpc31xx/Make.defs
@@ -31,7 +31,7 @@ CMN_CSRCS += arm_prefetchabort.c arm_releasepending.c arm_releasestack.c
 CMN_CSRCS += arm_reprioritizertr.c arm_schedulesigaction.c
 CMN_CSRCS += arm_sigdeliver.c arm_stackframe.c arm_syscall.c arm_unblocktask.c
 CMN_CSRCS += arm_undefinedinsn.c arm_usestack.c arm_vfork.c arm_puts.c
-CMN_CSRCS += arm_tcbinfo.c
+CMN_CSRCS += arm_tcbinfo.c arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/moxart/Make.defs b/arch/arm/src/moxart/Make.defs
index bbff29e..2e3109f 100644
--- a/arch/arm/src/moxart/Make.defs
+++ b/arch/arm/src/moxart/Make.defs
@@ -29,7 +29,7 @@ CMN_CSRCS += arm_interruptcontext.c arm_prefetchabort.c arm_releasepending.c
 CMN_CSRCS += arm_releasestack.c arm_reprioritizertr.c arm_schedulesigaction.c
 CMN_CSRCS += arm_sigdeliver.c arm_stackframe.c arm_syscall.c arm_unblocktask.c
 CMN_CSRCS += arm_undefinedinsn.c arm_usestack.c arm_vfork.c arm_etherstub.c
-CMN_CSRCS += arm_puts.c arm_tcbinfo.c
+CMN_CSRCS += arm_puts.c arm_tcbinfo.c arm_switchcontext.c
 
 CHIP_ASRCS  = moxart_lowputc.S
 
diff --git a/arch/arm/src/sama5/Make.defs b/arch/arm/src/sama5/Make.defs
index 7ba2cd0..aca45a0 100644
--- a/arch/arm/src/sama5/Make.defs
+++ b/arch/arm/src/sama5/Make.defs
@@ -62,6 +62,7 @@ CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_mmu.c arm_prefetchabort.c
 CMN_CSRCS += arm_releasepending.c arm_reprioritizertr.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
 CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 # Configuration dependent C files
 
diff --git a/arch/arm/src/str71x/Make.defs b/arch/arm/src/str71x/Make.defs
index de22749..6b93936 100644
--- a/arch/arm/src/str71x/Make.defs
+++ b/arch/arm/src/str71x/Make.defs
@@ -31,6 +31,7 @@ CMN_CSRCS += arm_releasestack.c arm_reprioritizertr.c arm_stackframe.c
 CMN_CSRCS += arm_syscall.c arm_unblocktask.c arm_undefinedinsn.c arm_usestack.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
 CMN_CSRCS += arm_lowputs.c arm_vfork.c arm_puts.c arm_tcbinfo.c
+CMN_CSRCS += arm_switchcontext.c
 
 ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
 CMN_CSRCS += arm_idle.c
diff --git a/arch/arm/src/tms570/Make.defs b/arch/arm/src/tms570/Make.defs
index f26fbaf..3e4175a 100644
--- a/arch/arm/src/tms570/Make.defs
+++ b/arch/arm/src/tms570/Make.defs
@@ -51,6 +51,7 @@ CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_prefetchabort.c
 CMN_CSRCS += arm_releasepending.c arm_reprioritizertr.c
 CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
 CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c
+CMN_CSRCS += arm_switchcontext.c
 
 # Configuration dependent C files