Skip to content

Commit 7ace160

Browse files
charlie-rivosKAGA-KOKO
authored andcommitted
LoongArch: entry: Migrate ret_from_fork() to C
LoongArch is the only architecture that calls syscall_exit_to_user_mode() from assembly. Move the call into C so that this function can be inlined across all architectures. Signed-off-by: Charlie Jenkins <charlie@rivosinc.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250320-riscv_optimize_entry-v6-3-63e187e26041@rivosinc.com
1 parent 5b3d610 commit 7ace160

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

arch/loongarch/include/asm/asm-prototypes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ __int128_t __ashlti3(__int128_t a, int b);
1212
__int128_t __ashrti3(__int128_t a, int b);
1313
__int128_t __lshrti3(__int128_t a, int b);
1414
#endif
15+
16+
asmlinkage void noinstr __no_stack_protector ret_from_fork(struct task_struct *prev,
17+
struct pt_regs *regs);
18+
19+
asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_struct *prev,
20+
struct pt_regs *regs,
21+
int (*fn)(void *),
22+
void *fn_arg);

arch/loongarch/kernel/entry.S

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,22 @@ SYM_CODE_START(handle_syscall)
7777
SYM_CODE_END(handle_syscall)
7878
_ASM_NOKPROBE(handle_syscall)
7979

80-
SYM_CODE_START(ret_from_fork)
80+
SYM_CODE_START(ret_from_fork_asm)
8181
UNWIND_HINT_REGS
82-
bl schedule_tail # a0 = struct task_struct *prev
83-
move a0, sp
84-
bl syscall_exit_to_user_mode
82+
move a1, sp
83+
bl ret_from_fork
8584
RESTORE_STATIC
8685
RESTORE_SOME
8786
RESTORE_SP_AND_RET
88-
SYM_CODE_END(ret_from_fork)
87+
SYM_CODE_END(ret_from_fork_asm)
8988

90-
SYM_CODE_START(ret_from_kernel_thread)
89+
SYM_CODE_START(ret_from_kernel_thread_asm)
9190
UNWIND_HINT_REGS
92-
bl schedule_tail # a0 = struct task_struct *prev
93-
move a0, s1
94-
jirl ra, s0, 0
95-
move a0, sp
96-
bl syscall_exit_to_user_mode
91+
move a1, sp
92+
move a2, s0
93+
move a3, s1
94+
bl ret_from_kernel_thread
9795
RESTORE_STATIC
9896
RESTORE_SOME
9997
RESTORE_SP_AND_RET
100-
SYM_CODE_END(ret_from_kernel_thread)
98+
SYM_CODE_END(ret_from_kernel_thread_asm)

arch/loongarch/kernel/process.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/init.h>
1515
#include <linux/kernel.h>
1616
#include <linux/errno.h>
17+
#include <linux/entry-common.h>
1718
#include <linux/sched.h>
1819
#include <linux/sched/debug.h>
1920
#include <linux/sched/task.h>
@@ -33,6 +34,7 @@
3334
#include <linux/prctl.h>
3435
#include <linux/nmi.h>
3536

37+
#include <asm/asm-prototypes.h>
3638
#include <asm/asm.h>
3739
#include <asm/bootinfo.h>
3840
#include <asm/cpu.h>
@@ -47,6 +49,7 @@
4749
#include <asm/pgtable.h>
4850
#include <asm/processor.h>
4951
#include <asm/reg.h>
52+
#include <asm/switch_to.h>
5053
#include <asm/unwind.h>
5154
#include <asm/vdso.h>
5255

@@ -63,8 +66,9 @@ EXPORT_SYMBOL(__stack_chk_guard);
6366
unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
6467
EXPORT_SYMBOL(boot_option_idle_override);
6568

66-
asmlinkage void ret_from_fork(void);
67-
asmlinkage void ret_from_kernel_thread(void);
69+
asmlinkage void restore_and_ret(void);
70+
asmlinkage void ret_from_fork_asm(void);
71+
asmlinkage void ret_from_kernel_thread_asm(void);
6872

6973
void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
7074
{
@@ -138,6 +142,23 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
138142
return 0;
139143
}
140144

145+
asmlinkage void noinstr __no_stack_protector ret_from_fork(struct task_struct *prev,
146+
struct pt_regs *regs)
147+
{
148+
schedule_tail(prev);
149+
syscall_exit_to_user_mode(regs);
150+
}
151+
152+
asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_struct *prev,
153+
struct pt_regs *regs,
154+
int (*fn)(void *),
155+
void *fn_arg)
156+
{
157+
schedule_tail(prev);
158+
fn(fn_arg);
159+
syscall_exit_to_user_mode(regs);
160+
}
161+
141162
/*
142163
* Copy architecture-specific thread state
143164
*/
@@ -165,8 +186,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
165186
p->thread.reg03 = childksp;
166187
p->thread.reg23 = (unsigned long)args->fn;
167188
p->thread.reg24 = (unsigned long)args->fn_arg;
168-
p->thread.reg01 = (unsigned long)ret_from_kernel_thread;
169-
p->thread.sched_ra = (unsigned long)ret_from_kernel_thread;
189+
p->thread.reg01 = (unsigned long)ret_from_kernel_thread_asm;
190+
p->thread.sched_ra = (unsigned long)ret_from_kernel_thread_asm;
170191
memset(childregs, 0, sizeof(struct pt_regs));
171192
childregs->csr_euen = p->thread.csr_euen;
172193
childregs->csr_crmd = p->thread.csr_crmd;
@@ -182,8 +203,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
182203
childregs->regs[3] = usp;
183204

184205
p->thread.reg03 = (unsigned long) childregs;
185-
p->thread.reg01 = (unsigned long) ret_from_fork;
186-
p->thread.sched_ra = (unsigned long) ret_from_fork;
206+
p->thread.reg01 = (unsigned long) ret_from_fork_asm;
207+
p->thread.sched_ra = (unsigned long) ret_from_fork_asm;
187208

188209
/*
189210
* New tasks lose permission to use the fpu. This accelerates context

0 commit comments

Comments
 (0)