aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/entry_64.S
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 23:02:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 23:02:25 -0400
commit42859eea96ba6beabfb0369a1eeffa3c7d2bd9cb (patch)
treefa38aeda0d6e7a4c48a882b166b8643594a1ad50 /arch/x86/kernel/entry_64.S
parentf59b51fe3d3092c08d7d554ecb40db24011b2ebc (diff)
parentf322220d6159455da2b5a8a596d802c8695fed30 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull generic execve() changes from Al Viro: "This introduces the generic kernel_thread() and kernel_execve() functions, and switches x86, arm, alpha, um and s390 over to them." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (26 commits) s390: convert to generic kernel_execve() s390: switch to generic kernel_thread() s390: fold kernel_thread_helper() into ret_from_fork() s390: fold execve_tail() into start_thread(), convert to generic sys_execve() um: switch to generic kernel_thread() x86, um/x86: switch to generic sys_execve and kernel_execve x86: split ret_from_fork alpha: introduce ret_from_kernel_execve(), switch to generic kernel_execve() alpha: switch to generic kernel_thread() alpha: switch to generic sys_execve() arm: get rid of execve wrapper, switch to generic execve() implementation arm: optimized current_pt_regs() arm: introduce ret_from_kernel_execve(), switch to generic kernel_execve() arm: split ret_from_fork, simplify kernel_thread() [based on patch by rmk] generic sys_execve() generic kernel_execve() new helper: current_pt_regs() preparation for generic kernel_thread() um: kill thread->forking um: let signal_delivered() do SIGTRAP on singlestepping into handler ...
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r--arch/x86/kernel/entry_64.S74
1 files changed, 25 insertions, 49 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 44531acd9a81..cdc790c78f32 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -554,7 +554,7 @@ ENTRY(ret_from_fork)
554 RESTORE_REST 554 RESTORE_REST
555 555
556 testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? 556 testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?
557 jz retint_restore_args 557 jz 1f
558 558
559 testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET 559 testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET
560 jnz int_ret_from_sys_call 560 jnz int_ret_from_sys_call
@@ -562,6 +562,16 @@ ENTRY(ret_from_fork)
562 RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET 562 RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
563 jmp ret_from_sys_call # go to the SYSRET fastpath 563 jmp ret_from_sys_call # go to the SYSRET fastpath
564 564
5651:
566 subq $REST_SKIP, %rsp # move the stack pointer back
567 CFI_ADJUST_CFA_OFFSET REST_SKIP
568 movq %rbp, %rdi
569 call *%rbx
570 # exit
571 mov %eax, %edi
572 call do_exit
573 ud2 # padding for call trace
574
565 CFI_ENDPROC 575 CFI_ENDPROC
566END(ret_from_fork) 576END(ret_from_fork)
567 577
@@ -862,7 +872,6 @@ ENTRY(stub_execve)
862 PARTIAL_FRAME 0 872 PARTIAL_FRAME 0
863 SAVE_REST 873 SAVE_REST
864 FIXUP_TOP_OF_STACK %r11 874 FIXUP_TOP_OF_STACK %r11
865 movq %rsp, %rcx
866 call sys_execve 875 call sys_execve
867 RESTORE_TOP_OF_STACK %r11 876 RESTORE_TOP_OF_STACK %r11
868 movq %rax,RAX(%rsp) 877 movq %rax,RAX(%rsp)
@@ -912,8 +921,7 @@ ENTRY(stub_x32_execve)
912 PARTIAL_FRAME 0 921 PARTIAL_FRAME 0
913 SAVE_REST 922 SAVE_REST
914 FIXUP_TOP_OF_STACK %r11 923 FIXUP_TOP_OF_STACK %r11
915 movq %rsp, %rcx 924 call compat_sys_execve
916 call sys32_execve
917 RESTORE_TOP_OF_STACK %r11 925 RESTORE_TOP_OF_STACK %r11
918 movq %rax,RAX(%rsp) 926 movq %rax,RAX(%rsp)
919 RESTORE_REST 927 RESTORE_REST
@@ -1318,51 +1326,19 @@ bad_gs:
1318 jmp 2b 1326 jmp 2b
1319 .previous 1327 .previous
1320 1328
1321ENTRY(kernel_thread_helper) 1329ENTRY(ret_from_kernel_execve)
1322 pushq $0 # fake return address 1330 movq %rdi, %rsp
1323 CFI_STARTPROC 1331 movl $0, RAX(%rsp)
1324 /* 1332 // RESTORE_REST
1325 * Here we are in the child and the registers are set as they were 1333 movq 0*8(%rsp), %r15
1326 * at kernel_thread() invocation in the parent. 1334 movq 1*8(%rsp), %r14
1327 */ 1335 movq 2*8(%rsp), %r13
1328 call *%rsi 1336 movq 3*8(%rsp), %r12
1329 # exit 1337 movq 4*8(%rsp), %rbp
1330 mov %eax, %edi 1338 movq 5*8(%rsp), %rbx
1331 call do_exit 1339 addq $(6*8), %rsp
1332 ud2 # padding for call trace 1340 jmp int_ret_from_sys_call
1333 CFI_ENDPROC 1341END(ret_from_kernel_execve)
1334END(kernel_thread_helper)
1335
1336/*
1337 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
1338 *
1339 * C extern interface:
1340 * extern long execve(const char *name, char **argv, char **envp)
1341 *
1342 * asm input arguments:
1343 * rdi: name, rsi: argv, rdx: envp
1344 *
1345 * We want to fallback into:
1346 * extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
1347 *
1348 * do_sys_execve asm fallback arguments:
1349 * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
1350 */
1351ENTRY(kernel_execve)
1352 CFI_STARTPROC
1353 FAKE_STACK_FRAME $0
1354 SAVE_ALL
1355 movq %rsp,%rcx
1356 call sys_execve
1357 movq %rax, RAX(%rsp)
1358 RESTORE_REST
1359 testq %rax,%rax
1360 je int_ret_from_sys_call
1361 RESTORE_ARGS
1362 UNFAKE_STACK_FRAME
1363 ret
1364 CFI_ENDPROC
1365END(kernel_execve)
1366 1342
1367/* Call softirq on interrupt stack. Interrupts are off. */ 1343/* Call softirq on interrupt stack. Interrupts are off. */
1368ENTRY(call_softirq) 1344ENTRY(call_softirq)