diff --git a/arch/loongarch/kernel/entry.S b/arch/loongarch/kernel/entry.S index 893e632e76dab963fb4160174425fc3be1082e40..8670e9d128ab25b91089a6c4645c25435b73d546 100644 --- a/arch/loongarch/kernel/entry.S +++ b/arch/loongarch/kernel/entry.S @@ -14,13 +14,14 @@ #include #include #include +#include .text .cfi_sections .debug_frame .align 5 SYM_FUNC_START(handle_syscall) csrrd t0, PERCPU_BASE_KS - la.abs t1, kernelsp + la.pcrel t1, kernelsp add.d t1, t1, t0 move t2, sp ld.d sp, t1, 0 @@ -28,11 +29,10 @@ SYM_FUNC_START(handle_syscall) addi.d sp, sp, -PT_SIZE cfi_st t2, PT_R3 cfi_rel_offset sp, PT_R3 - st.d zero, sp, PT_R0 csrrd t2, LOONGARCH_CSR_PRMD st.d t2, sp, PT_PRMD cfi_st ra, PT_R1 - cfi_st a0, PT_R4 + cfi_st a0, PT_ORIG_A0 cfi_st a1, PT_R5 cfi_st a2, PT_R6 cfi_st a3, PT_R7 @@ -41,6 +41,7 @@ SYM_FUNC_START(handle_syscall) cfi_st a6, PT_R10 cfi_st a7, PT_R11 csrrd ra, LOONGARCH_CSR_ERA + addi.d ra, ra, 4 st.d ra, sp, PT_ERA cfi_rel_offset ra, PT_ERA @@ -55,9 +56,17 @@ SYM_FUNC_START(handle_syscall) and tp, tp, sp move a0, sp + move a1, a7 bl do_syscall - RESTORE_ALL_AND_RET + addi.w t0, zero, __NR_rt_sigreturn + bne a0, t0, 1f + + RESTORE_STATIC + RESTORE_TEMP +1: + RESTORE_SOME + RESTORE_SP_AND_RET SYM_FUNC_END(handle_syscall) SYM_CODE_START(ret_from_fork) diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 3fc4211db9895f71bc356b075fbb79f6779bbbe6..796fcdcaa6a7cfd183a949d5906695e1fa2c76dc 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -37,18 +37,16 @@ void *sys_call_table[__NR_syscalls] = { typedef long (*sys_call_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); -void noinstr do_syscall(struct pt_regs *regs) +unsigned long noinstr do_syscall(struct pt_regs *regs, unsigned long nr) { - unsigned long nr; sys_call_fn syscall_fn; - nr = regs->regs[11]; /* Set for syscall restarting */ if (nr < NR_syscalls) regs->regs[0] = nr + 1; + else + regs->regs[0] = 0; - regs->csr_era += 4; - regs->orig_a0 = regs->regs[4]; regs->regs[4] = -ENOSYS; nr = syscall_enter_from_user_mode(regs, nr); @@ -60,4 +58,6 @@ void noinstr do_syscall(struct pt_regs *regs) } syscall_exit_to_user_mode(regs); + + return nr; }