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>
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>
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);
6366unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE ;
6467EXPORT_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
6973void 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