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

[incubator-nuttx] branch master updated (e855215 -> fbc1da9)

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

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


    from e855215  arch/risc-v: Remove unneeded ISA specifc interface
     new f5d180b  xtensa: spit up_irq_disable and up_irq_save INTLEVEL MARCO
     new fbc1da9  xtensa: use swint to swith context

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/xtensa/include/irq.h                          |   3 +-
 arch/xtensa/include/syscall.h                      | 245 ++++++++++++++++++++-
 arch/xtensa/include/xtensa/core.h                  |   5 +
 arch/xtensa/src/common/xtensa.h                    |   1 +
 arch/xtensa/src/common/xtensa_blocktask.c          |  46 +---
 arch/xtensa/src/common/xtensa_context.S            |  58 +----
 arch/xtensa/src/common/xtensa_initialstate.c       |   8 +-
 arch/xtensa/src/common/xtensa_releasepending.c     |  48 ++--
 arch/xtensa/src/common/xtensa_reprioritizertr.c    |  49 ++---
 .../src/common/xtensa_switchcontext.c}             |   7 +-
 arch/xtensa/src/common/xtensa_unblocktask.c        |  50 ++---
 arch/xtensa/src/esp32/Make.defs                    |   2 +-
 arch/xtensa/src/esp32s2/Make.defs                  |   1 +
 arch/xtensa/src/esp32s3/Make.defs                  |   1 +
 14 files changed, 317 insertions(+), 207 deletions(-)
 copy arch/{arm/src/common/arm_switchcontext.c => xtensa/src/common/xtensa_switchcontext.c} (91%)

[incubator-nuttx] 02/02: xtensa: use swint to swith context

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit fbc1da98b7b500580a183771c938cce121056c65
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Tue Jan 11 15:08:42 2022 +0800

    xtensa: use swint to swith context
    
    Reason for use sw-interrupt as syscall interrupt:
    The xtensa `syscall` instruction can cause SYSCALL interrupt.
    But SYSCALL interrupt is same interrupt level with level-one
    interrupt.
    Nuttx swint can enter `enter_critical_section` and gerenate
    interrupt.
    
    Signed-off-by: zhuyanlin <zh...@xiaomi.com>
---
 arch/xtensa/include/syscall.h                   | 245 +++++++++++++++++++++++-
 arch/xtensa/src/common/xtensa.h                 |   1 +
 arch/xtensa/src/common/xtensa_blocktask.c       |  46 ++---
 arch/xtensa/src/common/xtensa_context.S         |  58 +-----
 arch/xtensa/src/common/xtensa_initialstate.c    |   8 +-
 arch/xtensa/src/common/xtensa_releasepending.c  |  48 ++---
 arch/xtensa/src/common/xtensa_reprioritizertr.c |  49 ++---
 arch/xtensa/src/common/xtensa_switchcontext.c   |  47 +++++
 arch/xtensa/src/common/xtensa_unblocktask.c     |  50 ++---
 arch/xtensa/src/esp32/Make.defs                 |   2 +-
 arch/xtensa/src/esp32s2/Make.defs               |   1 +
 arch/xtensa/src/esp32s3/Make.defs               |   1 +
 12 files changed, 354 insertions(+), 202 deletions(-)

diff --git a/arch/xtensa/include/syscall.h b/arch/xtensa/include/syscall.h
index be0c239..57e23b4 100644
--- a/arch/xtensa/include/syscall.h
+++ b/arch/xtensa/include/syscall.h
@@ -30,20 +30,30 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#include <arch/irq.h>
 #ifndef __ASSEMBLY__
-#  include <debug.h>
 #  include <stdint.h>
 #endif
 #ifdef CONFIG_LIB_SYSCALL
 #  include <syscall.h>
 #endif
 
+#include "xtensa_swi.h"
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
-/* Configuration ************************************************************/
+#define SYS_syscall 0x00
+
+/* The SYS_signal_handler_return is executed here... its value is not always
+ * available in this context and so is assumed to be 7.
+ */
+
+#ifndef SYS_signal_handler_return
+#  define SYS_signal_handler_return (7)
+#elif SYS_signal_handler_return != 7
+#  error "SYS_signal_handler_return was assumed to be 7"
+#endif
 
 /* This logic uses three system calls {0,1,2} for context switching and one
  * for the syscall return.  So a minimum of four syscall values must be
@@ -92,6 +102,7 @@
 
 #ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_LIB_SYSCALL
+
 /* SYS call 3:
  *
  * void xtensa_syscall_return(void);
@@ -100,6 +111,7 @@
 #define SYS_syscall_return        (3)
 
 #ifdef CONFIG_BUILD_PROTECTED
+
 /* SYS call 4:
  *
  * void up_task_start(main_t taskentry, int argc, char *argv[])
@@ -107,6 +119,7 @@
  */
 
 #define SYS_task_start            (4)
+
 /* SYS call 6:
  *
  * void signal_handler(_sa_sigaction_t sighand, int signo,
@@ -144,10 +157,23 @@
 #endif /* CONFIG_LIB_SYSCALL */
 
 /****************************************************************************
- * Public Function Prototypes
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Inline functions
  ****************************************************************************/
 
 #ifndef __ASSEMBLY__
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
 #ifdef __cplusplus
 #define EXTERN extern "C"
 extern "C"
@@ -156,10 +182,219 @@ extern "C"
 #define EXTERN extern
 #endif
 
+/****************************************************************************
+ * Name: sys_call0
+ *
+ * Description:
+ *   System call SYS_ argument and no additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call0(unsigned int nbr)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+
+  __asm__ __volatile__
+  (
+    "movi a3, %1\n"
+    "wsr a3, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0)
+    : "a3", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call1
+ *
+ * Description:
+ *   System call SYS_ argument and one additional parameter.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a4, %1\n"
+    "wsr a4, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1)
+    : "a4", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call2
+ *
+ * Description:
+ *   System call SYS_ argument and two additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1,
+                                  uintptr_t parm2)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg2 __asm__("a4") = (long)(parm2);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a5, %1\n"
+    "wsr a5, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1), "r"(reg2)
+    : "a5", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call3
+ *
+ * Description:
+ *   System call SYS_ argument and three additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1,
+                                  uintptr_t parm2, uintptr_t parm3)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg3 __asm__("a5") = (long)(parm3);
+  register long reg2 __asm__("a4") = (long)(parm2);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a6, %1\n"
+    "wsr a6, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1), "r"(reg2),
+      "r"(reg3)
+    : "a6", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call4
+ *
+ * Description:
+ *   System call SYS_ argument and four additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1,
+                                  uintptr_t parm2, uintptr_t parm3,
+                                  uintptr_t parm4)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg4 __asm__("a6") = (long)(parm4);
+  register long reg3 __asm__("a5") = (long)(parm3);
+  register long reg2 __asm__("a4") = (long)(parm2);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a7, %1\n"
+    "wsr a7, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1), "r"(reg2),
+      "r"(reg3), "r"(reg4)
+    : "a7", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call5
+ *
+ * Description:
+ *   System call SYS_ argument and five additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1,
+                                  uintptr_t parm2, uintptr_t parm3,
+                                  uintptr_t parm4, uintptr_t parm5)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg5 __asm__("a7") = (long)(parm4);
+  register long reg4 __asm__("a6") = (long)(parm4);
+  register long reg3 __asm__("a5") = (long)(parm3);
+  register long reg2 __asm__("a4") = (long)(parm2);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a8, %1\n"
+    "wsr a8, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1), "r"(reg2),
+      "r"(reg3), "r"(reg4), "r"(reg5)
+    : "a8", "memory"
+  );
+
+  return reg0;
+}
+
+/****************************************************************************
+ * Name: sys_call6
+ *
+ * Description:
+ *   System call SYS_ argument and six additional parameters.
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
+                                  uintptr_t parm2, uintptr_t parm3,
+                                  uintptr_t parm4, uintptr_t parm5,
+                                  uintptr_t parm6)
+{
+  register long reg0 __asm__("a2") = (long)(nbr);
+  register long reg6 __asm__("a8") = (long)(parm4);
+  register long reg5 __asm__("a7") = (long)(parm4);
+  register long reg4 __asm__("a6") = (long)(parm4);
+  register long reg3 __asm__("a5") = (long)(parm3);
+  register long reg2 __asm__("a4") = (long)(parm2);
+  register long reg1 __asm__("a3") = (long)(parm1);
+
+  __asm__ __volatile__
+  (
+    "movi a9, %1\n"
+    "wsr a9, intset\n"
+    "isync\n"
+    : "=r"(reg0)
+    : "i"(XCHAL_SWINT_CALL), "r"(reg0), "r"(reg1), "r"(reg2),
+      "r"(reg3), "r"(reg4), "r"(reg5)
+    : "a9", "memory"
+  );
+
+  return reg0;
+}
+
 #undef EXTERN
 #ifdef __cplusplus
 }
 #endif
-#endif
 
+#endif /* __ASSEMBLY__ */
 #endif /* __ARCH_XTENSA_INCLUDE_SYSCALL_H */
diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h
index fe1dadc..abe95c8 100644
--- a/arch/xtensa/src/common/xtensa.h
+++ b/arch/xtensa/src/common/xtensa.h
@@ -265,6 +265,7 @@ void xtensa_pause_handler(void);
 
 int xtensa_context_save(uint32_t *regs);
 void xtensa_context_restore(uint32_t *regs) noreturn_function;
+void xtensa_switchcontext(uint32_t *saveregs, uint32_t *restoreregs);
 
 #if XCHAL_CP_NUM > 0
 void xtensa_coproc_savestate(struct xtensa_cpstate_s *cpstate);
diff --git a/arch/xtensa/src/common/xtensa_blocktask.c b/arch/xtensa/src/common/xtensa_blocktask.c
index 5a8c128..f090994 100644
--- a/arch/xtensa/src/common/xtensa_blocktask.c
+++ b/arch/xtensa/src/common/xtensa_blocktask.c
@@ -126,49 +126,27 @@ void up_block_task(struct tcb_s *tcb, tstate_t task_state)
           xtensa_restorestate(rtcb->xcp.regs);
         }
 
-      /* Copy the user C context into the TCB at the (old) head of the
-       * ready-to-run Task list. if up_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 (!xtensa_context_save(rtcb->xcp.regs))
+      else
         {
-#if XCHAL_CP_NUM > 0
-          /* Save the co-processor state in in the suspended thread's co-
-           * processor save area.
-           */
-
-          xtensa_coproc_savestate(&rtcb->xcp.cpstate);
-#endif
+          struct tcb_s *nexttcb = this_task();
 
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
            */
 
-          rtcb = this_task();
+          nxsched_resume_scheduler(nexttcb);
 
-#if XCHAL_CP_NUM > 0
-          /* Set up the co-processor state for the newly started thread. */
+          /* Then switch contexts */
 
-          xtensa_coproc_restorestate(&rtcb->xcp.cpstate);
-#endif
+          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->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
-           * thread at the head of the ready-to-run list.
+          /* xtensa_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.
            */
-
-          group_addrenv(rtcb);
-#endif
-          /* Reset scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts */
-
-          xtensa_context_restore(rtcb->xcp.regs);
         }
     }
 }
diff --git a/arch/xtensa/src/common/xtensa_context.S b/arch/xtensa/src/common/xtensa_context.S
index a733b3a..6885d4a 100644
--- a/arch/xtensa/src/common/xtensa_context.S
+++ b/arch/xtensa/src/common/xtensa_context.S
@@ -66,6 +66,9 @@
 #include <arch/xtensa/xtensa_abi.h>
 #include <arch/xtensa/xtensa_specregs.h>
 
+#include "syscall.h"
+#include "xtensa_swi.h"
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -541,55 +544,12 @@ _xtensa_context_restore:
 xtensa_context_restore:
 	ENTRY(16)
 
-#ifndef __XTENSA_CALL0_ABI__
-	/* Force a spill of the live registers of the thread that has been
-	 * suspended.
-	 *
-	 * _xtensa_window_spill return state:
-	 *   a2, a3: clobbered
-	 *   a4,a5,a8,a9,a12,a13: preserved
-	 *   a6,a7,a10,a11,a14,a15 clobbered if they were part of window(s)
-	 *      to be spilled, otherwise they are the same as on entry
-	 *   loop registers: Preserved
-	 *   SAR: clobbered
-	 *
-	 * We need to preserve only a2 for _xtensa_context_restore
-	 */
+	mov  a3, a2
+	movi a2, SYS_restore_context
+	movi a4, XCHAL_SWINT_CALL
+	wsr  a4, intset
+	isync
 
-	mov		a4, a2							/* Save a2 in a preserved register */
-	rsr		a5, PS							/* Save PS in preserved register */
-
-	movi	a3, ~(PS_WOE_MASK | PS_INTLEVEL_MASK)
-	and		a2, a5, a3						/* Clear WOE, INTLEVEL */
-	addi	a2, a2, XCHAL_EXCM_LEVEL		/* Set INTLEVEL = XCHAL_EXCM_LEVEL */
-	wsr		a2, PS							/* Apply to PS */
-	rsync
-
-	call0	_xtensa_window_spill
-	wsr		a5, PS							/* Restore PS */
-	rsync
-
-	mov		a2, a4							/* Recover a2 */
-#endif
-
-	/* Restore the processor state for the newly started thread */
-
-	call0	_xtensa_context_restore			/* Restore full register state */
-
-	/* Restore PC, PS, A0, and A2. */
-
-	l32i	a0, a2, (4 * REG_PS)			/* Restore PS */
-	wsr		a0, PS
-	l32i	a0, a2, (4 * REG_PC)			/* Set up for RFE */
-	wsr		a0, EPC_1
-	l32i	a0, a2, (4 * REG_A0)			/* Restore a0 */
-	l32i	a2, a2, (4 * REG_A2)			/* Restore A2 */
-
-	/* Return from exception. RFE returns from either the UserExceptionVector
-	 * or the KernelExceptionVector.  RFE sets PS.EXCM back to 0, and then
-	 * jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
-	 */
-
-	rfe										/* And return from "exception" */
+	RET(16)
 
 	.size	xtensa_context_restore, . - xtensa_context_restore
diff --git a/arch/xtensa/src/common/xtensa_initialstate.c b/arch/xtensa/src/common/xtensa_initialstate.c
index 5557c58..9b5157a 100644
--- a/arch/xtensa/src/common/xtensa_initialstate.c
+++ b/arch/xtensa/src/common/xtensa_initialstate.c
@@ -87,17 +87,15 @@ void up_initial_state(struct tcb_s *tcb)
   xcp->regs[REG_A1]   = (uint32_t)tcb->stack_base_ptr + /* Physical top of stack frame    */
                                   tcb->adj_stack_size;
 
-  /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user
-   * mode.
-   */
+  /* Set initial PS to int level 0, user mode. */
 
 #ifdef __XTENSA_CALL0_ABI__
-  xcp->regs[REG_PS]   = PS_UM | PS_EXCM;
+  xcp->regs[REG_PS]   = PS_UM;
 
 #else
   /* For windowed ABI set WOE and CALLINC (pretend task was 'call4'd). */
 
-  xcp->regs[REG_PS]   = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1);
+  xcp->regs[REG_PS]   = PS_UM | PS_WOE | PS_CALLINC(1);
 #endif
 
 #if XCHAL_CP_NUM > 0
diff --git a/arch/xtensa/src/common/xtensa_releasepending.c b/arch/xtensa/src/common/xtensa_releasepending.c
index 3614050..2630b7e 100644
--- a/arch/xtensa/src/common/xtensa_releasepending.c
+++ b/arch/xtensa/src/common/xtensa_releasepending.c
@@ -97,49 +97,27 @@ void up_release_pending(void)
           xtensa_restorestate(rtcb->xcp.regs);
         }
 
-      /* Copy the exception context into the TCB of the task that
-       * was currently active. if up_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 (!xtensa_context_save(rtcb->xcp.regs))
+      else
         {
-#if XCHAL_CP_NUM > 0
-          /* Save the co-processor state in in the suspended thread's co-
-           * processor save area.
-           */
+          struct tcb_s *nexttcb = this_task();
 
-          xtensa_coproc_savestate(&rtcb->xcp.cpstate);
-#endif
-          /* Restore the exception context of the rtcb at the (new) head
-           * of the ready-to-run task list.
-           */
-
-          rtcb = this_task();
+          /* Reset scheduler parameters */
 
-#if XCHAL_CP_NUM > 0
-          /* Set up the co-processor state for the newly started thread. */
+          nxsched_resume_scheduler(nexttcb);
 
-          xtensa_coproc_restorestate(&rtcb->xcp.cpstate);
-#endif
-
-#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
-           * thread at the head of the ready-to-run list.
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
            */
 
-          group_addrenv(rtcb);
-#endif
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts */
+          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
 
-          xtensa_context_restore(rtcb->xcp.regs);
+          /* xtensa_switchcontext forces a context switch to the task at the
+           * head of the ready-to-run list.  It does not 'return' in the
+           * 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/xtensa/src/common/xtensa_reprioritizertr.c b/arch/xtensa/src/common/xtensa_reprioritizertr.c
index 760a1c2..624b73e 100644
--- a/arch/xtensa/src/common/xtensa_reprioritizertr.c
+++ b/arch/xtensa/src/common/xtensa_reprioritizertr.c
@@ -149,51 +149,28 @@ void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority)
               xtensa_restorestate(rtcb->xcp.regs);
             }
 
-          /* Copy the exception context into the TCB at the (old) head of the
-           * ready-to-run Task list. if up_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 (!xtensa_context_save(rtcb->xcp.regs))
+          else
             {
-#if XCHAL_CP_NUM > 0
-              /* Save the co-processor state in in the suspended thread's co-
-               * processor save area.
-               */
+              struct tcb_s *nexttcb = this_task();
 
-              xtensa_coproc_savestate(&rtcb->xcp.cpstate);
-#endif
-              /* Restore the exception context of the rtcb at the (new) head
-               * of the ready-to-run task list.
-               */
+              /* Reset scheduler parameters */
 
-              rtcb = this_task();
+              nxsched_resume_scheduler(nexttcb);
 
-#if XCHAL_CP_NUM > 0
-              /* Set up the co-processor state for the newly started
-               * thread.
+              /* Switch context to the context of the task at the head of the
+               * ready to run list.
                */
 
-              xtensa_coproc_restorestate(&rtcb->xcp.cpstate);
-#endif
+              xtensa_switchcontext(rtcb->xcp.regs, nexttcb->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
-               * thread at the head of the ready-to-run list.
+              /* xtensa_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.
                */
-
-              group_addrenv(rtcb);
-#endif
-              /* Update scheduler parameters */
-
-              nxsched_resume_scheduler(rtcb);
-
-              /* Then switch contexts */
-
-              xtensa_context_restore(rtcb->xcp.regs);
             }
         }
     }
diff --git a/arch/xtensa/src/common/xtensa_switchcontext.c b/arch/xtensa/src/common/xtensa_switchcontext.c
new file mode 100644
index 0000000..3aecda2
--- /dev/null
+++ b/arch/xtensa/src/common/xtensa_switchcontext.c
@@ -0,0 +1,47 @@
+/****************************************************************************
+ * arch/xtensa/src/common/xtensa_switchcontext.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "syscall.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: xtensa_switchcontext
+ *
+ * Description:
+ *   Save the current thread context and restore the specified context.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void xtensa_switchcontext(uint32_t *saveregs, uint32_t *restoreregs)
+{
+  sys_call2(SYS_switch_context, (uintptr_t)saveregs, (uintptr_t)restoreregs);
+}
diff --git a/arch/xtensa/src/common/xtensa_unblocktask.c b/arch/xtensa/src/common/xtensa_unblocktask.c
index a1e42a0..4d975fb 100644
--- a/arch/xtensa/src/common/xtensa_unblocktask.c
+++ b/arch/xtensa/src/common/xtensa_unblocktask.c
@@ -111,51 +111,27 @@ void up_unblock_task(struct tcb_s *tcb)
           xtensa_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
-       * up_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 (!xtensa_context_save(rtcb->xcp.regs))
+      else
         {
-#if XCHAL_CP_NUM > 0
-          /* Save the co-processor state in in the suspended thread's co-
-           * processor save area.
-           */
-
-          xtensa_coproc_savestate(&rtcb->xcp.cpstate);
-#endif
-
-          /* 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();
 
-#if XCHAL_CP_NUM > 0
-          /* Set up the co-processor state for the newly started thread. */
+          /* Reset scheduler parameters */
 
-          xtensa_coproc_restorestate(&rtcb->xcp.cpstate);
-#endif
+          nxsched_resume_scheduler(nexttcb);
 
-#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
-           * thread at the head of the ready-to-run list.
+          /* Switch context to the context of the task at the head of the
+           * ready to run list.
            */
 
-          group_addrenv(rtcb);
-#endif
-          /* Update scheduler parameters */
-
-          nxsched_resume_scheduler(rtcb);
-
-          /* Then switch contexts */
+          xtensa_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs);
 
-          xtensa_context_restore(rtcb->xcp.regs);
+          /* xtensa_switchcontext forces a context switch to the task at the
+           * head of the ready-to-run list.  It does not 'return' in the
+           * 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/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index 5a1b015..dbd1374 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -40,7 +40,7 @@ CMN_CSRCS += xtensa_puts.c xtensa_releasepending.c xtensa_releasestack.c
 CMN_CSRCS += xtensa_reprioritizertr.c xtensa_schedsigaction.c
 CMN_CSRCS += xtensa_sigdeliver.c xtensa_stackframe.c xtensa_udelay.c
 CMN_CSRCS += xtensa_unblocktask.c xtensa_usestack.c xtensa_swint.c
-CMN_CSRCS += esp32_systemreset.c esp32_resetcause.c
+CMN_CSRCS += esp32_systemreset.c esp32_resetcause.c xtensa_switchcontext.c
 
 # Configuration-dependent common XTENSA files
 
diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs
index 7232e7f..da5a44a 100644
--- a/arch/xtensa/src/esp32s2/Make.defs
+++ b/arch/xtensa/src/esp32s2/Make.defs
@@ -40,6 +40,7 @@ CMN_CSRCS += xtensa_puts.c xtensa_releasepending.c xtensa_releasestack.c
 CMN_CSRCS += xtensa_reprioritizertr.c xtensa_schedsigaction.c
 CMN_CSRCS += xtensa_sigdeliver.c xtensa_stackframe.c xtensa_udelay.c
 CMN_CSRCS += xtensa_unblocktask.c xtensa_usestack.c xtensa_swint.c
+CMN_CSRCS += xtensa_switchcontext.c
 
 # Configuration-dependent common XTENSA files
 
diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs
index 339edfe..d70c4a3 100644
--- a/arch/xtensa/src/esp32s3/Make.defs
+++ b/arch/xtensa/src/esp32s3/Make.defs
@@ -40,6 +40,7 @@ CMN_CSRCS += xtensa_puts.c xtensa_releasepending.c xtensa_releasestack.c
 CMN_CSRCS += xtensa_reprioritizertr.c xtensa_schedsigaction.c
 CMN_CSRCS += xtensa_sigdeliver.c xtensa_stackframe.c xtensa_udelay.c
 CMN_CSRCS += xtensa_unblocktask.c xtensa_usestack.c xtensa_swint.c
+CMN_CSRCS += xtensa_switchcontext.c
 
 # Configuration-dependent common XTENSA files
 

[incubator-nuttx] 01/02: xtensa: spit up_irq_disable and up_irq_save INTLEVEL MARCO

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f5d180bbdf2d855129909024ba691baf4518fe58
Author: zhuyanlin <zh...@xiaomi.com>
AuthorDate: Fri Jan 14 16:52:11 2022 +0800

    xtensa: spit up_irq_disable and up_irq_save INTLEVEL MARCO
    
    For up_irq_disable, use XCHAL_EXCM_LEVEL
    For up_irq_save,  use XCHAL_IRQ_LEVEL.
    Then we can use svcall in enter_crritical_section.
    
    Signed-off-by: zhuyanlin <zh...@xiaomi.com>
---
 arch/xtensa/include/irq.h         | 3 ++-
 arch/xtensa/include/xtensa/core.h | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/xtensa/include/irq.h b/arch/xtensa/include/irq.h
index d6808af..cf99de0 100644
--- a/arch/xtensa/include/irq.h
+++ b/arch/xtensa/include/irq.h
@@ -37,6 +37,7 @@
 #include <arch/types.h>
 #include <arch/chip/tie.h>
 #include <arch/chip/core-isa.h>
+#include <arch/xtensa/core.h>
 
 #include <arch/xtensa/xtensa_specregs.h>
 #include <arch/xtensa/xtensa_corebits.h>
@@ -233,7 +234,7 @@ static inline uint32_t up_irq_save(void)
 
   __asm__ __volatile__
   (
-    "rsil %0, %1" : "=r"(ps) : "i"(XCHAL_EXCM_LEVEL)
+    "rsil %0, %1" : "=r"(ps) : "i"(XCHAL_IRQ_LEVEL)
   );
 
   /* Return the previous PS value so that it can be restored with
diff --git a/arch/xtensa/include/xtensa/core.h b/arch/xtensa/include/xtensa/core.h
index 6efab57..1385abd 100644
--- a/arch/xtensa/include/xtensa/core.h
+++ b/arch/xtensa/include/xtensa/core.h
@@ -90,6 +90,11 @@
 /* Interrupts ***************************************************************/
 
 /* Indexing macros: */
+#ifndef XCHAL_SYSCALL_LEVEL
+#  define XCHAL_IRQ_LEVEL  XCHAL_EXCM_LEVEL
+#else
+#  define XCHAL_IRQ_LEVEL  XCHAL_SYSCALL_LEVEL
+#endif
 
 #define _XCHAL_INTLEVEL_MASK(n)         XCHAL_INTLEVEL ## n ## _MASK
 #define XCHAL_INTLEVEL_MASK(n)          _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */