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

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


The following commit(s) were added to refs/heads/master by this push:
     new a014daf44f RISC-V: Add implementation for vfork
a014daf44f is described below

commit a014daf44f29866b82250bd9cc777672d667406c
Author: Ville Juven <[email protected]>
AuthorDate: Tue Apr 19 15:41:09 2022 +0300

    RISC-V: Add implementation for vfork
---
 arch/Kconfig                         |   1 +
 arch/risc-v/src/bl602/Make.defs      |   1 +
 arch/risc-v/src/c906/Make.defs       |   1 +
 arch/risc-v/src/common/riscv_vfork.c |  56 ++++++++-------
 arch/risc-v/src/common/riscv_vfork.h |  58 ++++++++--------
 arch/risc-v/src/common/vfork.S       | 130 +++++++++++++++++++++++++++++++++++
 arch/risc-v/src/esp32c3/Make.defs    |   3 +-
 arch/risc-v/src/fe310/Make.defs      |   1 +
 arch/risc-v/src/k210/Make.defs       |   1 +
 arch/risc-v/src/litex/Make.defs      |   1 +
 arch/risc-v/src/mpfs/Make.defs       |   1 +
 arch/risc-v/src/qemu-rv/Make.defs    |   1 +
 arch/risc-v/src/rv32m1/Make.defs     |   1 +
 13 files changed, 201 insertions(+), 55 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 365ffbd314..530f2d0d45 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -64,6 +64,7 @@ config ARCH_RISCV
        select ARCH_HAVE_BACKTRACE
        select ARCH_HAVE_INTERRUPTSTACK
        select ARCH_HAVE_STACKCHECK
+       select ARCH_HAVE_VFORK
        select ARCH_HAVE_CUSTOMOPT
        select ARCH_HAVE_SETJMP
        select ARCH_HAVE_STDARG_H
diff --git a/arch/risc-v/src/bl602/Make.defs b/arch/risc-v/src/bl602/Make.defs
index 72e53b5484..205af29f26 100644
--- a/arch/risc-v/src/bl602/Make.defs
+++ b/arch/risc-v/src/bl602/Make.defs
@@ -51,6 +51,7 @@ CMN_CSRCS += riscv_fpucmp.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/c906/Make.defs b/arch/risc-v/src/c906/Make.defs
index 52c7cac166..075b739e16 100644
--- a/arch/risc-v/src/c906/Make.defs
+++ b/arch/risc-v/src/c906/Make.defs
@@ -51,6 +51,7 @@ CMN_CSRCS += riscv_fpucmp.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/common/riscv_vfork.c 
b/arch/risc-v/src/common/riscv_vfork.c
index 29e091b03f..0e2c3ebc82 100644
--- a/arch/risc-v/src/common/riscv_vfork.c
+++ b/arch/risc-v/src/common/riscv_vfork.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/rv32im/riscv_vfork.c
+ * arch/risc-v/src/common/riscv_vfork.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -35,6 +35,8 @@
 #include <arch/irq.h>
 
 #include "riscv_vfork.h"
+#include "riscv_internal.h"
+
 #include "sched/sched.h"
 
 /****************************************************************************
@@ -95,40 +97,39 @@
 
 #ifdef CONFIG_ARCH_HAVE_VFORK
 
-#error This part of the port is not done yet!!
-
 pid_t up_vfork(const struct vfork_s *context)
 {
   struct tcb_s *parent = this_task();
   struct task_tcb_s *child;
-  uint32_t newsp;
+  uintptr_t newsp;
 #ifdef CONFIG_RISCV_FRAMEPOINTER
-  uint32_t newfp;
+  uintptr_t newfp;
 #endif
-  uint32_t newtop;
-  uint32_t stacktop;
-  uint32_t stackutil;
+  uintptr_t newtop;
+  uintptr_t stacktop;
+  uintptr_t stackutil;
 
-  sinfo("s0:%08x s1:%08x s2:%08x s3:%08x s4:%08x\n",
+  sinfo("s0:%" PRIxREG " s1:%" PRIxREG " s2:%" PRIxREG " s3:%" PRIxREG ""
+        " s4:%" PRIxREG "\n",
         context->s0, context->s1, context->s2, context->s3, context->s4);
 #ifdef CONFIG_RISCV_FRAMEPOINTER
-  sinfo("s5:%08x s6:%08x s7:%08x\n",
+  sinfo("s5:%" PRIxREG " s6:%" PRIxREG " s7:%" PRIxREG "\n",
         context->s5, context->s6, context->s7);
 #ifdef RISCV_SAVE_GP
-  sinfo("fp:%08x sp:%08x ra:%08x gp:%08x\n",
+  sinfo("fp:%" PRIxREG " sp:%" PRIxREG " ra:%" PRIxREG " gp:%" PRIxREG "\n",
         context->fp, context->sp, context->ra, context->gp);
 #else
-  sinfo("fp:%08x sp:%08x ra:%08x\n",
+  sinfo("fp:%" PRIxREG " sp:%" PRIxREG " ra:%" PRIxREG "\n",
         context->fp context->sp, context->ra);
 #endif
 #else
-  sinfo("s5:%08x s6:%08x s7:%08x s8:%08x\n",
+  sinfo("s5:%" PRIxREG " s6:%" PRIxREG " s7:%" PRIxREG " s8:%" PRIxREG "\n",
         context->s5, context->s6, context->s7, context->s8);
 #ifdef RISCV_SAVE_GP
-  sinfo("sp:%08x ra:%08x gp:%08x\n",
+  sinfo("sp:%" PRIxREG " ra:%" PRIxREG " gp:%" PRIxREG "\n",
         context->sp, context->ra, context->gp);
 #else
-  sinfo("sp:%08x ra:%08x\n",
+  sinfo("sp:%" PRIxREG " ra:%" PRIxREG "\n",
         context->sp, context->ra);
 #endif
 #endif
@@ -150,12 +151,11 @@ pid_t up_vfork(const struct vfork_s *context)
    * stack usage should be the difference between those two.
    */
 
-  stacktop = (uint32_t)parent->stack_base_ptr +
-                       parent->adj_stack_size;
+  stacktop = (uintptr_t)parent->stack_base_ptr + parent->adj_stack_size;
   DEBUGASSERT(stacktop > context->sp);
   stackutil = stacktop - context->sp;
 
-  sinfo("Parent: stackutil:%" PRIu32 "\n", stackutil);
+  sinfo("Parent: stackutil:%" PRIxREG "\n", stackutil);
 
   /* Make some feeble effort to preserve the stack contents.  This is
    * feeble because the stack surely contains invalid pointers and other
@@ -164,9 +164,15 @@ pid_t up_vfork(const struct vfork_s *context)
    * effort is overkill.
    */
 
-  newtop = (uint32_t)child->cmn.stack_base_ptr +
-                     child->cmn.adj_stack_size;
+  newtop = (uintptr_t)child->cmn.stack_base_ptr + child->cmn.adj_stack_size;
   newsp = newtop - stackutil;
+
+  /* Set up frame for context */
+
+  memcpy((void *)(newsp - XCPTCONTEXT_SIZE),
+         child->cmn.xcp.regs, XCPTCONTEXT_SIZE);
+
+  child->cmn.xcp.regs = (void *)(newsp - XCPTCONTEXT_SIZE);
   memcpy((void *)newsp, (const void *)context->sp, stackutil);
 
   /* Was there a frame pointer in place before? */
@@ -174,7 +180,7 @@ pid_t up_vfork(const struct vfork_s *context)
 #ifdef CONFIG_RISCV_FRAMEPOINTER
   if (context->fp >= context->sp && context->fp < stacktop)
     {
-      uint32_t frameutil = stacktop - context->fp;
+      uintptr_t frameutil = stacktop - context->fp;
       newfp = newtop - frameutil;
     }
   else
@@ -182,14 +188,14 @@ pid_t up_vfork(const struct vfork_s *context)
       newfp = context->fp;
     }
 
-  sinfo("Old stack top:%08x SP:%08x FP:%08x\n",
+  sinfo("Old stack top:%" PRIxREG " SP:%" PRIxREG " FP:%" PRIxREG "\n",
         stacktop, context->sp, context->fp);
-  sinfo("New stack top:%08x SP:%08x FP:%08x\n",
+  sinfo("New stack top:%" PRIxREG " SP:%" PRIxREG " FP:%" PRIxREG "\n",
         newtop, newsp, newfp);
 #else
-  sinfo("Old stack top:%08x SP:%08x\n",
+  sinfo("Old stack top:%" PRIxREG " SP:%" PRIxREG "\n",
         stacktop, context->sp);
-  sinfo("New stack top:%08x SP:%08x\n",
+  sinfo("New stack top:%" PRIxREG " SP:%" PRIxREG "\n",
         newtop, newsp);
 #endif
 
diff --git a/arch/risc-v/src/common/riscv_vfork.h 
b/arch/risc-v/src/common/riscv_vfork.h
index cf07984b47..24fed6942b 100644
--- a/arch/risc-v/src/common/riscv_vfork.h
+++ b/arch/risc-v/src/common/riscv_vfork.h
@@ -26,7 +26,7 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#include <arch/mips32/irq.h>
+#include <arch/irq.h>
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -60,28 +60,28 @@
  * r31     ra     Return address.
  */
 
-#define VFORK_S0_OFFSET   (0*4)   /* Saved register s0 */
-#define VFORK_S1_OFFSET   (1*4)   /* Saved register s1 */
-#define VFORK_S2_OFFSET   (2*4)   /* Saved register s2 */
-#define VFORK_S3_OFFSET   (3*4)   /* Saved register s3 */
-#define VFORK_S4_OFFSET   (4*4)   /* Saved register s4 */
-#define VFORK_S5_OFFSET   (5*4)   /* Saved register s5 */
-#define VFORK_S6_OFFSET   (6*4)   /* Saved register s6 */
-#define VFORK_S7_OFFSET   (7*4)   /* Saved register s7 */
+#define VFORK_S0_OFFSET   (0*INT_REG_SIZE)   /* Saved register s0 */
+#define VFORK_S1_OFFSET   (1*INT_REG_SIZE)   /* Saved register s1 */
+#define VFORK_S2_OFFSET   (2*INT_REG_SIZE)   /* Saved register s2 */
+#define VFORK_S3_OFFSET   (3*INT_REG_SIZE)   /* Saved register s3 */
+#define VFORK_S4_OFFSET   (4*INT_REG_SIZE)   /* Saved register s4 */
+#define VFORK_S5_OFFSET   (5*INT_REG_SIZE)   /* Saved register s5 */
+#define VFORK_S6_OFFSET   (6*INT_REG_SIZE)   /* Saved register s6 */
+#define VFORK_S7_OFFSET   (7*INT_REG_SIZE)   /* Saved register s7 */
 
 #ifdef CONFIG_RISCV_FRAMEPOINTER
-#  define VFORK_FP_OFFSET (8*4)   /* Frame pointer */
+#  define VFORK_FP_OFFSET (8*INT_REG_SIZE)   /* Frame pointer */
 #else
-#  define VFORK_S8_OFFSET (8*4)   /* Saved register s8 */
+#  define VFORK_S8_OFFSET (8*INT_REG_SIZE)   /* Saved register s8 */
 #endif
 
-#define VFORK_SP_OFFSET   (9*4)   /* Stack pointer*/
-#define VFORK_RA_OFFSET   (10*4)  /* Return address*/
+#define VFORK_SP_OFFSET   (9*INT_REG_SIZE)   /* Stack pointer*/
+#define VFORK_RA_OFFSET   (10*INT_REG_SIZE)  /* Return address*/
 #ifdef RISCV_SAVE_GP
-#  define VFORK_GP_OFFSET (11*4)   /* Global pointer */
-#  define VFORK_SIZEOF    (12*4)
+#  define VFORK_GP_OFFSET (11*INT_REG_SIZE)  /* Global pointer */
+#  define VFORK_SIZEOF    (12*INT_REG_SIZE)
 #else
-#  define VFORK_SIZEOF    (11*4)
+#  define VFORK_SIZEOF    (11*INT_REG_SIZE)
 #endif
 
 /****************************************************************************
@@ -93,23 +93,23 @@ struct vfork_s
 {
   /* CPU registers */
 
-  uint32_t s0;   /* Saved register s0 */
-  uint32_t s1;   /* Saved register s1 */
-  uint32_t s2;   /* Saved register s2 */
-  uint32_t s3;   /* Saved register s3 */
-  uint32_t s4;   /* Saved register s4 */
-  uint32_t s5;   /* Saved register s5 */
-  uint32_t s6;   /* Saved register s6 */
-  uint32_t s7;   /* Saved register s7 */
+  uintptr_t s0;   /* Saved register s0 */
+  uintptr_t s1;   /* Saved register s1 */
+  uintptr_t s2;   /* Saved register s2 */
+  uintptr_t s3;   /* Saved register s3 */
+  uintptr_t s4;   /* Saved register s4 */
+  uintptr_t s5;   /* Saved register s5 */
+  uintptr_t s6;   /* Saved register s6 */
+  uintptr_t s7;   /* Saved register s7 */
 #ifdef CONFIG_RISCV_FRAMEPOINTER
-  uint32_t fp;   /* Frame pointer */
+  uintptr_t fp;   /* Frame pointer */
 #else
-  uint32_t s8;   /* Saved register s8 */
+  uintptr_t s8;   /* Saved register s8 */
 #endif
-  uint32_t sp;   /* Stack pointer */
-  uint32_t ra;   /* Return address */
+  uintptr_t sp;   /* Stack pointer */
+  uintptr_t ra;   /* Return address */
 #ifdef RISCV_SAVE_GP
-  uint32_t gp;   /* Global pointer */
+  uintptr_t gp;   /* Global pointer */
 #endif
 
   /* Floating point registers (not yet) */
diff --git a/arch/risc-v/src/common/vfork.S b/arch/risc-v/src/common/vfork.S
new file mode 100644
index 0000000000..379f5fa3bf
--- /dev/null
+++ b/arch/risc-v/src/common/vfork.S
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * arch/risc-v/src/common/vfork.S
+ *
+ * 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 "riscv_vfork.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Symbols
+ ****************************************************************************/
+
+  .file  "vfork.S"
+  .globl up_vfork
+  .globl vfork
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vfork
+ *
+ * Description:
+ *   The vfork() function has the same effect as fork(), except that the
+ *   behavior is undefined if the process created by vfork() either modifies
+ *   any data other than a variable of type pid_t used to store the return
+ *   value from vfork(), or returns from the function in which vfork() was
+ *   called, or calls any other function before successfully calling _exit()
+ *   or one of the exec family of functions.
+ *
+ *   This thin layer implements vfork by simply calling up_vfork() with the
+ *   vfork() context as an argument.  The overall sequence is:
+ *
+ *   1) User code calls vfork().  vfork() collects context information and
+ *      transfers control up up_vfork().
+ *   2) up_vfork() and calls nxtask_setup_vfork().
+ *   3) nxtask_setup_vfork() allocates and configures the child task's TCB.
+ *      This consists of:
+ *      - Allocation of the child task's TCB.
+ *      - Initialization of file descriptors and streams
+ *      - Configuration of environment variables
+ *      - Allocate and initialize the stack
+ *      - Setup the input parameters for the task.
+ *      - Initialization of the TCB (including call to up_initial_state())
+ *   4) up_vfork() provides any additional operating context. up_vfork must:
+ *      - Initialize special values in any CPU registers that were not
+ *        already configured by up_initial_state()
+ *   5) up_vfork() then calls nxtask_start_vfork()
+ *   6) nxtask_start_vfork() then executes the child thread.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Upon successful completion, vfork() returns 0 to the child process and
+ *   returns the process ID of the child process to the parent process.
+ *   Otherwise, -1 is returned to the parent, no child process is created,
+ *   and errno is set to indicate the error.
+ *
+ ****************************************************************************/
+
+.type vfork, function
+
+vfork:
+  /* Create a stack frame */
+
+  addi        sp, sp, -VFORK_SIZEOF
+
+  /* CPU registers */
+  /* Save the volatile registers */
+
+  REGSTORE    s0, VFORK_S0_OFFSET(sp)
+  REGSTORE    s1, VFORK_S1_OFFSET(sp)
+  REGSTORE    s2, VFORK_S2_OFFSET(sp)
+  REGSTORE    s3, VFORK_S3_OFFSET(sp)
+  REGSTORE    s4, VFORK_S4_OFFSET(sp)
+  REGSTORE    s5, VFORK_S5_OFFSET(sp)
+  REGSTORE    s6, VFORK_S6_OFFSET(sp)
+  REGSTORE    s7, VFORK_S7_OFFSET(sp)
+
+  /* Save the frame pointer, stack pointer, and return address */
+
+#ifdef CONFIG_RISCV_FRAMEPOINTER
+  REGSTORE    fp, VFORK_FP_OFFSET(sp)
+#endif
+  addi        s0, sp, VFORK_SIZEOF
+  REGSTORE    s0, VFORK_SP_OFFSET(sp) /* original SP */
+  REGSTORE    x1, VFORK_RA_OFFSET(sp) /* return address */
+
+  /* Floating point registers (not yet) */
+
+  /* Then, call up_vfork(), passing it a pointer to the stack frame */
+
+  mv          a0, sp
+  jal         x1, up_vfork
+
+  /* Release the stack frame and return the value returned by up_vfork */
+
+  REGLOAD     x1, VFORK_RA_OFFSET(sp)
+  addi        sp, sp, VFORK_SIZEOF
+  ret
+
+  .size  vfork, .-vfork
+  .end
diff --git a/arch/risc-v/src/esp32c3/Make.defs 
b/arch/risc-v/src/esp32c3/Make.defs
index 15640d9392..db2ff2b812 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -52,7 +52,8 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
-CMN_CSRCS  += riscv_vfork.c
+CMN_ASRCS += vfork.S
+CMN_CSRCS += riscv_vfork.c
 endif
 
 # Specify our C code within this directory to be included
diff --git a/arch/risc-v/src/fe310/Make.defs b/arch/risc-v/src/fe310/Make.defs
index 4b09e739cc..0d865f393b 100644
--- a/arch/risc-v/src/fe310/Make.defs
+++ b/arch/risc-v/src/fe310/Make.defs
@@ -45,6 +45,7 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs
index 9f2d6411d1..8912c37960 100644
--- a/arch/risc-v/src/k210/Make.defs
+++ b/arch/risc-v/src/k210/Make.defs
@@ -51,6 +51,7 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/litex/Make.defs b/arch/risc-v/src/litex/Make.defs
index 768d5269ad..f4230c03b1 100644
--- a/arch/risc-v/src/litex/Make.defs
+++ b/arch/risc-v/src/litex/Make.defs
@@ -45,6 +45,7 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs
index c58e938036..479d00c825 100755
--- a/arch/risc-v/src/mpfs/Make.defs
+++ b/arch/risc-v/src/mpfs/Make.defs
@@ -52,6 +52,7 @@ CMN_CSRCS += riscv_fpucmp.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/qemu-rv/Make.defs 
b/arch/risc-v/src/qemu-rv/Make.defs
index 0d4d701333..a222285990 100644
--- a/arch/risc-v/src/qemu-rv/Make.defs
+++ b/arch/risc-v/src/qemu-rv/Make.defs
@@ -51,6 +51,7 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 
diff --git a/arch/risc-v/src/rv32m1/Make.defs b/arch/risc-v/src/rv32m1/Make.defs
index f1dc2d0dea..3fcacd53f1 100644
--- a/arch/risc-v/src/rv32m1/Make.defs
+++ b/arch/risc-v/src/rv32m1/Make.defs
@@ -45,6 +45,7 @@ CMN_CSRCS += riscv_checkstack.c
 endif
 
 ifeq ($(CONFIG_ARCH_HAVE_VFORK),y)
+CMN_ASRCS += vfork.S
 CMN_CSRCS += riscv_vfork.c
 endif
 

Reply via email to