diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 23:02:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 23:02:25 -0400 |
commit | 42859eea96ba6beabfb0369a1eeffa3c7d2bd9cb (patch) | |
tree | fa38aeda0d6e7a4c48a882b166b8643594a1ad50 /arch/x86/kernel/entry_64.S | |
parent | f59b51fe3d3092c08d7d554ecb40db24011b2ebc (diff) | |
parent | f322220d6159455da2b5a8a596d802c8695fed30 (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.S | 74 |
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 | ||
565 | 1: | ||
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 |
566 | END(ret_from_fork) | 576 | END(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 | ||
1321 | ENTRY(kernel_thread_helper) | 1329 | ENTRY(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 | 1341 | END(ret_from_kernel_execve) |
1334 | END(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 | */ | ||
1351 | ENTRY(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 | ||
1365 | END(kernel_execve) | ||
1366 | 1342 | ||
1367 | /* Call softirq on interrupt stack. Interrupts are off. */ | 1343 | /* Call softirq on interrupt stack. Interrupts are off. */ |
1368 | ENTRY(call_softirq) | 1344 | ENTRY(call_softirq) |