mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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
This commit is contained in:
parent
5b3d6103b3
commit
7ace1602ab
3 changed files with 45 additions and 18 deletions
|
@ -12,3 +12,11 @@ __int128_t __ashlti3(__int128_t a, int b);
|
||||||
__int128_t __ashrti3(__int128_t a, int b);
|
__int128_t __ashrti3(__int128_t a, int b);
|
||||||
__int128_t __lshrti3(__int128_t a, int b);
|
__int128_t __lshrti3(__int128_t a, int b);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
asmlinkage void noinstr __no_stack_protector ret_from_fork(struct task_struct *prev,
|
||||||
|
struct pt_regs *regs);
|
||||||
|
|
||||||
|
asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_struct *prev,
|
||||||
|
struct pt_regs *regs,
|
||||||
|
int (*fn)(void *),
|
||||||
|
void *fn_arg);
|
||||||
|
|
|
@ -77,24 +77,22 @@ SYM_CODE_START(handle_syscall)
|
||||||
SYM_CODE_END(handle_syscall)
|
SYM_CODE_END(handle_syscall)
|
||||||
_ASM_NOKPROBE(handle_syscall)
|
_ASM_NOKPROBE(handle_syscall)
|
||||||
|
|
||||||
SYM_CODE_START(ret_from_fork)
|
SYM_CODE_START(ret_from_fork_asm)
|
||||||
UNWIND_HINT_REGS
|
UNWIND_HINT_REGS
|
||||||
bl schedule_tail # a0 = struct task_struct *prev
|
move a1, sp
|
||||||
move a0, sp
|
bl ret_from_fork
|
||||||
bl syscall_exit_to_user_mode
|
|
||||||
RESTORE_STATIC
|
RESTORE_STATIC
|
||||||
RESTORE_SOME
|
RESTORE_SOME
|
||||||
RESTORE_SP_AND_RET
|
RESTORE_SP_AND_RET
|
||||||
SYM_CODE_END(ret_from_fork)
|
SYM_CODE_END(ret_from_fork_asm)
|
||||||
|
|
||||||
SYM_CODE_START(ret_from_kernel_thread)
|
SYM_CODE_START(ret_from_kernel_thread_asm)
|
||||||
UNWIND_HINT_REGS
|
UNWIND_HINT_REGS
|
||||||
bl schedule_tail # a0 = struct task_struct *prev
|
move a1, sp
|
||||||
move a0, s1
|
move a2, s0
|
||||||
jirl ra, s0, 0
|
move a3, s1
|
||||||
move a0, sp
|
bl ret_from_kernel_thread
|
||||||
bl syscall_exit_to_user_mode
|
|
||||||
RESTORE_STATIC
|
RESTORE_STATIC
|
||||||
RESTORE_SOME
|
RESTORE_SOME
|
||||||
RESTORE_SP_AND_RET
|
RESTORE_SP_AND_RET
|
||||||
SYM_CODE_END(ret_from_kernel_thread)
|
SYM_CODE_END(ret_from_kernel_thread_asm)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/entry-common.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/sched/debug.h>
|
#include <linux/sched/debug.h>
|
||||||
#include <linux/sched/task.h>
|
#include <linux/sched/task.h>
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
#include <linux/prctl.h>
|
#include <linux/prctl.h>
|
||||||
#include <linux/nmi.h>
|
#include <linux/nmi.h>
|
||||||
|
|
||||||
|
#include <asm/asm-prototypes.h>
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
@ -47,6 +49,7 @@
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/reg.h>
|
#include <asm/reg.h>
|
||||||
|
#include <asm/switch_to.h>
|
||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/vdso.h>
|
#include <asm/vdso.h>
|
||||||
|
|
||||||
|
@ -63,8 +66,9 @@ EXPORT_SYMBOL(__stack_chk_guard);
|
||||||
unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
|
unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
|
||||||
EXPORT_SYMBOL(boot_option_idle_override);
|
EXPORT_SYMBOL(boot_option_idle_override);
|
||||||
|
|
||||||
asmlinkage void ret_from_fork(void);
|
asmlinkage void restore_and_ret(void);
|
||||||
asmlinkage void ret_from_kernel_thread(void);
|
asmlinkage void ret_from_fork_asm(void);
|
||||||
|
asmlinkage void ret_from_kernel_thread_asm(void);
|
||||||
|
|
||||||
void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
|
void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
|
||||||
{
|
{
|
||||||
|
@ -138,6 +142,23 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asmlinkage void noinstr __no_stack_protector ret_from_fork(struct task_struct *prev,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
schedule_tail(prev);
|
||||||
|
syscall_exit_to_user_mode(regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_struct *prev,
|
||||||
|
struct pt_regs *regs,
|
||||||
|
int (*fn)(void *),
|
||||||
|
void *fn_arg)
|
||||||
|
{
|
||||||
|
schedule_tail(prev);
|
||||||
|
fn(fn_arg);
|
||||||
|
syscall_exit_to_user_mode(regs);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy architecture-specific thread state
|
* Copy architecture-specific thread state
|
||||||
*/
|
*/
|
||||||
|
@ -165,8 +186,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
|
||||||
p->thread.reg03 = childksp;
|
p->thread.reg03 = childksp;
|
||||||
p->thread.reg23 = (unsigned long)args->fn;
|
p->thread.reg23 = (unsigned long)args->fn;
|
||||||
p->thread.reg24 = (unsigned long)args->fn_arg;
|
p->thread.reg24 = (unsigned long)args->fn_arg;
|
||||||
p->thread.reg01 = (unsigned long)ret_from_kernel_thread;
|
p->thread.reg01 = (unsigned long)ret_from_kernel_thread_asm;
|
||||||
p->thread.sched_ra = (unsigned long)ret_from_kernel_thread;
|
p->thread.sched_ra = (unsigned long)ret_from_kernel_thread_asm;
|
||||||
memset(childregs, 0, sizeof(struct pt_regs));
|
memset(childregs, 0, sizeof(struct pt_regs));
|
||||||
childregs->csr_euen = p->thread.csr_euen;
|
childregs->csr_euen = p->thread.csr_euen;
|
||||||
childregs->csr_crmd = p->thread.csr_crmd;
|
childregs->csr_crmd = p->thread.csr_crmd;
|
||||||
|
@ -182,8 +203,8 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
|
||||||
childregs->regs[3] = usp;
|
childregs->regs[3] = usp;
|
||||||
|
|
||||||
p->thread.reg03 = (unsigned long) childregs;
|
p->thread.reg03 = (unsigned long) childregs;
|
||||||
p->thread.reg01 = (unsigned long) ret_from_fork;
|
p->thread.reg01 = (unsigned long) ret_from_fork_asm;
|
||||||
p->thread.sched_ra = (unsigned long) ret_from_fork;
|
p->thread.sched_ra = (unsigned long) ret_from_fork_asm;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* New tasks lose permission to use the fpu. This accelerates context
|
* New tasks lose permission to use the fpu. This accelerates context
|
||||||
|
|
Loading…
Add table
Reference in a new issue