diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.c b/components/lwp/arch/risc-v/rv64/lwp_arch.c index 62383f91fa9..ceb206e8c28 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_arch.c +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.c @@ -258,7 +258,42 @@ struct signal_ucontext struct rt_hw_stack_frame frame; }; -void *arch_signal_ucontext_restore(rt_base_t user_sp) +void arch_syscall_restart(void *sp, void *ksp); + +void arch_signal_check_erestart(void *eframe, void *ksp) +{ + struct rt_hw_stack_frame *exp_frame = eframe; + long rc = exp_frame->a0; + long sys_id = exp_frame->a7; + + (void)sys_id; + + if (rc == -ERESTART) + { + LOG_D("%s(rc=%ld,sys_id=%ld,pid=%d)", __func__, rc, sys_id, lwp_self()->pid); + LOG_D("%s: restart rc = %ld", lwp_get_syscall_name(sys_id), rc); + + /* t0 stores the copy of user's first syscall argument */ + exp_frame->a0 = exp_frame->t0; + /* adjust for epc auto-increment in syscall_handler */ + exp_frame->epc -= 4; + /* copy exception frame from user stack to kernel stack */ + lwp_memcpy(ksp - sizeof(*eframe), eframe, sizeof(*eframe)); + + arch_syscall_restart(eframe, ksp); + } + + return ; +} + +static void arch_signal_post_action(struct signal_ucontext *new_sp, rt_base_t kernel_sp) +{ + arch_signal_check_erestart(&new_sp->frame, (void *)kernel_sp); + + return ; +} + +void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp) { struct signal_ucontext *new_sp; new_sp = (void *)user_sp; @@ -266,6 +301,7 @@ void *arch_signal_ucontext_restore(rt_base_t user_sp) if (lwp_user_accessable(new_sp, sizeof(*new_sp))) { lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL); + arch_signal_post_action(new_sp, kernel_sp); } else { @@ -320,7 +356,13 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo, void arch_syscall_set_errno(void *eframe, int expected, int code) { - /* NO support */ + struct rt_hw_stack_frame *exp_frame = eframe; + + if (exp_frame->a0 == -expected) + { + exp_frame->a0 = -code; + } + return ; } @@ -354,4 +396,4 @@ int arch_backtrace_uthread(rt_thread_t thread) return -1; } return -1; -} +} \ No newline at end of file diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.h b/components/lwp/arch/risc-v/rv64/lwp_arch.h index f1d1176f5cb..df06f19c937 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_arch.h +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.h @@ -69,7 +69,7 @@ rt_inline void icache_invalid_all(void) } struct rt_hw_stack_frame; -void *arch_signal_ucontext_restore(rt_base_t user_sp); +void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp); void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo, struct rt_hw_stack_frame *exp_frame, rt_base_t user_sp, lwp_sigset_t *save_sig_mask); @@ -79,4 +79,4 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo, #endif -#endif /*LWP_ARCH_H__*/ +#endif /*LWP_ARCH_H__*/ \ No newline at end of file diff --git a/components/lwp/arch/risc-v/rv64/lwp_gcc.S b/components/lwp/arch/risc-v/rv64/lwp_gcc.S index c207285c6fa..268d3bb23a3 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_gcc.S +++ b/components/lwp/arch/risc-v/rv64/lwp_gcc.S @@ -98,12 +98,28 @@ ret_to_user_exit: // `RESTORE_ALL` also reset sp to user sp, and setup sscratch sret +/* + * void void arch_syscall_restart(void *sp, void *ksp); + */ +.global arch_syscall_restart +arch_syscall_restart: + addi a1, a1, -CTX_REG_NR * REGBYTES + + /* set stack pointer to saved user exception frame on kernel stack */ + mv sp, a1 + + /* restore all user registers, and setup sscratch to point to ksp */ + RESTORE_ALL + + j trap_entry + /** * Restore user context from exception frame stroraged in ustack * And handle pending signals; */ arch_signal_quit: LOAD a0, FRAME_OFF_SP(sp) + addi a1, sp, CTX_REG_NR * REGBYTES call arch_signal_ucontext_restore /* reset kernel sp to the stack */ diff --git a/libcpu/risc-v/common64/syscall_c.c b/libcpu/risc-v/common64/syscall_c.c index ceffd94dbcd..128c481b5de 100644 --- a/libcpu/risc-v/common64/syscall_c.c +++ b/libcpu/risc-v/common64/syscall_c.c @@ -54,9 +54,13 @@ void syscall_handler(struct rt_hw_stack_frame *regs) LOG_I("[0x%lx] %s(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)", rt_thread_self(), syscall_name, regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5, regs->a6); + /* Save original a0 (1st argument) in kernel-stored t0 context: + * - a0 serves as both system call's 1st argument (input) and return value (output) + * - t0 is caller-saved, user code must preserve it before ecall if needed + */ + regs->t0 = regs->a0; regs->a0 = syscallfunc(regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5, regs->a6); - regs->a7 = 0; regs->epc += 4; // skip ecall instruction LOG_I("[0x%lx] %s ret: 0x%lx", rt_thread_self(), syscall_name, regs->a0); } -#endif /* RT_USING_SMART */ +#endif /* RT_USING_SMART */ \ No newline at end of file