Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions arch/risc-v/include/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,12 @@ struct xcptcontext

uintreg_t *regs;

#ifdef CONFIG_LIB_SYSCALL
/* User integer registers upon system call entry */

uintreg_t *sregs;
#endif

/* FPU register save area */

#if defined(CONFIG_ARCH_FPU) && defined(CONFIG_ARCH_LAZYFPU)
Expand Down
47 changes: 27 additions & 20 deletions arch/risc-v/src/common/riscv_fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,14 @@ pid_t riscv_fork(const struct fork_s *context)
uintptr_t newtop;
uintptr_t stacktop;
uintptr_t stackutil;
irqstate_t flags;
#ifdef CONFIG_SCHED_THREAD_LOCAL
uintptr_t tp;
#endif
UNUSED(context);

/* parent regs may change in irq, we should disable irq here */

flags = up_irq_save();

/* Allocate and initialize a TCB for the child task. */

child = nxtask_setup_fork((start_t)parent->xcp.regs[REG_RA]);
child = nxtask_setup_fork((start_t)parent->xcp.sregs[REG_RA]);
if (!child)
{
sinfo("nxtask_setup_fork failed\n");
Expand All @@ -130,36 +125,50 @@ pid_t riscv_fork(const struct fork_s *context)
/* Copy parent user stack to child */

stacktop = (uintptr_t)parent->stack_base_ptr + parent->adj_stack_size;
DEBUGASSERT(stacktop > parent->xcp.regs[REG_SP]);
stackutil = stacktop - parent->xcp.regs[REG_SP];
DEBUGASSERT(stacktop > parent->xcp.sregs[REG_SP]);
stackutil = stacktop - parent->xcp.sregs[REG_SP];

/* Copy the parent stack contents (overwrites child's SP and TP) */
/* Copy goes to child's user stack top */

newtop = (uintptr_t)child->cmn.stack_base_ptr + child->cmn.adj_stack_size;
newsp = newtop - stackutil;

memcpy((void *)newsp, (const void *)parent->xcp.sregs[REG_SP], stackutil);

#ifdef CONFIG_SCHED_THREAD_LOCAL
/* Save child's thread pointer */

tp = child->cmn.xcp.regs[REG_TP];
#endif

/* Set up frame for context and copy the parent's user context there */
/* Determine the integer context save area */

memcpy((void *)(newsp - XCPTCONTEXT_SIZE),
parent->xcp.regs, XCPTCONTEXT_SIZE);
#ifdef CONFIG_ARCH_KERNEL_STACK
if (child->cmn.xcp.kstack)
{
/* Set context to kernel stack */

/* Save FPU */
stacktop = (uintptr_t)child->cmn.xcp.ktopstk;
}
else
#endif
{
/* Set context to user stack */

riscv_savefpu(child->cmn.xcp.regs, riscv_fpuregs(&child->cmn));
stacktop = newsp;
}

/* Copy the parent stack contents */
/* Set the new register restore area to the new stack top */

memcpy((void *)newsp, (const void *)parent->xcp.regs[REG_SP], stackutil);
child->cmn.xcp.regs = (void *)(stacktop - XCPTCONTEXT_SIZE);

/* Set the new register restore area to the new stack top */
/* Copy the parent integer context (overwrites child's SP and TP) */

child->cmn.xcp.regs = (void *)(newsp - XCPTCONTEXT_SIZE);
memcpy(child->cmn.xcp.regs, parent->xcp.sregs, XCPTCONTEXT_SIZE);

/* Save FPU */

riscv_savefpu(child->cmn.xcp.regs, riscv_fpuregs(&child->cmn));

/* Return 0 to child */

Expand All @@ -169,8 +178,6 @@ pid_t riscv_fork(const struct fork_s *context)
child->cmn.xcp.regs[REG_TP] = tp;
#endif

up_irq_restore(flags);

/* And, finally, start the child task. On a failure, nxtask_start_fork()
* will discard the TCB by calling nxtask_abort_fork().
*/
Expand Down
2 changes: 1 addition & 1 deletion arch/risc-v/src/common/riscv_swint.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ uintptr_t dispatch_syscall(unsigned int nbr, uintptr_t parm1,

/* Set the user register context to TCB */

rtcb->xcp.regs = context;
rtcb->xcp.sregs = context;

/* Indicate that we are in a syscall handler */

Expand Down