Skip to content

Commit 7f4d270

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

File tree

4 files changed

+65
-5
lines changed

4 files changed

+65
-5
lines changed

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

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
1818
* 2023-10-16 Shell Support a new backtrace framework
1919
*/
20+
2021
#include <rthw.h>
2122
#include <rtthread.h>
2223

@@ -258,14 +259,50 @@ struct signal_ucontext
258259
struct rt_hw_stack_frame frame;
259260
};
260261

261-
void *arch_signal_ucontext_restore(rt_base_t user_sp)
262+
void arch_syscall_restart(void *sp, void *ksp);
263+
264+
void arch_signal_check_erestart(void *eframe, void *ksp)
265+
{
266+
struct rt_hw_stack_frame *exp_frame = eframe;
267+
long rc = exp_frame->a0;
268+
long sys_id = exp_frame->a7;
269+
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+
/* adjust for epc auto-increment in syscall_handler */
280+
exp_frame->epc -= 4;
281+
/* copy exception frame from user stack to kernel stack */
282+
lwp_memcpy(ksp - sizeof(*eframe), eframe, sizeof(*eframe));
283+
284+
arch_syscall_restart(eframe, ksp);
285+
}
286+
287+
return ;
288+
}
289+
290+
static void arch_signal_post_action(struct signal_ucontext *new_sp, rt_base_t kernel_sp)
291+
{
292+
arch_signal_check_erestart(&new_sp->frame, (void *)kernel_sp);
293+
294+
return ;
295+
}
296+
297+
void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp)
262298
{
263299
struct signal_ucontext *new_sp;
264300
new_sp = (void *)user_sp;
265301

266302
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
267303
{
268304
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
305+
arch_signal_post_action(new_sp, kernel_sp);
269306
}
270307
else
271308
{
@@ -320,7 +357,13 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
320357

321358
void arch_syscall_set_errno(void *eframe, int expected, int code)
322359
{
323-
/* NO support */
360+
struct rt_hw_stack_frame *exp_frame = eframe;
361+
362+
if (exp_frame->a0 == -expected)
363+
{
364+
exp_frame->a0 = -code;
365+
}
366+
324367
return ;
325368
}
326369

@@ -355,3 +398,4 @@ int arch_backtrace_uthread(rt_thread_t thread)
355398
}
356399
return -1;
357400
}
401+

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ rt_inline void icache_invalid_all(void)
6969
}
7070

7171
struct rt_hw_stack_frame;
72-
void *arch_signal_ucontext_restore(rt_base_t user_sp);
72+
void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp);
7373
void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
7474
struct rt_hw_stack_frame *exp_frame, rt_base_t user_sp,
7575
lwp_sigset_t *save_sig_mask);
@@ -79,4 +79,4 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
7979

8080
#endif
8181

82-
#endif /*LWP_ARCH_H__*/
82+
#endif /*LWP_ARCH_H__*/

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

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

101+
/*
102+
* void void arch_syscall_restart(void *sp, void *ksp);
103+
*/
104+
.global arch_syscall_restart
105+
arch_syscall_restart:
106+
addi a1, a1, -CTX_REG_NR * REGBYTES
107+
108+
/* set stack pointer to saved user exception frame on kernel stack */
109+
mv sp, a1
110+
111+
/* restore all user registers, and setup sscratch to point to ksp */
112+
RESTORE_ALL
113+
114+
j trap_entry
115+
101116
/**
102117
* Restore user context from exception frame stroraged in ustack
103118
* And handle pending signals;
104119
*/
105120
arch_signal_quit:
106121
LOAD a0, FRAME_OFF_SP(sp)
122+
addi a1, sp, CTX_REG_NR * REGBYTES
107123
call arch_signal_ucontext_restore
108124

109125
/* reset kernel sp to the stack */

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)