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