Skip to content

Commit d02aaac

Browse files
committed
signal: add support for restartable system calls on RISC-V64
1 parent 2d75100 commit d02aaac

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

components/lwp/arch/risc-v/rv64/lwp_arch.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006-2021, RT-Thread Development Team
2+
* Copyright (c) 2006-2025, RT-Thread Development Team
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -258,6 +258,41 @@ struct signal_ucontext
258258
struct rt_hw_stack_frame frame;
259259
};
260260

261+
void arch_syscall_restart(void *sp);
262+
263+
void arch_signal_check_erestart(void *eframe, void *ksp)
264+
{
265+
struct rt_hw_stack_frame *exp_frame = eframe;
266+
long rc = exp_frame->a0;
267+
long sys_id = exp_frame->a7;
268+
269+
(void)ksp;
270+
(void)sys_id;
271+
272+
if (rc == -ERESTART)
273+
{
274+
LOG_D("%s(rc=%ld,sys_id=%ld,pid=%d)", __func__, rc, sys_id, lwp_self()->pid);
275+
LOG_D("%s: restart rc = %ld", lwp_get_syscall_name(sys_id), rc);
276+
277+
/* t0 stores the copy of user's first syscall argument */
278+
exp_frame->a0 = exp_frame->t0;
279+
280+
/* adjust for epc auto-increment in syscall_handler */
281+
exp_frame->epc -= 4;
282+
283+
arch_syscall_restart(eframe);
284+
}
285+
286+
return ;
287+
}
288+
289+
static void arch_signal_post_action(struct signal_ucontext *new_sp)
290+
{
291+
arch_signal_check_erestart(&new_sp->frame,0);
292+
293+
return ;
294+
}
295+
261296
void *arch_signal_ucontext_restore(rt_base_t user_sp)
262297
{
263298
struct signal_ucontext *new_sp;
@@ -266,6 +301,7 @@ void *arch_signal_ucontext_restore(rt_base_t user_sp)
266301
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
267302
{
268303
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
304+
arch_signal_post_action(new_sp);
269305
}
270306
else
271307
{
@@ -320,7 +356,13 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
320356

321357
void arch_syscall_set_errno(void *eframe, int expected, int code)
322358
{
323-
/* NO support */
359+
struct rt_hw_stack_frame *exp_frame = eframe;
360+
361+
if (exp_frame->a0 == -expected)
362+
{
363+
exp_frame->a0 = -code;
364+
}
365+
324366
return ;
325367
}
326368

@@ -355,3 +397,4 @@ int arch_backtrace_uthread(rt_thread_t thread)
355397
}
356398
return -1;
357399
}
400+

components/lwp/arch/risc-v/rv64/lwp_gcc.S

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,25 @@ ret_to_user_exit:
9898
// `RESTORE_ALL` also reset sp to user sp, and setup sscratch
9999
sret
100100

101+
.global arch_syscall_restart
102+
arch_syscall_restart:
103+
/* discard kernel context by moving stack pointer */
104+
addi sp, sp, CTX_REG_NR * REGBYTES
105+
106+
/* store kernel stack pointer in exception frame (a0 points to frame) */
107+
STORE sp, FRAME_OFF_SP(a0)
108+
109+
/* switch to user exception frame */
110+
mv sp, a0
111+
112+
/* restore all user registers from exception frame (except sp) */
113+
RESTORE_ALL
114+
115+
/* exchange sp and sscratch */
116+
csrrw sp, sscratch, sp
117+
118+
j trap_entry
119+
101120
/**
102121
* Restore user context from exception frame stroraged in ustack
103122
* And handle pending signals;

libcpu/risc-v/common64/syscall_c.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ void syscall_handler(struct rt_hw_stack_frame *regs)
5454

5555
LOG_I("[0x%lx] %s(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)", rt_thread_self(), syscall_name,
5656
regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5, regs->a6);
57+
regs->t0 = regs->a0;
5758
regs->a0 = syscallfunc(regs->a0, regs->a1, regs->a2, regs->a3, regs->a4, regs->a5, regs->a6);
58-
regs->a7 = 0;
5959
regs->epc += 4; // skip ecall instruction
6060
LOG_I("[0x%lx] %s ret: 0x%lx", rt_thread_self(), syscall_name, regs->a0);
6161
}

0 commit comments

Comments
 (0)