summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/entry_64.S
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-09-10 20:44:54 (GMT)
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-01 02:53:31 (GMT)
commit7076aada1040de4ed79a5977dbabdb5e5ea5e249 (patch)
treedfcf480d21cd714a1cc42f38417c427d06526f5a /arch/x86/kernel/entry_64.S
parent44f4b56b54d2ab5d06c1726f2cde8ca15c8fac47 (diff)
downloadlinux-7076aada1040de4ed79a5977dbabdb5e5ea5e249.tar.xz
x86: split ret_from_fork
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r--arch/x86/kernel/entry_64.S27
1 files changed, 11 insertions, 16 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 69babd8..5526d17 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -450,7 +450,7 @@ ENTRY(ret_from_fork)
RESTORE_REST
testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
- jz retint_restore_args
+ jz 1f
testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
jnz int_ret_from_sys_call
@@ -458,6 +458,16 @@ ENTRY(ret_from_fork)
RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
jmp ret_from_sys_call # go to the SYSRET fastpath
+1:
+ subq $REST_SKIP, %rsp # move the stack pointer back
+ CFI_ADJUST_CFA_OFFSET REST_SKIP
+ movq %rbp, %rdi
+ call *%rbx
+ # exit
+ mov %eax, %edi
+ call do_exit
+ ud2 # padding for call trace
+
CFI_ENDPROC
END(ret_from_fork)
@@ -1206,21 +1216,6 @@ bad_gs:
jmp 2b
.previous
-ENTRY(kernel_thread_helper)
- pushq $0 # fake return address
- CFI_STARTPROC
- /*
- * Here we are in the child and the registers are set as they were
- * at kernel_thread() invocation in the parent.
- */
- call *%rsi
- # exit
- mov %eax, %edi
- call do_exit
- ud2 # padding for call trace
- CFI_ENDPROC
-END(kernel_thread_helper)
-
/*
* execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
*