diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h index fb16b84b17799..cd2665cd88631 100644 --- a/arch/risc-v/include/irq.h +++ b/arch/risc-v/include/irq.h @@ -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) diff --git a/arch/risc-v/src/common/riscv_fork.c b/arch/risc-v/src/common/riscv_fork.c index 896d8d46c41c5..76a784a4f5929 100644 --- a/arch/risc-v/src/common/riscv_fork.c +++ b/arch/risc-v/src/common/riscv_fork.c @@ -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"); @@ -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 */ @@ -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(). */ diff --git a/arch/risc-v/src/common/riscv_swint.c b/arch/risc-v/src/common/riscv_swint.c index 4cf68ac0aa9c7..cfe5838102316 100644 --- a/arch/risc-v/src/common/riscv_swint.c +++ b/arch/risc-v/src/common/riscv_swint.c @@ -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 */