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/nuttx.git

commit 040eb3c990adad935409cddd077976d7742ca043
Author: Ville Juven <ville.ju...@unikie.com>
AuthorDate: Tue May 16 18:03:53 2023 +0300

    riscv/swint: Give the full tcb to the context switch routine
    
    Why? The tcb can contain info that is needed by the context switch
    routine. One example is lazy-FPU handling; the integer registers can
    be stored into the stack, because they are always stored & restored.
    
    Lazy-FPU however needs a non-volatile location to store the FPU registers
    as the save feature will skip saving a clean FPU, but the restore must
    always restore the FPU registers if the thread uses FPU.
---
 arch/risc-v/src/common/riscv_exit.c          |  2 +-
 arch/risc-v/src/common/riscv_internal.h      | 25 +++++++++++++++++++------
 arch/risc-v/src/common/riscv_sigdeliver.c    |  4 +++-
 arch/risc-v/src/common/riscv_swint.c         | 21 +++++++++++++--------
 arch/risc-v/src/common/riscv_switchcontext.c |  6 +++---
 5 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/arch/risc-v/src/common/riscv_exit.c 
b/arch/risc-v/src/common/riscv_exit.c
index c6177f29b7..143ffb438a 100644
--- a/arch/risc-v/src/common/riscv_exit.c
+++ b/arch/risc-v/src/common/riscv_exit.c
@@ -139,7 +139,7 @@ void up_exit(int status)
 
   /* Then switch contexts */
 
-  riscv_fullcontextrestore(tcb->xcp.regs);
+  riscv_fullcontextrestore(tcb);
 
   /* riscv_fullcontextrestore() should not return but could if the software
    * interrupts are disabled.
diff --git a/arch/risc-v/src/common/riscv_internal.h 
b/arch/risc-v/src/common/riscv_internal.h
index f3a50d4c95..6b385818cb 100644
--- a/arch/risc-v/src/common/riscv_internal.h
+++ b/arch/risc-v/src/common/riscv_internal.h
@@ -29,6 +29,7 @@
 
 #ifndef __ASSEMBLY__
 #  include <nuttx/compiler.h>
+#  include <nuttx/sched.h>
 #  include <sys/types.h>
 #  include <stdint.h>
 #  include <syscall.h>
@@ -207,6 +208,18 @@ void riscv_fpuconfig(void);
 #  define riscv_fpuconfig()
 #endif
 
+/* Save / restore context of task */
+
+static inline void riscv_savecontext(struct tcb_s *tcb)
+{
+  tcb->xcp.regs = (uintptr_t *)CURRENT_REGS;
+}
+
+static inline void riscv_restorecontext(struct tcb_s *tcb)
+{
+  CURRENT_REGS = (uintptr_t *)tcb->xcp.regs;
+}
+
 /* RISC-V PMP Config ********************************************************/
 
 int riscv_config_pmp_region(uintptr_t region, uintptr_t attr,
@@ -304,19 +317,19 @@ void *riscv_perform_syscall(uintptr_t *regs);
 
 /* SYS call 1:
  *
- * void riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
+ * void riscv_fullcontextrestore(struct tcb_s *next) noreturn_function;
  */
 
-#define riscv_fullcontextrestore(restoreregs) \
-  sys_call1(SYS_restore_context, (uintptr_t)restoreregs)
+#define riscv_fullcontextrestore(next) \
+  sys_call1(SYS_restore_context, (uintptr_t)next)
 
 /* SYS call 2:
  *
- * void riscv_switchcontext(uintptr_t *saveregs, uintptr_t *restoreregs);
+ * riscv_switchcontext(struct tcb_s *prev, struct tcb_s *next);
  */
 
-#define riscv_switchcontext(saveregs, restoreregs) \
-  sys_call2(SYS_switch_context, (uintptr_t)saveregs, (uintptr_t)restoreregs)
+#define riscv_switchcontext(prev, next) \
+  sys_call2(SYS_switch_context, (uintptr_t)prev, (uintptr_t)next)
 
 #ifdef CONFIG_BUILD_KERNEL
 /* SYS call 3:
diff --git a/arch/risc-v/src/common/riscv_sigdeliver.c 
b/arch/risc-v/src/common/riscv_sigdeliver.c
index c5c61cd9ca..0ff3261785 100644
--- a/arch/risc-v/src/common/riscv_sigdeliver.c
+++ b/arch/risc-v/src/common/riscv_sigdeliver.c
@@ -155,5 +155,7 @@ retry:
 #ifdef CONFIG_SMP
   rtcb->irqcount--;
 #endif
-  riscv_fullcontextrestore(regs);
+
+  rtcb->xcp.regs = regs;
+  riscv_fullcontextrestore(rtcb);
 }
diff --git a/arch/risc-v/src/common/riscv_swint.c 
b/arch/risc-v/src/common/riscv_swint.c
index 8eae2db37c..dc2c11f00e 100644
--- a/arch/risc-v/src/common/riscv_swint.c
+++ b/arch/risc-v/src/common/riscv_swint.c
@@ -135,12 +135,12 @@ int riscv_swint(int irq, void *context, void *arg)
       /* A0=SYS_restore_context: This a restore context command:
        *
        * void
-       * riscv_fullcontextrestore(uintptr_t *restoreregs) noreturn_function;
+       * void riscv_fullcontextrestore(struct tcb_s *prev) noreturn_function;
        *
        * At this point, the following values are saved in context:
        *
        *   A0 = SYS_restore_context
-       *   A1 = restoreregs
+       *   A1 = next
        *
        * In this case, we simply need to set CURRENT_REGS to restore register
        * area referenced in the saved A1. context == CURRENT_REGS is the
@@ -150,21 +150,23 @@ int riscv_swint(int irq, void *context, void *arg)
 
       case SYS_restore_context:
         {
+          struct tcb_s *next = (struct tcb_s *)regs[REG_A1];
+
           DEBUGASSERT(regs[REG_A1] != 0);
-          CURRENT_REGS = (uintptr_t *)regs[REG_A1];
+          CURRENT_REGS = (uintptr_t *)next->xcp.regs;
         }
         break;
 
       /* A0=SYS_switch_context: This a switch context command:
        *
        * void
-       * riscv_switchcontext(uintptr_t *saveregs, uintptr_t *restoreregs);
+       * riscv_switchcontext(struct tcb_s *prev, struct tcb_s *next);
        *
        * At this point, the following values are saved in context:
        *
        *   A0 = SYS_switch_context
-       *   A1 = saveregs
-       *   A2 = restoreregs
+       *   A1 = prev
+       *   A2 = next
        *
        * In this case, we save the context registers to the save register
        * area referenced by the saved contents of R5 and then set
@@ -174,9 +176,12 @@ int riscv_swint(int irq, void *context, void *arg)
 
       case SYS_switch_context:
         {
+          struct tcb_s *prev = (struct tcb_s *)regs[REG_A1];
+          struct tcb_s *next = (struct tcb_s *)regs[REG_A2];
+
           DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0);
-          *(uintptr_t **)regs[REG_A1] = (uintptr_t *)regs;
-          CURRENT_REGS = (uintptr_t *)regs[REG_A2];
+          prev->xcp.regs = (uintptr_t *)CURRENT_REGS;
+          CURRENT_REGS = (uintptr_t *)next->xcp.regs;
         }
         break;
 
diff --git a/arch/risc-v/src/common/riscv_switchcontext.c 
b/arch/risc-v/src/common/riscv_switchcontext.c
index 30ea84a00f..d39ad24b68 100644
--- a/arch/risc-v/src/common/riscv_switchcontext.c
+++ b/arch/risc-v/src/common/riscv_switchcontext.c
@@ -69,7 +69,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
        * Just copy the CURRENT_REGS into the OLD rtcb.
        */
 
-      riscv_savestate(rtcb->xcp.regs);
+      riscv_savecontext(rtcb);
 
       /* Update scheduler parameters */
 
@@ -79,7 +79,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
        * changes will be made when the interrupt returns.
        */
 
-      riscv_restorestate(tcb->xcp.regs);
+      riscv_restorecontext(tcb);
     }
 
   /* No, then we will need to perform the user context switch */
@@ -92,7 +92,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb)
 
       /* Then switch contexts */
 
-      riscv_switchcontext(&rtcb->xcp.regs, tcb->xcp.regs);
+      riscv_switchcontext(rtcb, tcb);
 
       /* riscv_switchcontext forces a context switch to the task at the
        * head of the ready-to-run list.  It does not 'return' in the

Reply via email to