ret_from_fork is a mix of assembly code and calls to C functions.
Re-implement ret_from_fork so that it calls a single C function.

Signed-off-by: Alexandre Chartre <alexandre.char...@oracle.com>
---
 arch/x86/entry/common.c   | 18 ++++++++++++++++++
 arch/x86/entry/entry_64.S | 28 +++++-----------------------
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index d222212908ad..7ee15a12c115 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -35,6 +35,24 @@
 #include <asm/syscall.h>
 #include <asm/irq_stack.h>
 
+__visible noinstr void return_from_fork(struct pt_regs *regs,
+                                       struct task_struct *prev,
+                                       void (*kfunc)(void *), void *kargs)
+{
+       schedule_tail(prev);
+       if (kfunc) {
+               /* kernel thread */
+               kfunc(kargs);
+               /*
+                * A kernel thread is allowed to return here after
+                * successfully calling kernel_execve(). Exit to
+                * userspace to complete the execve() syscall.
+                */
+               regs->ax = 0;
+       }
+       syscall_exit_to_user_mode(regs);
+}
+
 static __always_inline void run_syscall(sys_call_ptr_t sysfunc,
                                        struct pt_regs *regs)
 {
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 274384644b5e..73e9cd47dc83 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -276,31 +276,13 @@ SYM_FUNC_END(__switch_to_asm)
  */
 .pushsection .text, "ax"
 SYM_CODE_START(ret_from_fork)
-       UNWIND_HINT_EMPTY
-       movq    %rax, %rdi
-       call    schedule_tail                   /* rdi: 'prev' task parameter */
-
-       testq   %rbx, %rbx                      /* from kernel_thread? */
-       jnz     1f                              /* kernel threads are uncommon 
*/
-
-2:
        UNWIND_HINT_REGS
-       movq    %rsp, %rdi
-       call    syscall_exit_to_user_mode       /* returns with IRQs disabled */
+       movq    %rsp, %rdi                      /* pt_regs */
+       movq    %rax, %rsi                      /* 'prev' task parameter */
+       movq    %rbx, %rdx                      /* kernel thread func */
+       movq    %r12, %rcx                      /* kernel thread arg */
+       call    return_from_fork                /* returns with IRQs disabled */
        jmp     swapgs_restore_regs_and_return_to_usermode
-
-1:
-       /* kernel thread */
-       UNWIND_HINT_EMPTY
-       movq    %r12, %rdi
-       CALL_NOSPEC rbx
-       /*
-        * A kernel thread is allowed to return here after successfully
-        * calling kernel_execve().  Exit to userspace to complete the execve()
-        * syscall.
-        */
-       movq    $0, RAX(%rsp)
-       jmp     2b
 SYM_CODE_END(ret_from_fork)
 .popsection
 
-- 
2.18.4

Reply via email to