RISC-V: Add implementation for vfork
This commit is contained in:
parent
2580520828
commit
a014daf44f
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) */
|
||||
|
130
arch/risc-v/src/common/vfork.S
Normal file
130
arch/risc-v/src/common/vfork.S
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user