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 | |
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')
88 files changed, 303 insertions, 889 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 550cce4dd648..26a28419cafc 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -271,6 +271,9 @@ config ARCH_WANT_OLD_COMPAT_IPC | |||
271 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION | 271 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION |
272 | bool | 272 | bool |
273 | 273 | ||
274 | config GENERIC_KERNEL_THREAD | ||
275 | bool | ||
276 | |||
274 | config HAVE_ARCH_SECCOMP_FILTER | 277 | config HAVE_ARCH_SECCOMP_FILTER |
275 | bool | 278 | bool |
276 | help | 279 | help |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9944dedee5b1..7da91246e279 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -20,6 +20,7 @@ config ALPHA | |||
20 | select GENERIC_CMOS_UPDATE | 20 | select GENERIC_CMOS_UPDATE |
21 | select GENERIC_STRNCPY_FROM_USER | 21 | select GENERIC_STRNCPY_FROM_USER |
22 | select GENERIC_STRNLEN_USER | 22 | select GENERIC_STRNLEN_USER |
23 | select GENERIC_KERNEL_THREAD | ||
23 | help | 24 | help |
24 | The Alpha is a 64-bit general-purpose processor designed and | 25 | The Alpha is a 64-bit general-purpose processor designed and |
25 | marketed by the Digital Equipment Corporation of blessed memory, | 26 | marketed by the Digital Equipment Corporation of blessed memory, |
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild index d97d66334e6f..64ffc9e9e548 100644 --- a/arch/alpha/include/asm/Kbuild +++ b/arch/alpha/include/asm/Kbuild | |||
@@ -10,3 +10,4 @@ header-y += pal.h | |||
10 | header-y += reg.h | 10 | header-y += reg.h |
11 | header-y += regdef.h | 11 | header-y += regdef.h |
12 | header-y += sysinfo.h | 12 | header-y += sysinfo.h |
13 | generic-y += exec.h | ||
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h deleted file mode 100644 index 4a5a41f30779..000000000000 --- a/arch/alpha/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __ALPHA_EXEC_H | ||
2 | #define __ALPHA_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* __ALPHA_EXEC_H */ | ||
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h index e37b887b3d9f..6cb7fe85c4b5 100644 --- a/arch/alpha/include/asm/processor.h +++ b/arch/alpha/include/asm/processor.h | |||
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); | |||
49 | /* Free all resources held by a thread. */ | 49 | /* Free all resources held by a thread. */ |
50 | extern void release_thread(struct task_struct *); | 50 | extern void release_thread(struct task_struct *); |
51 | 51 | ||
52 | /* Create a kernel thread without removing it from tasklists. */ | ||
53 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
54 | |||
55 | unsigned long get_wchan(struct task_struct *p); | 52 | unsigned long get_wchan(struct task_struct *p); |
56 | 53 | ||
57 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) | 54 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) |
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index a31a78eac9b9..3cb6c1188984 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h | |||
@@ -481,6 +481,8 @@ | |||
481 | #define __ARCH_WANT_SYS_OLDUMOUNT | 481 | #define __ARCH_WANT_SYS_OLDUMOUNT |
482 | #define __ARCH_WANT_SYS_SIGPENDING | 482 | #define __ARCH_WANT_SYS_SIGPENDING |
483 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 483 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
484 | #define __ARCH_WANT_SYS_EXECVE | ||
485 | #define __ARCH_WANT_KERNEL_EXECVE | ||
484 | 486 | ||
485 | /* "Conditional" syscalls. What we want is | 487 | /* "Conditional" syscalls. What we want is |
486 | 488 | ||
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 15fa821d09cd..89566b346c0f 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c | |||
@@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s); | |||
50 | EXPORT_SYMBOL(alpha_write_fp_reg); | 50 | EXPORT_SYMBOL(alpha_write_fp_reg); |
51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); | 51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); |
52 | 52 | ||
53 | /* entry.S */ | ||
54 | EXPORT_SYMBOL(kernel_thread); | ||
55 | |||
56 | /* Networking helper routines. */ | 53 | /* Networking helper routines. */ |
57 | EXPORT_SYMBOL(csum_tcpudp_magic); | 54 | EXPORT_SYMBOL(csum_tcpudp_magic); |
58 | EXPORT_SYMBOL(ip_compute_csum); | 55 | EXPORT_SYMBOL(ip_compute_csum); |
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index ec0da0567ab5..7e43e1156d10 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S | |||
@@ -609,59 +609,35 @@ ret_from_fork: | |||
609 | .end ret_from_fork | 609 | .end ret_from_fork |
610 | 610 | ||
611 | /* | 611 | /* |
612 | * kernel_thread(fn, arg, clone_flags) | 612 | * ... and new kernel threads - here |
613 | */ | 613 | */ |
614 | .align 4 | 614 | .align 4 |
615 | .globl kernel_thread | 615 | .globl ret_from_kernel_thread |
616 | .ent kernel_thread | 616 | .ent ret_from_kernel_thread |
617 | kernel_thread: | 617 | ret_from_kernel_thread: |
618 | /* We can be called from a module. */ | 618 | mov $17, $16 |
619 | ldgp $gp, 0($27) | 619 | jsr $26, schedule_tail |
620 | .prologue 1 | 620 | mov $9, $27 |
621 | subq $sp, SP_OFF+6*8, $sp | 621 | mov $10, $16 |
622 | br $1, 2f /* load start address */ | 622 | jsr $26, ($9) |
623 | |||
624 | /* We've now "returned" from a fake system call. */ | ||
625 | unop | ||
626 | blt $0, 1f /* error? */ | ||
627 | ldi $1, 0x3fff | ||
628 | beq $20, 1f /* parent or child? */ | ||
629 | |||
630 | bic $sp, $1, $8 /* in child. */ | ||
631 | jsr $26, ($27) | ||
632 | ldgp $gp, 0($26) | 623 | ldgp $gp, 0($26) |
633 | mov $0, $16 | 624 | mov $0, $16 |
634 | mov $31, $26 | 625 | mov $31, $26 |
635 | jmp $31, sys_exit | 626 | jmp $31, sys_exit |
627 | .end ret_from_kernel_thread | ||
636 | 628 | ||
637 | 1: ret /* in parent. */ | 629 | .globl ret_from_kernel_execve |
638 | 630 | .align 4 | |
639 | .align 4 | 631 | .ent ret_from_kernel_execve |
640 | 2: /* Fake a system call stack frame, as we can't do system calls | 632 | ret_from_kernel_execve: |
641 | from kernel space. Note that we store FN and ARG as they | 633 | mov $16, $sp |
642 | need to be set up in the child for the call. Also store $8 | ||
643 | and $26 for use in the parent. */ | ||
644 | stq $31, SP_OFF($sp) /* ps */ | ||
645 | stq $1, SP_OFF+8($sp) /* pc */ | ||
646 | stq $gp, SP_OFF+16($sp) /* gp */ | ||
647 | stq $16, 136($sp) /* $27; FN for child */ | ||
648 | stq $17, SP_OFF+24($sp) /* $16; ARG for child */ | ||
649 | stq $8, 64($sp) /* $8 */ | ||
650 | stq $26, 128($sp) /* $26 */ | ||
651 | /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */ | 634 | /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */ |
652 | ldq $2, alpha_mv+HAE_CACHE | 635 | ldq $2, alpha_mv+HAE_CACHE |
653 | stq $2, 152($sp) /* HAE */ | 636 | stq $2, 152($sp) /* HAE */ |
637 | mov $31, $19 /* to disable syscall restarts */ | ||
638 | br $31, ret_to_user | ||
654 | 639 | ||
655 | /* Shuffle FLAGS to the front; add CLONE_VM. */ | 640 | .end ret_from_kernel_execve |
656 | ldi $1, CLONE_VM|CLONE_UNTRACED | ||
657 | or $18, $1, $16 | ||
658 | bsr $26, sys_clone | ||
659 | |||
660 | /* We don't actually care for a3 success widgetry in the kernel. | ||
661 | Not for positive errno values. */ | ||
662 | stq $0, 0($sp) /* $0 */ | ||
663 | br ret_to_kernel | ||
664 | .end kernel_thread | ||
665 | 641 | ||
666 | 642 | ||
667 | /* | 643 | /* |
@@ -745,15 +721,6 @@ sys_rt_sigreturn: | |||
745 | .end sys_rt_sigreturn | 721 | .end sys_rt_sigreturn |
746 | 722 | ||
747 | .align 4 | 723 | .align 4 |
748 | .globl sys_execve | ||
749 | .ent sys_execve | ||
750 | sys_execve: | ||
751 | .prologue 0 | ||
752 | mov $sp, $19 | ||
753 | jmp $31, do_sys_execve | ||
754 | .end sys_execve | ||
755 | |||
756 | .align 4 | ||
757 | .globl alpha_ni_syscall | 724 | .globl alpha_ni_syscall |
758 | .ent alpha_ni_syscall | 725 | .ent alpha_ni_syscall |
759 | alpha_ni_syscall: | 726 | alpha_ni_syscall: |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 83638aa096d5..4054e0ffe2b2 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -263,33 +263,35 @@ alpha_vfork(struct pt_regs *regs) | |||
263 | 263 | ||
264 | /* | 264 | /* |
265 | * Copy an alpha thread.. | 265 | * Copy an alpha thread.. |
266 | * | ||
267 | * Note the "stack_offset" stuff: when returning to kernel mode, we need | ||
268 | * to have some extra stack-space for the kernel stack that still exists | ||
269 | * after the "ret_from_fork". When returning to user mode, we only want | ||
270 | * the space needed by the syscall stack frame (ie "struct pt_regs"). | ||
271 | * Use the passed "regs" pointer to determine how much space we need | ||
272 | * for a kernel fork(). | ||
273 | */ | 266 | */ |
274 | 267 | ||
275 | int | 268 | int |
276 | copy_thread(unsigned long clone_flags, unsigned long usp, | 269 | copy_thread(unsigned long clone_flags, unsigned long usp, |
277 | unsigned long unused, | 270 | unsigned long arg, |
278 | struct task_struct * p, struct pt_regs * regs) | 271 | struct task_struct * p, struct pt_regs * regs) |
279 | { | 272 | { |
280 | extern void ret_from_fork(void); | 273 | extern void ret_from_fork(void); |
274 | extern void ret_from_kernel_thread(void); | ||
281 | 275 | ||
282 | struct thread_info *childti = task_thread_info(p); | 276 | struct thread_info *childti = task_thread_info(p); |
283 | struct pt_regs * childregs; | 277 | struct pt_regs *childregs = task_pt_regs(p); |
284 | struct switch_stack * childstack, *stack; | 278 | struct switch_stack *childstack, *stack; |
285 | unsigned long stack_offset, settls; | 279 | unsigned long settls; |
286 | 280 | ||
287 | stack_offset = PAGE_SIZE - sizeof(struct pt_regs); | 281 | childstack = ((struct switch_stack *) childregs) - 1; |
288 | if (!(regs->ps & 8)) | 282 | if (unlikely(!regs)) { |
289 | stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; | 283 | /* kernel thread */ |
290 | childregs = (struct pt_regs *) | 284 | memset(childstack, 0, |
291 | (stack_offset + PAGE_SIZE + task_stack_page(p)); | 285 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
292 | 286 | childstack->r26 = (unsigned long) ret_from_kernel_thread; | |
287 | childstack->r9 = usp; /* function */ | ||
288 | childstack->r10 = arg; | ||
289 | childregs->hae = alpha_mv.hae_cache, | ||
290 | childti->pcb.usp = 0; | ||
291 | childti->pcb.ksp = (unsigned long) childstack; | ||
292 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
293 | return 0; | ||
294 | } | ||
293 | *childregs = *regs; | 295 | *childregs = *regs; |
294 | settls = regs->r20; | 296 | settls = regs->r20; |
295 | childregs->r0 = 0; | 297 | childregs->r0 = 0; |
@@ -297,7 +299,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
297 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ | 299 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ |
298 | regs->r20 = 0; | 300 | regs->r20 = 0; |
299 | stack = ((struct switch_stack *) regs) - 1; | 301 | stack = ((struct switch_stack *) regs) - 1; |
300 | childstack = ((struct switch_stack *) childregs) - 1; | ||
301 | *childstack = *stack; | 302 | *childstack = *stack; |
302 | childstack->r26 = (unsigned long) ret_from_fork; | 303 | childstack->r26 = (unsigned long) ret_from_fork; |
303 | childti->pcb.usp = usp; | 304 | childti->pcb.usp = usp; |
@@ -386,27 +387,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) | |||
386 | EXPORT_SYMBOL(dump_elf_task_fp); | 387 | EXPORT_SYMBOL(dump_elf_task_fp); |
387 | 388 | ||
388 | /* | 389 | /* |
389 | * sys_execve() executes a new program. | ||
390 | */ | ||
391 | asmlinkage int | ||
392 | do_sys_execve(const char __user *ufilename, | ||
393 | const char __user *const __user *argv, | ||
394 | const char __user *const __user *envp, struct pt_regs *regs) | ||
395 | { | ||
396 | int error; | ||
397 | char *filename; | ||
398 | |||
399 | filename = getname(ufilename); | ||
400 | error = PTR_ERR(filename); | ||
401 | if (IS_ERR(filename)) | ||
402 | goto out; | ||
403 | error = do_execve(filename, argv, envp, regs); | ||
404 | putname(filename); | ||
405 | out: | ||
406 | return error; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * Return saved PC of a blocked thread. This assumes the frame | 390 | * Return saved PC of a blocked thread. This assumes the frame |
411 | * pointer is the 6th saved long on the kernel stack and that the | 391 | * pointer is the 6th saved long on the kernel stack and that the |
412 | * saved return address is the first long in the frame. This all | 392 | * saved return address is the first long in the frame. This all |
@@ -459,22 +439,3 @@ get_wchan(struct task_struct *p) | |||
459 | } | 439 | } |
460 | return pc; | 440 | return pc; |
461 | } | 441 | } |
462 | |||
463 | int kernel_execve(const char *path, const char *const argv[], const char *const envp[]) | ||
464 | { | ||
465 | /* Avoid the HAE being gratuitously wrong, which would cause us | ||
466 | to do the whole turn off interrupts thing and restore it. */ | ||
467 | struct pt_regs regs = {.hae = alpha_mv.hae_cache}; | ||
468 | int err = do_execve(path, argv, envp, ®s); | ||
469 | if (!err) { | ||
470 | struct pt_regs *p = current_pt_regs(); | ||
471 | /* copy regs to normal position and off to userland we go... */ | ||
472 | *p = regs; | ||
473 | __asm__ __volatile__ ( | ||
474 | "mov %0, $sp;" | ||
475 | "br $31, ret_from_sys_call" | ||
476 | : : "r"(p)); | ||
477 | } | ||
478 | return err; | ||
479 | } | ||
480 | EXPORT_SYMBOL(kernel_execve); | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2867a7742306..e40eefb5d32d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -52,6 +52,7 @@ config ARM | |||
52 | select GENERIC_STRNCPY_FROM_USER | 52 | select GENERIC_STRNCPY_FROM_USER |
53 | select GENERIC_STRNLEN_USER | 53 | select GENERIC_STRNLEN_USER |
54 | select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN | 54 | select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN |
55 | select GENERIC_KERNEL_THREAD | ||
55 | help | 56 | help |
56 | The ARM series is a line of low-power-consumption RISC chip designs | 57 | The ARM series is a line of low-power-consumption RISC chip designs |
57 | licensed by ARM Ltd and targeted at embedded applications and | 58 | licensed by ARM Ltd and targeted at embedded applications and |
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 99afa7498260..06e7d509eaac 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h | |||
@@ -85,11 +85,6 @@ unsigned long get_wchan(struct task_struct *p); | |||
85 | #define cpu_relax() barrier() | 85 | #define cpu_relax() barrier() |
86 | #endif | 86 | #endif |
87 | 87 | ||
88 | /* | ||
89 | * Create a new kernel thread | ||
90 | */ | ||
91 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
92 | |||
93 | #define task_pt_regs(p) \ | 88 | #define task_pt_regs(p) \ |
94 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) | 89 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) |
95 | 90 | ||
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 355ece523f41..44fe998269d9 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
@@ -254,6 +254,11 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) | |||
254 | return regs->ARM_sp; | 254 | return regs->ARM_sp; |
255 | } | 255 | } |
256 | 256 | ||
257 | #define current_pt_regs(void) ({ \ | ||
258 | register unsigned long sp asm ("sp"); \ | ||
259 | (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \ | ||
260 | }) | ||
261 | |||
257 | #endif /* __KERNEL__ */ | 262 | #endif /* __KERNEL__ */ |
258 | 263 | ||
259 | #endif /* __ASSEMBLY__ */ | 264 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 74542c52f9be..368165e33c1c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #include <asm/barrier.h> | 2 | #include <asm/barrier.h> |
3 | #include <asm/compiler.h> | 3 | #include <asm/compiler.h> |
4 | #include <asm/cmpxchg.h> | 4 | #include <asm/cmpxchg.h> |
5 | #include <asm/exec.h> | ||
6 | #include <asm/switch_to.h> | 5 | #include <asm/switch_to.h> |
7 | #include <asm/system_info.h> | 6 | #include <asm/system_info.h> |
8 | #include <asm/system_misc.h> | 7 | #include <asm/system_misc.h> |
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index d9ff5cc3a506..f259921edfe9 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
@@ -478,6 +478,8 @@ | |||
478 | #define __ARCH_WANT_OLD_READDIR | 478 | #define __ARCH_WANT_OLD_READDIR |
479 | #define __ARCH_WANT_SYS_SOCKETCALL | 479 | #define __ARCH_WANT_SYS_SOCKETCALL |
480 | #endif | 480 | #endif |
481 | #define __ARCH_WANT_SYS_EXECVE | ||
482 | #define __ARCH_WANT_KERNEL_EXECVE | ||
481 | 483 | ||
482 | /* | 484 | /* |
483 | * "Conditional" syscalls | 485 | * "Conditional" syscalls |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index e337879595e5..831cd38c8d99 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -20,7 +20,7 @@ | |||
20 | CALL(sys_creat) | 20 | CALL(sys_creat) |
21 | CALL(sys_link) | 21 | CALL(sys_link) |
22 | /* 10 */ CALL(sys_unlink) | 22 | /* 10 */ CALL(sys_unlink) |
23 | CALL(sys_execve_wrapper) | 23 | CALL(sys_execve) |
24 | CALL(sys_chdir) | 24 | CALL(sys_chdir) |
25 | CALL(OBSOLETE(sys_time)) /* used by libc4 */ | 25 | CALL(OBSOLETE(sys_time)) /* used by libc4 */ |
26 | CALL(sys_mknod) | 26 | CALL(sys_mknod) |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f45987037bf1..e340fa1db203 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -91,6 +91,30 @@ ENTRY(ret_from_fork) | |||
91 | b ret_slow_syscall | 91 | b ret_slow_syscall |
92 | ENDPROC(ret_from_fork) | 92 | ENDPROC(ret_from_fork) |
93 | 93 | ||
94 | ENTRY(ret_from_kernel_thread) | ||
95 | UNWIND(.fnstart) | ||
96 | UNWIND(.cantunwind) | ||
97 | bl schedule_tail | ||
98 | mov r0, r4 | ||
99 | adr lr, BSYM(1f) @ kernel threads should not exit | ||
100 | mov pc, r5 | ||
101 | 1: bl do_exit | ||
102 | nop | ||
103 | UNWIND(.fnend) | ||
104 | ENDPROC(ret_from_kernel_thread) | ||
105 | |||
106 | /* | ||
107 | * turn a kernel thread into userland process | ||
108 | * use: ret_from_kernel_execve(struct pt_regs *normal) | ||
109 | */ | ||
110 | ENTRY(ret_from_kernel_execve) | ||
111 | mov why, #0 @ not a syscall | ||
112 | str why, [r0, #S_R0] @ ... and we want 0 in ->ARM_r0 as well | ||
113 | get_thread_info tsk @ thread structure | ||
114 | mov sp, r0 @ stack pointer just under pt_regs | ||
115 | b ret_slow_syscall | ||
116 | ENDPROC(ret_from_kernel_execve) | ||
117 | |||
94 | .equ NR_syscalls,0 | 118 | .equ NR_syscalls,0 |
95 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 | 119 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 |
96 | #include "calls.S" | 120 | #include "calls.S" |
@@ -517,11 +541,6 @@ sys_vfork_wrapper: | |||
517 | b sys_vfork | 541 | b sys_vfork |
518 | ENDPROC(sys_vfork_wrapper) | 542 | ENDPROC(sys_vfork_wrapper) |
519 | 543 | ||
520 | sys_execve_wrapper: | ||
521 | add r3, sp, #S_OFF | ||
522 | b sys_execve | ||
523 | ENDPROC(sys_execve_wrapper) | ||
524 | |||
525 | sys_clone_wrapper: | 544 | sys_clone_wrapper: |
526 | add ip, sp, #S_OFF | 545 | add ip, sp, #S_OFF |
527 | str ip, [sp, #4] | 546 | str ip, [sp, #4] |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 04eea22d7958..f98c17ff1957 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -373,6 +373,7 @@ void release_thread(struct task_struct *dead_task) | |||
373 | } | 373 | } |
374 | 374 | ||
375 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 375 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
376 | asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); | ||
376 | 377 | ||
377 | int | 378 | int |
378 | copy_thread(unsigned long clone_flags, unsigned long stack_start, | 379 | copy_thread(unsigned long clone_flags, unsigned long stack_start, |
@@ -381,13 +382,20 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
381 | struct thread_info *thread = task_thread_info(p); | 382 | struct thread_info *thread = task_thread_info(p); |
382 | struct pt_regs *childregs = task_pt_regs(p); | 383 | struct pt_regs *childregs = task_pt_regs(p); |
383 | 384 | ||
384 | *childregs = *regs; | ||
385 | childregs->ARM_r0 = 0; | ||
386 | childregs->ARM_sp = stack_start; | ||
387 | |||
388 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); | 385 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); |
386 | |||
387 | if (likely(regs)) { | ||
388 | *childregs = *regs; | ||
389 | childregs->ARM_r0 = 0; | ||
390 | childregs->ARM_sp = stack_start; | ||
391 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | ||
392 | } else { | ||
393 | thread->cpu_context.r4 = stk_sz; | ||
394 | thread->cpu_context.r5 = stack_start; | ||
395 | thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; | ||
396 | childregs->ARM_cpsr = SVC_MODE; | ||
397 | } | ||
389 | thread->cpu_context.sp = (unsigned long)childregs; | 398 | thread->cpu_context.sp = (unsigned long)childregs; |
390 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | ||
391 | 399 | ||
392 | clear_ptrace_hw_breakpoint(p); | 400 | clear_ptrace_hw_breakpoint(p); |
393 | 401 | ||
@@ -423,63 +431,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) | |||
423 | } | 431 | } |
424 | EXPORT_SYMBOL(dump_fpu); | 432 | EXPORT_SYMBOL(dump_fpu); |
425 | 433 | ||
426 | /* | ||
427 | * Shuffle the argument into the correct register before calling the | ||
428 | * thread function. r4 is the thread argument, r5 is the pointer to | ||
429 | * the thread function, and r6 points to the exit function. | ||
430 | */ | ||
431 | extern void kernel_thread_helper(void); | ||
432 | asm( ".pushsection .text\n" | ||
433 | " .align\n" | ||
434 | " .type kernel_thread_helper, #function\n" | ||
435 | "kernel_thread_helper:\n" | ||
436 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
437 | " bl trace_hardirqs_on\n" | ||
438 | #endif | ||
439 | " msr cpsr_c, r7\n" | ||
440 | " mov r0, r4\n" | ||
441 | " mov lr, r6\n" | ||
442 | " mov pc, r5\n" | ||
443 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | ||
444 | " .popsection"); | ||
445 | |||
446 | #ifdef CONFIG_ARM_UNWIND | ||
447 | extern void kernel_thread_exit(long code); | ||
448 | asm( ".pushsection .text\n" | ||
449 | " .align\n" | ||
450 | " .type kernel_thread_exit, #function\n" | ||
451 | "kernel_thread_exit:\n" | ||
452 | " .fnstart\n" | ||
453 | " .cantunwind\n" | ||
454 | " bl do_exit\n" | ||
455 | " nop\n" | ||
456 | " .fnend\n" | ||
457 | " .size kernel_thread_exit, . - kernel_thread_exit\n" | ||
458 | " .popsection"); | ||
459 | #else | ||
460 | #define kernel_thread_exit do_exit | ||
461 | #endif | ||
462 | |||
463 | /* | ||
464 | * Create a kernel thread. | ||
465 | */ | ||
466 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
467 | { | ||
468 | struct pt_regs regs; | ||
469 | |||
470 | memset(®s, 0, sizeof(regs)); | ||
471 | |||
472 | regs.ARM_r4 = (unsigned long)arg; | ||
473 | regs.ARM_r5 = (unsigned long)fn; | ||
474 | regs.ARM_r6 = (unsigned long)kernel_thread_exit; | ||
475 | regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; | ||
476 | regs.ARM_pc = (unsigned long)kernel_thread_helper; | ||
477 | regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT; | ||
478 | |||
479 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
480 | } | ||
481 | EXPORT_SYMBOL(kernel_thread); | ||
482 | |||
483 | unsigned long get_wchan(struct task_struct *p) | 434 | unsigned long get_wchan(struct task_struct *p) |
484 | { | 435 | { |
485 | struct stackframe frame; | 436 | struct stackframe frame; |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 76cbb055dd05..c2a898aa57aa 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -59,69 +59,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs) | |||
59 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); | 59 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); |
60 | } | 60 | } |
61 | 61 | ||
62 | /* sys_execve() executes a new program. | ||
63 | * This is called indirectly via a small wrapper | ||
64 | */ | ||
65 | asmlinkage int sys_execve(const char __user *filenamei, | ||
66 | const char __user *const __user *argv, | ||
67 | const char __user *const __user *envp, struct pt_regs *regs) | ||
68 | { | ||
69 | int error; | ||
70 | char * filename; | ||
71 | |||
72 | filename = getname(filenamei); | ||
73 | error = PTR_ERR(filename); | ||
74 | if (IS_ERR(filename)) | ||
75 | goto out; | ||
76 | error = do_execve(filename, argv, envp, regs); | ||
77 | putname(filename); | ||
78 | out: | ||
79 | return error; | ||
80 | } | ||
81 | |||
82 | int kernel_execve(const char *filename, | ||
83 | const char *const argv[], | ||
84 | const char *const envp[]) | ||
85 | { | ||
86 | struct pt_regs regs; | ||
87 | int ret; | ||
88 | |||
89 | memset(®s, 0, sizeof(struct pt_regs)); | ||
90 | ret = do_execve(filename, | ||
91 | (const char __user *const __user *)argv, | ||
92 | (const char __user *const __user *)envp, ®s); | ||
93 | if (ret < 0) | ||
94 | goto out; | ||
95 | |||
96 | /* | ||
97 | * Save argc to the register structure for userspace. | ||
98 | */ | ||
99 | regs.ARM_r0 = ret; | ||
100 | |||
101 | /* | ||
102 | * We were successful. We won't be returning to our caller, but | ||
103 | * instead to user space by manipulating the kernel stack. | ||
104 | */ | ||
105 | asm( "add r0, %0, %1\n\t" | ||
106 | "mov r1, %2\n\t" | ||
107 | "mov r2, %3\n\t" | ||
108 | "bl memmove\n\t" /* copy regs to top of stack */ | ||
109 | "mov r8, #0\n\t" /* not a syscall */ | ||
110 | "mov r9, %0\n\t" /* thread structure */ | ||
111 | "mov sp, r0\n\t" /* reposition stack pointer */ | ||
112 | "b ret_to_user" | ||
113 | : | ||
114 | : "r" (current_thread_info()), | ||
115 | "Ir" (THREAD_START_SP - sizeof(regs)), | ||
116 | "r" (®s), | ||
117 | "Ir" (sizeof(regs)) | ||
118 | : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory"); | ||
119 | |||
120 | out: | ||
121 | return ret; | ||
122 | } | ||
123 | EXPORT_SYMBOL(kernel_execve); | ||
124 | |||
125 | /* | 62 | /* |
126 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle | 63 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle |
127 | * with a different argument ordering. | 64 | * with a different argument ordering. |
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index e3ba7bca06fa..be0433ee5a8e 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild | |||
@@ -1,5 +1,6 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | ||
4 | 5 | ||
5 | header-y += cachectl.h | 6 | header-y += cachectl.h |
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h deleted file mode 100644 index f467be8bf823..000000000000 --- a/arch/avr32/include/asm/exec.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | #ifndef __ASM_AVR32_EXEC_H | ||
9 | #define __ASM_AVR32_EXEC_H | ||
10 | |||
11 | #define arch_align_stack(x) (x) | ||
12 | |||
13 | #endif /* __ASM_AVR32_EXEC_H */ | ||
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index 277f1a4ecb09..4e4e98da8192 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild | |||
@@ -12,6 +12,7 @@ generic-y += div64.h | |||
12 | generic-y += dma.h | 12 | generic-y += dma.h |
13 | generic-y += emergency-restart.h | 13 | generic-y += emergency-restart.h |
14 | generic-y += errno.h | 14 | generic-y += errno.h |
15 | generic-y += exec.h | ||
15 | generic-y += fb.h | 16 | generic-y += fb.h |
16 | generic-y += fcntl.h | 17 | generic-y += fcntl.h |
17 | generic-y += futex.h | 18 | generic-y += futex.h |
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h deleted file mode 100644 index 0fea482cdc84..000000000000 --- a/arch/c6x/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _ASM_C6X_EXEC_H | ||
2 | #define _ASM_C6X_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* _ASM_C6X_EXEC_H */ | ||
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index a8eab26a1ec7..ff1bf7fcae8e 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild | |||
@@ -9,3 +9,4 @@ header-y += rs485.h | |||
9 | header-y += sync_serial.h | 9 | header-y += sync_serial.h |
10 | 10 | ||
11 | generic-y += clkdev.h | 11 | generic-y += clkdev.h |
12 | generic-y += exec.h | ||
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h deleted file mode 100644 index 9665dab7e25b..000000000000 --- a/arch/cris/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __ASM_CRIS_EXEC_H | ||
2 | #define __ASM_CRIS_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* __ASM_CRIS_EXEC_H */ | ||
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index 13cd044aabdf..251bd7125576 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild | |||
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm | |||
3 | header-y += registers.h | 3 | header-y += registers.h |
4 | header-y += termios.h | 4 | header-y += termios.h |
5 | generic-y += clkdev.h | 5 | generic-y += clkdev.h |
6 | generic-y += exec.h | ||
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h deleted file mode 100644 index 65c91305d4a7..000000000000 --- a/arch/frv/include/asm/exec.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* FR-V CPU executable handling | ||
2 | * | ||
3 | * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_EXEC_H | ||
13 | #define _ASM_EXEC_H | ||
14 | |||
15 | #define arch_align_stack(x) (x) | ||
16 | |||
17 | #endif /* _ASM_EXEC_H */ | ||
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 0e152a93c125..fccd81eddff1 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | ||
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h deleted file mode 100644 index c01c45ccadf9..000000000000 --- a/arch/h8300/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _H8300_EXEC_H | ||
2 | #define _H8300_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* _H8300_EXEC_H */ | ||
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c index 620dd18197a0..553cd60ee659 100644 --- a/arch/hexagon/kernel/syscall.c +++ b/arch/hexagon/kernel/syscall.c | |||
@@ -87,4 +87,3 @@ int kernel_execve(const char *filename, | |||
87 | 87 | ||
88 | return retval; | 88 | return retval; |
89 | } | 89 | } |
90 | EXPORT_SYMBOL(kernel_execve); | ||
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 58f3d14a6cd4..562f59315847 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild | |||
@@ -14,3 +14,4 @@ header-y += rse.h | |||
14 | header-y += ucontext.h | 14 | header-y += ucontext.h |
15 | header-y += ustack.h | 15 | header-y += ustack.h |
16 | generic-y += clkdev.h | 16 | generic-y += clkdev.h |
17 | generic-y += exec.h | ||
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h deleted file mode 100644 index b26242490e36..000000000000 --- a/arch/ia64/include/asm/exec.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Process execution defines. | ||
3 | * | ||
4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | ||
5 | * David Mosberger-Tang <davidm@hpl.hp.com> | ||
6 | * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com> | ||
7 | * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> | ||
8 | */ | ||
9 | #ifndef _ASM_IA64_EXEC_H | ||
10 | #define _ASM_IA64_EXEC_H | ||
11 | |||
12 | #define arch_align_stack(x) (x) | ||
13 | |||
14 | #endif /* _ASM_IA64_EXEC_H */ | ||
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 0e152a93c125..fccd81eddff1 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | ||
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h deleted file mode 100644 index c805dbd75b5d..000000000000 --- a/arch/m32r/include/asm/exec.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2001 Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto | ||
7 | * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org> | ||
8 | */ | ||
9 | #ifndef _ASM_M32R_EXEC_H | ||
10 | #define _ASM_M32R_EXEC_H | ||
11 | |||
12 | #define arch_align_stack(x) (x) | ||
13 | |||
14 | #endif /* _ASM_M32R_EXEC_H */ | ||
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index bfe675f0faee..ecb540810ab3 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild | |||
@@ -7,6 +7,7 @@ generic-y += cputime.h | |||
7 | generic-y += device.h | 7 | generic-y += device.h |
8 | generic-y += emergency-restart.h | 8 | generic-y += emergency-restart.h |
9 | generic-y += errno.h | 9 | generic-y += errno.h |
10 | generic-y += exec.h | ||
10 | generic-y += futex.h | 11 | generic-y += futex.h |
11 | generic-y += ioctl.h | 12 | generic-y += ioctl.h |
12 | generic-y += ipcbuf.h | 13 | generic-y += ipcbuf.h |
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h deleted file mode 100644 index 0499adf90230..000000000000 --- a/arch/m68k/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _M68K_EXEC_H | ||
2 | #define _M68K_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* _M68K_EXEC_H */ | ||
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 48510f6cec8f..8653072d7e9f 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm | |||
2 | 2 | ||
3 | header-y += elf.h | 3 | header-y += elf.h |
4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
5 | generic-y += exec.h | ||
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h deleted file mode 100644 index e750de1fe8fb..000000000000 --- a/arch/microblaze/include/asm/exec.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_MICROBLAZE_EXEC_H | ||
10 | #define _ASM_MICROBLAZE_EXEC_H | ||
11 | |||
12 | #define arch_align_stack(x) (x) | ||
13 | |||
14 | #endif /* _ASM_MICROBLAZE_EXEC_H */ | ||
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index 0d20f5526dd8..fccd81eddff1 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | ||
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h deleted file mode 100644 index c74e367f4b9d..000000000000 --- a/arch/mn10300/include/asm/exec.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | /* MN10300 process execution definitions | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | #ifndef _ASM_EXEC_H | ||
12 | #define _ASM_EXEC_H | ||
13 | |||
14 | #define arch_align_stack(x) (x) | ||
15 | |||
16 | #endif /* _ASM_EXEC_H */ | ||
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index 0587f62e5b76..458371a1565a 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild | |||
@@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm | |||
3 | header-y += pdc.h | 3 | header-y += pdc.h |
4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
5 | generic-y += word-at-a-time.h | 5 | generic-y += word-at-a-time.h |
6 | generic-y += exec.h | ||
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h deleted file mode 100644 index 6bb5af75b17a..000000000000 --- a/arch/parisc/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __PARISC_EXEC_H | ||
2 | #define __PARISC_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* __PARISC_EXEC_H */ | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ceff7aef2477..99d2d790d152 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -135,6 +135,7 @@ config S390 | |||
135 | select GENERIC_CLOCKEVENTS | 135 | select GENERIC_CLOCKEVENTS |
136 | select KTIME_SCALAR if 32BIT | 136 | select KTIME_SCALAR if 32BIT |
137 | select HAVE_ARCH_SECCOMP_FILTER | 137 | select HAVE_ARCH_SECCOMP_FILTER |
138 | select GENERIC_KERNEL_THREAD | ||
138 | 139 | ||
139 | config SCHED_OMIT_FRAME_POINTER | 140 | config SCHED_OMIT_FRAME_POINTER |
140 | def_bool y | 141 | def_bool y |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 56831dfa9198..94e749c90230 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -35,6 +35,7 @@ static inline void get_cpu_id(struct cpuid *ptr) | |||
35 | extern void s390_adjust_jiffies(void); | 35 | extern void s390_adjust_jiffies(void); |
36 | extern const struct seq_operations cpuinfo_op; | 36 | extern const struct seq_operations cpuinfo_op; |
37 | extern int sysctl_ieee_emulation_warnings; | 37 | extern int sysctl_ieee_emulation_warnings; |
38 | extern void execve_tail(void); | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. | 41 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. |
@@ -126,6 +127,7 @@ struct stack_frame { | |||
126 | regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \ | 127 | regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \ |
127 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ | 128 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ |
128 | regs->gprs[15] = new_stackp; \ | 129 | regs->gprs[15] = new_stackp; \ |
130 | execve_tail(); \ | ||
129 | } while (0) | 131 | } while (0) |
130 | 132 | ||
131 | #define start_thread31(regs, new_psw, new_stackp) do { \ | 133 | #define start_thread31(regs, new_psw, new_stackp) do { \ |
@@ -135,6 +137,7 @@ struct stack_frame { | |||
135 | __tlb_flush_mm(current->mm); \ | 137 | __tlb_flush_mm(current->mm); \ |
136 | crst_table_downgrade(current->mm, 1UL << 31); \ | 138 | crst_table_downgrade(current->mm, 1UL << 31); \ |
137 | update_mm(current->mm, current); \ | 139 | update_mm(current->mm, current); \ |
140 | execve_tail(); \ | ||
138 | } while (0) | 141 | } while (0) |
139 | 142 | ||
140 | /* Forward declaration, a strange C thing */ | 143 | /* Forward declaration, a strange C thing */ |
@@ -150,7 +153,6 @@ static inline void show_cacheinfo(struct seq_file *m) { } | |||
150 | 153 | ||
151 | /* Free all resources held by a thread. */ | 154 | /* Free all resources held by a thread. */ |
152 | extern void release_thread(struct task_struct *); | 155 | extern void release_thread(struct task_struct *); |
153 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
154 | 156 | ||
155 | /* | 157 | /* |
156 | * Return saved PC of a blocked thread. | 158 | * Return saved PC of a blocked thread. |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 4e64b5cd1558..8192e292753a 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
@@ -417,6 +417,8 @@ | |||
417 | # define __ARCH_WANT_COMPAT_SYS_TIME | 417 | # define __ARCH_WANT_COMPAT_SYS_TIME |
418 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 418 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
419 | # endif | 419 | # endif |
420 | #define __ARCH_WANT_SYS_EXECVE | ||
421 | #define __ARCH_WANT_KERNEL_EXECVE | ||
420 | 422 | ||
421 | /* | 423 | /* |
422 | * "Conditional" syscalls | 424 | * "Conditional" syscalls |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 189963c90c6e..65cca95843e1 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -432,32 +432,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) | |||
432 | return ret; | 432 | return ret; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* | ||
436 | * sys32_execve() executes a new program after the asm stub has set | ||
437 | * things up for us. This should basically do what I want it to. | ||
438 | */ | ||
439 | asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv, | ||
440 | compat_uptr_t __user *envp) | ||
441 | { | ||
442 | struct pt_regs *regs = task_pt_regs(current); | ||
443 | char *filename; | ||
444 | long rc; | ||
445 | |||
446 | filename = getname(name); | ||
447 | rc = PTR_ERR(filename); | ||
448 | if (IS_ERR(filename)) | ||
449 | return rc; | ||
450 | rc = compat_do_execve(filename, argv, envp, regs); | ||
451 | if (rc) | ||
452 | goto out; | ||
453 | current->thread.fp_regs.fpc=0; | ||
454 | asm volatile("sfpc %0,0" : : "d" (0)); | ||
455 | rc = regs->gprs[2]; | ||
456 | out: | ||
457 | putname(filename); | ||
458 | return rc; | ||
459 | } | ||
460 | |||
461 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, | 435 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, |
462 | size_t count, u32 poshi, u32 poslo) | 436 | size_t count, u32 poshi, u32 poslo) |
463 | { | 437 | { |
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 90887bd98cf0..d4d0239970ac 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h | |||
@@ -125,8 +125,6 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, | |||
125 | compat_sigset_t __user *oset, size_t sigsetsize); | 125 | compat_sigset_t __user *oset, size_t sigsetsize); |
126 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); | 126 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); |
127 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); | 127 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); |
128 | long sys32_execve(const char __user *name, compat_uptr_t __user *argv, | ||
129 | compat_uptr_t __user *envp); | ||
130 | long sys32_init_module(void __user *umod, unsigned long len, | 128 | long sys32_init_module(void __user *umod, unsigned long len, |
131 | const char __user *uargs); | 129 | const char __user *uargs); |
132 | long sys32_delete_module(const char __user *name_user, unsigned int flags); | 130 | long sys32_delete_module(const char __user *name_user, unsigned int flags); |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 3afba804fe97..ad79b846535c 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -1576,7 +1576,7 @@ ENTRY(sys32_execve_wrapper) | |||
1576 | llgtr %r2,%r2 # char * | 1576 | llgtr %r2,%r2 # char * |
1577 | llgtr %r3,%r3 # compat_uptr_t * | 1577 | llgtr %r3,%r3 # compat_uptr_t * |
1578 | llgtr %r4,%r4 # compat_uptr_t * | 1578 | llgtr %r4,%r4 # compat_uptr_t * |
1579 | jg sys32_execve # branch to system call | 1579 | jg compat_sys_execve # branch to system call |
1580 | 1580 | ||
1581 | ENTRY(sys_fanotify_init_wrapper) | 1581 | ENTRY(sys_fanotify_init_wrapper) |
1582 | llgfr %r2,%r2 # unsigned int | 1582 | llgfr %r2,%r2 # unsigned int |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 870bad6d56fc..ef46f66bc0d6 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -331,45 +331,38 @@ ENTRY(ret_from_fork) | |||
331 | l %r12,__LC_THREAD_INFO | 331 | l %r12,__LC_THREAD_INFO |
332 | l %r13,__LC_SVC_NEW_PSW+4 | 332 | l %r13,__LC_SVC_NEW_PSW+4 |
333 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 333 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
334 | jo 0f | 334 | je 1f |
335 | st %r15,__PT_R15(%r11) # store stack pointer for new kthread | 335 | l %r1,BASED(.Lschedule_tail) |
336 | 0: l %r1,BASED(.Lschedule_tail) | ||
337 | basr %r14,%r1 # call schedule_tail | 336 | basr %r14,%r1 # call schedule_tail |
338 | TRACE_IRQS_ON | 337 | TRACE_IRQS_ON |
339 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 338 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
340 | j sysc_tracenogo | 339 | j sysc_tracenogo |
341 | 340 | ||
341 | 1: # it's a kernel thread | ||
342 | st %r15,__PT_R15(%r11) # store stack pointer for new kthread | ||
343 | l %r1,BASED(.Lschedule_tail) | ||
344 | basr %r14,%r1 # call schedule_tail | ||
345 | TRACE_IRQS_ON | ||
346 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
347 | lm %r9,%r11,__PT_R9(%r11) # load gprs | ||
348 | ENTRY(kernel_thread_starter) | ||
349 | la %r2,0(%r10) | ||
350 | basr %r14,%r9 | ||
351 | la %r2,0 | ||
352 | br %r11 # do_exit | ||
353 | |||
342 | # | 354 | # |
343 | # kernel_execve function needs to deal with pt_regs that is not | 355 | # kernel_execve function needs to deal with pt_regs that is not |
344 | # at the usual place | 356 | # at the usual place |
345 | # | 357 | # |
346 | ENTRY(kernel_execve) | 358 | ENTRY(ret_from_kernel_execve) |
347 | stm %r12,%r15,48(%r15) | 359 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
348 | lr %r14,%r15 | 360 | lr %r15,%r2 |
349 | l %r13,__LC_SVC_NEW_PSW+4 | 361 | lr %r11,%r2 |
350 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 362 | ahi %r15,-STACK_FRAME_OVERHEAD |
351 | st %r14,__SF_BACKCHAIN(%r15) | ||
352 | la %r12,STACK_FRAME_OVERHEAD(%r15) | ||
353 | xc 0(__PT_SIZE,%r12),0(%r12) | ||
354 | l %r1,BASED(.Ldo_execve) | ||
355 | lr %r5,%r12 | ||
356 | basr %r14,%r1 # call do_execve | ||
357 | ltr %r2,%r2 | ||
358 | je 0f | ||
359 | ahi %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
360 | lm %r12,%r15,48(%r15) | ||
361 | br %r14 | ||
362 | # execve succeeded. | ||
363 | 0: ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
364 | l %r15,__LC_KERNEL_STACK # load ksp | ||
365 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
366 | la %r11,STACK_FRAME_OVERHEAD(%r15) | ||
367 | mvc 0(__PT_SIZE,%r11),0(%r12) # copy pt_regs | ||
368 | l %r12,__LC_THREAD_INFO | ||
369 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 363 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
364 | l %r12,__LC_THREAD_INFO | ||
370 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 365 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
371 | l %r1,BASED(.Lexecve_tail) | ||
372 | basr %r14,%r1 # call execve_tail | ||
373 | j sysc_return | 366 | j sysc_return |
374 | 367 | ||
375 | /* | 368 | /* |
@@ -931,8 +924,6 @@ cleanup_idle_wait: | |||
931 | .Ldo_signal: .long do_signal | 924 | .Ldo_signal: .long do_signal |
932 | .Ldo_notify_resume: .long do_notify_resume | 925 | .Ldo_notify_resume: .long do_notify_resume |
933 | .Ldo_per_trap: .long do_per_trap | 926 | .Ldo_per_trap: .long do_per_trap |
934 | .Ldo_execve: .long do_execve | ||
935 | .Lexecve_tail: .long execve_tail | ||
936 | .Ljump_table: .long pgm_check_table | 927 | .Ljump_table: .long pgm_check_table |
937 | .Lschedule: .long schedule | 928 | .Lschedule: .long schedule |
938 | #ifdef CONFIG_PREEMPT | 929 | #ifdef CONFIG_PREEMPT |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index a5f4dc42a5db..d0d3f69a7346 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -58,9 +58,6 @@ long sys_fork(void); | |||
58 | long sys_clone(unsigned long newsp, unsigned long clone_flags, | 58 | long sys_clone(unsigned long newsp, unsigned long clone_flags, |
59 | int __user *parent_tidptr, int __user *child_tidptr); | 59 | int __user *parent_tidptr, int __user *child_tidptr); |
60 | long sys_vfork(void); | 60 | long sys_vfork(void); |
61 | void execve_tail(void); | ||
62 | long sys_execve(const char __user *name, const char __user *const __user *argv, | ||
63 | const char __user *const __user *envp); | ||
64 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); | 61 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); |
65 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 62 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
66 | struct old_sigaction __user *oact); | 63 | struct old_sigaction __user *oact); |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7549985402f7..f9761f806c9e 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -353,41 +353,31 @@ ENTRY(ret_from_fork) | |||
353 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 353 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
354 | lg %r12,__LC_THREAD_INFO | 354 | lg %r12,__LC_THREAD_INFO |
355 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 355 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
356 | jo 0f | 356 | je 1f |
357 | stg %r15,__PT_R15(%r11) # store stack pointer for new kthread | 357 | brasl %r14,schedule_tail |
358 | 0: brasl %r14,schedule_tail | ||
359 | TRACE_IRQS_ON | 358 | TRACE_IRQS_ON |
360 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 359 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
361 | j sysc_tracenogo | 360 | j sysc_tracenogo |
362 | 361 | 1: # it's a kernel thread | |
363 | # | 362 | stg %r15,__PT_R15(%r11) # store stack pointer for new kthread |
364 | # kernel_execve function needs to deal with pt_regs that is not | 363 | brasl %r14,schedule_tail |
365 | # at the usual place | 364 | TRACE_IRQS_ON |
366 | # | 365 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
367 | ENTRY(kernel_execve) | 366 | lmg %r9,%r11,__PT_R9(%r11) # load gprs |
368 | stmg %r12,%r15,96(%r15) | 367 | ENTRY(kernel_thread_starter) |
369 | lgr %r14,%r15 | 368 | la %r2,0(%r10) |
370 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 369 | basr %r14,%r9 |
371 | stg %r14,__SF_BACKCHAIN(%r15) | 370 | la %r2,0 |
372 | la %r12,STACK_FRAME_OVERHEAD(%r15) | 371 | br %r11 # do_exit |
373 | xc 0(__PT_SIZE,%r12),0(%r12) | 372 | |
374 | lgr %r5,%r12 | 373 | ENTRY(ret_from_kernel_execve) |
375 | brasl %r14,do_execve | 374 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
376 | ltgfr %r2,%r2 | 375 | lgr %r15,%r2 |
377 | je 0f | 376 | lgr %r11,%r2 |
378 | aghi %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE) | 377 | aghi %r15,-STACK_FRAME_OVERHEAD |
379 | lmg %r12,%r15,96(%r15) | ||
380 | br %r14 | ||
381 | # execve succeeded. | ||
382 | 0: ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
383 | lg %r15,__LC_KERNEL_STACK # load ksp | ||
384 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
385 | la %r11,STACK_FRAME_OVERHEAD(%r15) | ||
386 | mvc 0(__PT_SIZE,%r11),0(%r12) # copy pt_regs | ||
387 | lg %r12,__LC_THREAD_INFO | ||
388 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 378 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
379 | lg %r12,__LC_THREAD_INFO | ||
389 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 380 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
390 | brasl %r14,execve_tail | ||
391 | j sysc_return | 381 | j sysc_return |
392 | 382 | ||
393 | /* | 383 | /* |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5024be27df44..cd31ad457a9b 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -100,35 +100,6 @@ void cpu_idle(void) | |||
100 | 100 | ||
101 | extern void __kprobes kernel_thread_starter(void); | 101 | extern void __kprobes kernel_thread_starter(void); |
102 | 102 | ||
103 | asm( | ||
104 | ".section .kprobes.text, \"ax\"\n" | ||
105 | ".global kernel_thread_starter\n" | ||
106 | "kernel_thread_starter:\n" | ||
107 | " la 2,0(10)\n" | ||
108 | " basr 14,9\n" | ||
109 | " la 2,0\n" | ||
110 | " br 11\n" | ||
111 | ".previous\n"); | ||
112 | |||
113 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
114 | { | ||
115 | struct pt_regs regs; | ||
116 | |||
117 | memset(®s, 0, sizeof(regs)); | ||
118 | regs.psw.mask = psw_kernel_bits | | ||
119 | PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; | ||
120 | regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE; | ||
121 | regs.gprs[9] = (unsigned long) fn; | ||
122 | regs.gprs[10] = (unsigned long) arg; | ||
123 | regs.gprs[11] = (unsigned long) do_exit; | ||
124 | regs.orig_gpr2 = -1; | ||
125 | |||
126 | /* Ok, create the new process.. */ | ||
127 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, | ||
128 | 0, ®s, 0, NULL, NULL); | ||
129 | } | ||
130 | EXPORT_SYMBOL(kernel_thread); | ||
131 | |||
132 | /* | 103 | /* |
133 | * Free current thread data structures etc.. | 104 | * Free current thread data structures etc.. |
134 | */ | 105 | */ |
@@ -146,7 +117,7 @@ void release_thread(struct task_struct *dead_task) | |||
146 | } | 117 | } |
147 | 118 | ||
148 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | 119 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, |
149 | unsigned long unused, | 120 | unsigned long arg, |
150 | struct task_struct *p, struct pt_regs *regs) | 121 | struct task_struct *p, struct pt_regs *regs) |
151 | { | 122 | { |
152 | struct thread_info *ti; | 123 | struct thread_info *ti; |
@@ -158,20 +129,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
158 | 129 | ||
159 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); | 130 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); |
160 | p->thread.ksp = (unsigned long) frame; | 131 | p->thread.ksp = (unsigned long) frame; |
161 | /* Store access registers to kernel stack of new process. */ | 132 | /* Save access registers to new thread structure. */ |
162 | frame->childregs = *regs; | 133 | save_access_regs(&p->thread.acrs[0]); |
163 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | 134 | /* start new process with ar4 pointing to the correct address space */ |
164 | frame->childregs.gprs[15] = new_stackp; | 135 | p->thread.mm_segment = get_fs(); |
165 | frame->sf.back_chain = 0; | 136 | /* Don't copy debug registers */ |
137 | memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); | ||
138 | memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); | ||
139 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); | ||
140 | clear_tsk_thread_flag(p, TIF_PER_TRAP); | ||
141 | /* Initialize per thread user and system timer values */ | ||
142 | ti = task_thread_info(p); | ||
143 | ti->user_timer = 0; | ||
144 | ti->system_timer = 0; | ||
166 | 145 | ||
146 | frame->sf.back_chain = 0; | ||
167 | /* new return point is ret_from_fork */ | 147 | /* new return point is ret_from_fork */ |
168 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; | 148 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; |
169 | |||
170 | /* fake return stack for resume(), don't go back to schedule */ | 149 | /* fake return stack for resume(), don't go back to schedule */ |
171 | frame->sf.gprs[9] = (unsigned long) frame; | 150 | frame->sf.gprs[9] = (unsigned long) frame; |
172 | 151 | ||
173 | /* Save access registers to new thread structure. */ | 152 | /* Store access registers to kernel stack of new process. */ |
174 | save_access_regs(&p->thread.acrs[0]); | 153 | if (unlikely(!regs)) { |
154 | /* kernel thread */ | ||
155 | memset(&frame->childregs, 0, sizeof(struct pt_regs)); | ||
156 | frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | | ||
157 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; | ||
158 | frame->childregs.psw.addr = PSW_ADDR_AMODE | | ||
159 | (unsigned long) kernel_thread_starter; | ||
160 | frame->childregs.gprs[9] = new_stackp; /* function */ | ||
161 | frame->childregs.gprs[10] = arg; | ||
162 | frame->childregs.gprs[11] = (unsigned long) do_exit; | ||
163 | frame->childregs.orig_gpr2 = -1; | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | frame->childregs = *regs; | ||
168 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | ||
169 | frame->childregs.gprs[15] = new_stackp; | ||
175 | 170 | ||
176 | /* Don't copy runtime instrumentation info */ | 171 | /* Don't copy runtime instrumentation info */ |
177 | p->thread.ri_cb = NULL; | 172 | p->thread.ri_cb = NULL; |
@@ -202,17 +197,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
202 | } | 197 | } |
203 | } | 198 | } |
204 | #endif /* CONFIG_64BIT */ | 199 | #endif /* CONFIG_64BIT */ |
205 | /* start new process with ar4 pointing to the correct address space */ | ||
206 | p->thread.mm_segment = get_fs(); | ||
207 | /* Don't copy debug registers */ | ||
208 | memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); | ||
209 | memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); | ||
210 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); | ||
211 | clear_tsk_thread_flag(p, TIF_PER_TRAP); | ||
212 | /* Initialize per thread user and system timer values */ | ||
213 | ti = task_thread_info(p); | ||
214 | ti->user_timer = 0; | ||
215 | ti->system_timer = 0; | ||
216 | return 0; | 200 | return 0; |
217 | } | 201 | } |
218 | 202 | ||
@@ -258,31 +242,6 @@ asmlinkage void execve_tail(void) | |||
258 | } | 242 | } |
259 | 243 | ||
260 | /* | 244 | /* |
261 | * sys_execve() executes a new program. | ||
262 | */ | ||
263 | SYSCALL_DEFINE3(execve, const char __user *, name, | ||
264 | const char __user *const __user *, argv, | ||
265 | const char __user *const __user *, envp) | ||
266 | { | ||
267 | struct pt_regs *regs = task_pt_regs(current); | ||
268 | char *filename; | ||
269 | long rc; | ||
270 | |||
271 | filename = getname(name); | ||
272 | rc = PTR_ERR(filename); | ||
273 | if (IS_ERR(filename)) | ||
274 | return rc; | ||
275 | rc = do_execve(filename, argv, envp, regs); | ||
276 | if (rc) | ||
277 | goto out; | ||
278 | execve_tail(); | ||
279 | rc = regs->gprs[2]; | ||
280 | out: | ||
281 | putname(filename); | ||
282 | return rc; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * fill in the FPU structure for a core dump. | 245 | * fill in the FPU structure for a core dump. |
287 | */ | 246 | */ |
288 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) | 247 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) |
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 7b673ddcd555..86eadceff097 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild | |||
@@ -7,6 +7,7 @@ generic-y += delay.h | |||
7 | generic-y += div64.h | 7 | generic-y += div64.h |
8 | generic-y += emergency-restart.h | 8 | generic-y += emergency-restart.h |
9 | generic-y += errno.h | 9 | generic-y += errno.h |
10 | generic-y += exec.h | ||
10 | generic-y += fcntl.h | 11 | generic-y += fcntl.h |
11 | generic-y += ioctl.h | 12 | generic-y += ioctl.h |
12 | generic-y += ipcbuf.h | 13 | generic-y += ipcbuf.h |
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h deleted file mode 100644 index 69486a9497f7..000000000000 --- a/arch/sh/include/asm/exec.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima | ||
3 | * Copyright (C) 2002 Paul Mundt | ||
4 | */ | ||
5 | #ifndef __ASM_SH_EXEC_H | ||
6 | #define __ASM_SH_EXEC_H | ||
7 | |||
8 | #define arch_align_stack(x) (x) | ||
9 | |||
10 | #endif /* __ASM_SH_EXEC_H */ | ||
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 61d41c11ee0a..10d54e5e37f5 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
5 | generic-y += div64.h | 5 | generic-y += div64.h |
6 | generic-y += exec.h | ||
6 | generic-y += local64.h | 7 | generic-y += local64.h |
7 | generic-y += irq_regs.h | 8 | generic-y += irq_regs.h |
8 | generic-y += local.h | 9 | generic-y += local.h |
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h deleted file mode 100644 index 2e085881e0d1..000000000000 --- a/arch/sparc/include/asm/exec.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __SPARC_EXEC_H | ||
2 | #define __SPARC_EXEC_H | ||
3 | |||
4 | #define arch_align_stack(x) (x) | ||
5 | |||
6 | #endif /* __SPARC_EXEC_H */ | ||
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index ea2e8ea3eb61..5cd98fac9899 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild | |||
@@ -13,6 +13,7 @@ generic-y += cputime.h | |||
13 | generic-y += div64.h | 13 | generic-y += div64.h |
14 | generic-y += emergency-restart.h | 14 | generic-y += emergency-restart.h |
15 | generic-y += errno.h | 15 | generic-y += errno.h |
16 | generic-y += exec.h | ||
16 | generic-y += fb.h | 17 | generic-y += fb.h |
17 | generic-y += fcntl.h | 18 | generic-y += fcntl.h |
18 | generic-y += ioctl.h | 19 | generic-y += ioctl.h |
diff --git a/arch/tile/include/asm/exec.h b/arch/tile/include/asm/exec.h deleted file mode 100644 index a714e1950867..000000000000 --- a/arch/tile/include/asm/exec.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef _ASM_TILE_EXEC_H | ||
16 | #define _ASM_TILE_EXEC_H | ||
17 | |||
18 | #define arch_align_stack(x) (x) | ||
19 | |||
20 | #endif /* _ASM_TILE_EXEC_H */ | ||
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 24e97be814bc..1e82e954e978 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h | |||
@@ -63,8 +63,6 @@ static inline void release_thread(struct task_struct *task) | |||
63 | { | 63 | { |
64 | } | 64 | } |
65 | 65 | ||
66 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
67 | |||
68 | extern unsigned long thread_saved_pc(struct task_struct *t); | 66 | extern unsigned long thread_saved_pc(struct task_struct *t); |
69 | 67 | ||
70 | static inline void mm_copy_segments(struct mm_struct *from_mm, | 68 | static inline void mm_copy_segments(struct mm_struct *from_mm, |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index de66c421ae9d..ab019c7f0b57 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <mem_user.h> | 16 | #include <mem_user.h> |
17 | #include <skas.h> | 17 | #include <skas.h> |
18 | #include <os.h> | 18 | #include <os.h> |
19 | #include "internal.h" | ||
20 | 19 | ||
21 | void flush_thread(void) | 20 | void flush_thread(void) |
22 | { | 21 | { |
@@ -49,27 +48,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
49 | } | 48 | } |
50 | EXPORT_SYMBOL(start_thread); | 49 | EXPORT_SYMBOL(start_thread); |
51 | 50 | ||
52 | long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) | 51 | void __noreturn ret_from_kernel_execve(struct pt_regs *unused) |
53 | { | 52 | { |
54 | long err; | 53 | UML_LONGJMP(current->thread.exec_buf, 1); |
55 | |||
56 | err = do_execve(file, argv, env, ¤t->thread.regs); | ||
57 | if (!err) | ||
58 | UML_LONGJMP(current->thread.exec_buf, 1); | ||
59 | return err; | ||
60 | } | ||
61 | |||
62 | long sys_execve(const char __user *file, const char __user *const __user *argv, | ||
63 | const char __user *const __user *env) | ||
64 | { | ||
65 | long error; | ||
66 | char *filename; | ||
67 | |||
68 | filename = getname(file); | ||
69 | error = PTR_ERR(filename); | ||
70 | if (IS_ERR(filename)) goto out; | ||
71 | error = do_execve(filename, argv, env, ¤t->thread.regs); | ||
72 | putname(filename); | ||
73 | out: | ||
74 | return error; | ||
75 | } | 54 | } |
diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h deleted file mode 100644 index 5bf97db24a04..000000000000 --- a/arch/um/kernel/internal.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env); | ||
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 41f53240e794..30629783b3e0 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -69,18 +69,6 @@ unsigned long alloc_stack(int order, int atomic) | |||
69 | return page; | 69 | return page; |
70 | } | 70 | } |
71 | 71 | ||
72 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
73 | { | ||
74 | int pid; | ||
75 | |||
76 | current->thread.request.u.thread.proc = fn; | ||
77 | current->thread.request.u.thread.arg = arg; | ||
78 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, | ||
79 | ¤t->thread.regs, 0, NULL, NULL); | ||
80 | return pid; | ||
81 | } | ||
82 | EXPORT_SYMBOL(kernel_thread); | ||
83 | |||
84 | static inline void set_current(struct task_struct *task) | 72 | static inline void set_current(struct task_struct *task) |
85 | { | 73 | { |
86 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) | 74 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) |
@@ -177,7 +165,7 @@ void fork_handler(void) | |||
177 | } | 165 | } |
178 | 166 | ||
179 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 167 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
180 | unsigned long stack_top, struct task_struct * p, | 168 | unsigned long arg, struct task_struct * p, |
181 | struct pt_regs *regs) | 169 | struct pt_regs *regs) |
182 | { | 170 | { |
183 | void (*handler)(void); | 171 | void (*handler)(void); |
@@ -198,7 +186,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
198 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 186 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
199 | } else { | 187 | } else { |
200 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); | 188 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); |
201 | p->thread.request.u.thread = current->thread.request.u.thread; | 189 | p->thread.request.u.thread.proc = (int (*)(void *))sp; |
190 | p->thread.request.u.thread.arg = (void *)arg; | ||
202 | handler = new_thread_handler; | 191 | handler = new_thread_handler; |
203 | } | 192 | } |
204 | 193 | ||
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 10808bda3671..a81f3705e90f 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/mman.h> | 13 | #include <asm/mman.h> |
14 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
15 | #include <asm/unistd.h> | 15 | #include <asm/unistd.h> |
16 | #include "internal.h" | ||
17 | 16 | ||
18 | long sys_fork(void) | 17 | long sys_fork(void) |
19 | { | 18 | { |
@@ -50,19 +49,3 @@ long old_mmap(unsigned long addr, unsigned long len, | |||
50 | out: | 49 | out: |
51 | return err; | 50 | return err; |
52 | } | 51 | } |
53 | |||
54 | int kernel_execve(const char *filename, | ||
55 | const char *const argv[], | ||
56 | const char *const envp[]) | ||
57 | { | ||
58 | mm_segment_t fs; | ||
59 | int ret; | ||
60 | |||
61 | fs = get_fs(); | ||
62 | set_fs(KERNEL_DS); | ||
63 | ret = um_execve(filename, (const char __user *const __user *)argv, | ||
64 | (const char __user *const __user *) envp); | ||
65 | set_fs(fs); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 123c59a06c14..c910c9857e11 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild | |||
@@ -11,6 +11,7 @@ generic-y += device.h | |||
11 | generic-y += div64.h | 11 | generic-y += div64.h |
12 | generic-y += emergency-restart.h | 12 | generic-y += emergency-restart.h |
13 | generic-y += errno.h | 13 | generic-y += errno.h |
14 | generic-y += exec.h | ||
14 | generic-y += fb.h | 15 | generic-y += fb.h |
15 | generic-y += fcntl.h | 16 | generic-y += fcntl.h |
16 | generic-y += ftrace.h | 17 | generic-y += ftrace.h |
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h deleted file mode 100644 index 06d1f0f57888..000000000000 --- a/arch/unicore32/include/asm/exec.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | /* | ||
2 | * Process execution bits for PKUnity SoC and UniCore ISA | ||
3 | * | ||
4 | * Copyright (C) 2001-2012 GUAN Xue-tao | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef __UNICORE_EXEC_H__ | ||
11 | #define __UNICORE_EXEC_H__ | ||
12 | |||
13 | #define arch_align_stack(x) (x) | ||
14 | |||
15 | #endif /* __UNICORE_EXEC_H__ */ | ||
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index 3afe60a39ac9..5fd9af773e15 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c | |||
@@ -104,7 +104,6 @@ int kernel_execve(const char *filename, | |||
104 | out: | 104 | out: |
105 | return ret; | 105 | return ret; |
106 | } | 106 | } |
107 | EXPORT_SYMBOL(kernel_execve); | ||
108 | 107 | ||
109 | /* Note: used by the compat code even in 64-bit Linux. */ | 108 | /* Note: used by the compat code even in 64-bit Linux. */ |
110 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, | 109 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1ae94bcae5d9..42d2c35a5bbd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -108,6 +108,7 @@ config X86 | |||
108 | select GENERIC_STRNLEN_USER | 108 | select GENERIC_STRNLEN_USER |
109 | select HAVE_RCU_USER_QS if X86_64 | 109 | select HAVE_RCU_USER_QS if X86_64 |
110 | select HAVE_IRQ_TIME_ACCOUNTING | 110 | select HAVE_IRQ_TIME_ACCOUNTING |
111 | select GENERIC_KERNEL_THREAD | ||
111 | 112 | ||
112 | config INSTRUCTION_DECODER | 113 | config INSTRUCTION_DECODER |
113 | def_bool y | 114 | def_bool y |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 9c289504e680..076745fc8045 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -465,7 +465,7 @@ GLOBAL(\label) | |||
465 | PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi | 465 | PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi |
466 | PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi | 466 | PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi |
467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx | 467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx |
468 | PTREGSCALL stub32_execve, sys32_execve, %rcx | 468 | PTREGSCALL stub32_execve, compat_sys_execve, %rcx |
469 | PTREGSCALL stub32_fork, sys_fork, %rdi | 469 | PTREGSCALL stub32_fork, sys_fork, %rdi |
470 | PTREGSCALL stub32_clone, sys32_clone, %rdx | 470 | PTREGSCALL stub32_clone, sys32_clone, %rdx |
471 | PTREGSCALL stub32_vfork, sys_vfork, %rdi | 471 | PTREGSCALL stub32_vfork, sys_vfork, %rdi |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index c5b938d92eab..86d68d1c8806 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -385,21 +385,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, | |||
385 | return ret; | 385 | return ret; |
386 | } | 386 | } |
387 | 387 | ||
388 | asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv, | ||
389 | compat_uptr_t __user *envp, struct pt_regs *regs) | ||
390 | { | ||
391 | long error; | ||
392 | char *filename; | ||
393 | |||
394 | filename = getname(name); | ||
395 | error = PTR_ERR(filename); | ||
396 | if (IS_ERR(filename)) | ||
397 | return error; | ||
398 | error = compat_do_execve(filename, argv, envp, regs); | ||
399 | putname(filename); | ||
400 | return error; | ||
401 | } | ||
402 | |||
403 | asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, | 388 | asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, |
404 | struct pt_regs *regs) | 389 | struct pt_regs *regs) |
405 | { | 390 | { |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b98c0d958ebb..ad1fc8511674 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -588,11 +588,6 @@ typedef struct { | |||
588 | } mm_segment_t; | 588 | } mm_segment_t; |
589 | 589 | ||
590 | 590 | ||
591 | /* | ||
592 | * create a kernel thread without removing it from tasklists | ||
593 | */ | ||
594 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
595 | |||
596 | /* Free all resources held by a thread. */ | 591 | /* Free all resources held by a thread. */ |
597 | extern void release_thread(struct task_struct *); | 592 | extern void release_thread(struct task_struct *); |
598 | 593 | ||
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 4ca1c611b552..a9a8cf3da49d 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h | |||
@@ -54,8 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32); | |||
54 | asmlinkage long sys32_personality(unsigned long); | 54 | asmlinkage long sys32_personality(unsigned long); |
55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); | 55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); |
56 | 56 | ||
57 | asmlinkage long sys32_execve(const char __user *, compat_uptr_t __user *, | ||
58 | compat_uptr_t __user *, struct pt_regs *); | ||
59 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); | 57 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); |
60 | 58 | ||
61 | long sys32_lseek(unsigned int, int, unsigned int); | 59 | long sys32_lseek(unsigned int, int, unsigned int); |
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index f1d8b441fc77..2be0b880417e 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -25,7 +25,7 @@ int sys_fork(struct pt_regs *); | |||
25 | int sys_vfork(struct pt_regs *); | 25 | int sys_vfork(struct pt_regs *); |
26 | long sys_execve(const char __user *, | 26 | long sys_execve(const char __user *, |
27 | const char __user *const __user *, | 27 | const char __user *const __user *, |
28 | const char __user *const __user *, struct pt_regs *); | 28 | const char __user *const __user *); |
29 | long sys_clone(unsigned long, unsigned long, void __user *, | 29 | long sys_clone(unsigned long, unsigned long, void __user *, |
30 | void __user *, struct pt_regs *); | 30 | void __user *, struct pt_regs *); |
31 | 31 | ||
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index c535d847e3b5..2d946e63ee82 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -79,7 +79,6 @@ struct thread_info { | |||
79 | #define TIF_SIGPENDING 2 /* signal pending */ | 79 | #define TIF_SIGPENDING 2 /* signal pending */ |
80 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | 80 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ |
81 | #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ | 81 | #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ |
82 | #define TIF_IRET 5 /* force IRET */ | ||
83 | #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ | 82 | #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ |
84 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ | 83 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ |
85 | #define TIF_SECCOMP 8 /* secure computing */ | 84 | #define TIF_SECCOMP 8 /* secure computing */ |
@@ -105,7 +104,6 @@ struct thread_info { | |||
105 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 104 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
106 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) | 105 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) |
107 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 106 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
108 | #define _TIF_IRET (1 << TIF_IRET) | ||
109 | #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) | 107 | #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) |
110 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 108 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
111 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 109 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 0d9776e9e2dc..55d155560fdf 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h | |||
@@ -50,6 +50,8 @@ | |||
50 | # define __ARCH_WANT_SYS_TIME | 50 | # define __ARCH_WANT_SYS_TIME |
51 | # define __ARCH_WANT_SYS_UTIME | 51 | # define __ARCH_WANT_SYS_UTIME |
52 | # define __ARCH_WANT_SYS_WAITPID | 52 | # define __ARCH_WANT_SYS_WAITPID |
53 | # define __ARCH_WANT_SYS_EXECVE | ||
54 | # define __ARCH_WANT_KERNEL_EXECVE | ||
53 | 55 | ||
54 | /* | 56 | /* |
55 | * "Conditional" syscalls | 57 | * "Conditional" syscalls |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index a48ea05157d3..91ce48f05f9f 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -23,7 +23,7 @@ obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o | |||
23 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o | 23 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o |
24 | obj-$(CONFIG_IRQ_WORK) += irq_work.o | 24 | obj-$(CONFIG_IRQ_WORK) += irq_work.o |
25 | obj-y += probe_roms.o | 25 | obj-y += probe_roms.o |
26 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o | 26 | obj-$(CONFIG_X86_32) += i386_ksyms_32.o |
27 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | 27 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o |
28 | obj-y += syscall_$(BITS).o | 28 | obj-y += syscall_$(BITS).o |
29 | obj-$(CONFIG_X86_64) += vsyscall_64.o | 29 | obj-$(CONFIG_X86_64) += vsyscall_64.o |
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index 68de2dc962ec..28610822fb3c 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c | |||
@@ -69,4 +69,7 @@ void common(void) { | |||
69 | OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); | 69 | OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); |
70 | OFFSET(BP_pref_address, boot_params, hdr.pref_address); | 70 | OFFSET(BP_pref_address, boot_params, hdr.pref_address); |
71 | OFFSET(BP_code32_start, boot_params, hdr.code32_start); | 71 | OFFSET(BP_code32_start, boot_params, hdr.code32_start); |
72 | |||
73 | BLANK(); | ||
74 | DEFINE(PTREGS_SIZE, sizeof(struct pt_regs)); | ||
72 | } | 75 | } |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 0750e3ba87c0..8f9ed1afde8f 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -299,6 +299,13 @@ ENTRY(ret_from_fork) | |||
299 | CFI_ENDPROC | 299 | CFI_ENDPROC |
300 | END(ret_from_fork) | 300 | END(ret_from_fork) |
301 | 301 | ||
302 | ENTRY(ret_from_kernel_execve) | ||
303 | movl %eax, %esp | ||
304 | movl $0,PT_EAX(%esp) | ||
305 | GET_THREAD_INFO(%ebp) | ||
306 | jmp syscall_exit | ||
307 | END(ret_from_kernel_execve) | ||
308 | |||
302 | /* | 309 | /* |
303 | * Interrupt exit functions should be protected against kprobes | 310 | * Interrupt exit functions should be protected against kprobes |
304 | */ | 311 | */ |
@@ -323,8 +330,7 @@ ret_from_intr: | |||
323 | andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax | 330 | andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax |
324 | #else | 331 | #else |
325 | /* | 332 | /* |
326 | * We can be coming here from a syscall done in the kernel space, | 333 | * We can be coming here from child spawned by kernel_thread(). |
327 | * e.g. a failed kernel_execve(). | ||
328 | */ | 334 | */ |
329 | movl PT_CS(%esp), %eax | 335 | movl PT_CS(%esp), %eax |
330 | andl $SEGMENT_RPL_MASK, %eax | 336 | andl $SEGMENT_RPL_MASK, %eax |
@@ -732,7 +738,6 @@ ENDPROC(ptregs_##name) | |||
732 | PTREGSCALL1(iopl) | 738 | PTREGSCALL1(iopl) |
733 | PTREGSCALL0(fork) | 739 | PTREGSCALL0(fork) |
734 | PTREGSCALL0(vfork) | 740 | PTREGSCALL0(vfork) |
735 | PTREGSCALL3(execve) | ||
736 | PTREGSCALL2(sigaltstack) | 741 | PTREGSCALL2(sigaltstack) |
737 | PTREGSCALL0(sigreturn) | 742 | PTREGSCALL0(sigreturn) |
738 | PTREGSCALL0(rt_sigreturn) | 743 | PTREGSCALL0(rt_sigreturn) |
@@ -1015,15 +1020,20 @@ END(spurious_interrupt_bug) | |||
1015 | */ | 1020 | */ |
1016 | .popsection | 1021 | .popsection |
1017 | 1022 | ||
1018 | ENTRY(kernel_thread_helper) | 1023 | ENTRY(ret_from_kernel_thread) |
1019 | pushl $0 # fake return address for unwinder | ||
1020 | CFI_STARTPROC | 1024 | CFI_STARTPROC |
1021 | movl %edi,%eax | 1025 | pushl_cfi %eax |
1022 | call *%esi | 1026 | call schedule_tail |
1027 | GET_THREAD_INFO(%ebp) | ||
1028 | popl_cfi %eax | ||
1029 | pushl_cfi $0x0202 # Reset kernel eflags | ||
1030 | popfl_cfi | ||
1031 | movl PT_EBP(%esp),%eax | ||
1032 | call *PT_EBX(%esp) | ||
1023 | call do_exit | 1033 | call do_exit |
1024 | ud2 # padding for call trace | 1034 | ud2 # padding for call trace |
1025 | CFI_ENDPROC | 1035 | CFI_ENDPROC |
1026 | ENDPROC(kernel_thread_helper) | 1036 | ENDPROC(ret_from_kernel_thread) |
1027 | 1037 | ||
1028 | #ifdef CONFIG_XEN | 1038 | #ifdef CONFIG_XEN |
1029 | /* Xen doesn't set %esp to be precisely what the normal sysenter | 1039 | /* Xen doesn't set %esp to be precisely what the normal sysenter |
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) |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index dc3567e083f9..b644e1c765dc 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -293,71 +293,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
293 | } | 293 | } |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * This gets run with %si containing the | ||
297 | * function to call, and %di containing | ||
298 | * the "args". | ||
299 | */ | ||
300 | extern void kernel_thread_helper(void); | ||
301 | |||
302 | /* | ||
303 | * Create a kernel thread | ||
304 | */ | ||
305 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
306 | { | ||
307 | struct pt_regs regs; | ||
308 | |||
309 | memset(®s, 0, sizeof(regs)); | ||
310 | |||
311 | regs.si = (unsigned long) fn; | ||
312 | regs.di = (unsigned long) arg; | ||
313 | |||
314 | #ifdef CONFIG_X86_32 | ||
315 | regs.ds = __USER_DS; | ||
316 | regs.es = __USER_DS; | ||
317 | regs.fs = __KERNEL_PERCPU; | ||
318 | regs.gs = __KERNEL_STACK_CANARY; | ||
319 | #else | ||
320 | regs.ss = __KERNEL_DS; | ||
321 | #endif | ||
322 | |||
323 | regs.orig_ax = -1; | ||
324 | regs.ip = (unsigned long) kernel_thread_helper; | ||
325 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
326 | regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
327 | |||
328 | /* Ok, create the new process.. */ | ||
329 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
330 | } | ||
331 | EXPORT_SYMBOL(kernel_thread); | ||
332 | |||
333 | /* | ||
334 | * sys_execve() executes a new program. | ||
335 | */ | ||
336 | long sys_execve(const char __user *name, | ||
337 | const char __user *const __user *argv, | ||
338 | const char __user *const __user *envp, struct pt_regs *regs) | ||
339 | { | ||
340 | long error; | ||
341 | char *filename; | ||
342 | |||
343 | filename = getname(name); | ||
344 | error = PTR_ERR(filename); | ||
345 | if (IS_ERR(filename)) | ||
346 | return error; | ||
347 | error = do_execve(filename, argv, envp, regs); | ||
348 | |||
349 | #ifdef CONFIG_X86_32 | ||
350 | if (error == 0) { | ||
351 | /* Make sure we don't return using sysenter.. */ | ||
352 | set_thread_flag(TIF_IRET); | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | putname(filename); | ||
357 | return error; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Idle related variables and functions | 296 | * Idle related variables and functions |
362 | */ | 297 | */ |
363 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; | 298 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index b9ff83c7135b..44e0bff38e72 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <asm/switch_to.h> | 57 | #include <asm/switch_to.h> |
58 | 58 | ||
59 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 59 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
60 | asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); | ||
60 | 61 | ||
61 | /* | 62 | /* |
62 | * Return saved PC of a blocked thread. | 63 | * Return saved PC of a blocked thread. |
@@ -127,23 +128,39 @@ void release_thread(struct task_struct *dead_task) | |||
127 | } | 128 | } |
128 | 129 | ||
129 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
130 | unsigned long unused, | 131 | unsigned long arg, |
131 | struct task_struct *p, struct pt_regs *regs) | 132 | struct task_struct *p, struct pt_regs *regs) |
132 | { | 133 | { |
133 | struct pt_regs *childregs; | 134 | struct pt_regs *childregs = task_pt_regs(p); |
134 | struct task_struct *tsk; | 135 | struct task_struct *tsk; |
135 | int err; | 136 | int err; |
136 | 137 | ||
137 | childregs = task_pt_regs(p); | 138 | p->thread.sp = (unsigned long) childregs; |
139 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
140 | |||
141 | if (unlikely(!regs)) { | ||
142 | /* kernel thread */ | ||
143 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
144 | p->thread.ip = (unsigned long) ret_from_kernel_thread; | ||
145 | task_user_gs(p) = __KERNEL_STACK_CANARY; | ||
146 | childregs->ds = __USER_DS; | ||
147 | childregs->es = __USER_DS; | ||
148 | childregs->fs = __KERNEL_PERCPU; | ||
149 | childregs->bx = sp; /* function */ | ||
150 | childregs->bp = arg; | ||
151 | childregs->orig_ax = -1; | ||
152 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | ||
153 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
154 | p->fpu_counter = 0; | ||
155 | p->thread.io_bitmap_ptr = NULL; | ||
156 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
157 | return 0; | ||
158 | } | ||
138 | *childregs = *regs; | 159 | *childregs = *regs; |
139 | childregs->ax = 0; | 160 | childregs->ax = 0; |
140 | childregs->sp = sp; | 161 | childregs->sp = sp; |
141 | 162 | ||
142 | p->thread.sp = (unsigned long) childregs; | ||
143 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
144 | |||
145 | p->thread.ip = (unsigned long) ret_from_fork; | 163 | p->thread.ip = (unsigned long) ret_from_fork; |
146 | |||
147 | task_user_gs(p) = get_user_gs(regs); | 164 | task_user_gs(p) = get_user_gs(regs); |
148 | 165 | ||
149 | p->fpu_counter = 0; | 166 | p->fpu_counter = 0; |
@@ -190,6 +207,12 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
190 | regs->cs = __USER_CS; | 207 | regs->cs = __USER_CS; |
191 | regs->ip = new_ip; | 208 | regs->ip = new_ip; |
192 | regs->sp = new_sp; | 209 | regs->sp = new_sp; |
210 | regs->flags = X86_EFLAGS_IF; | ||
211 | /* | ||
212 | * force it to the iret return path by making it look as if there was | ||
213 | * some work pending. | ||
214 | */ | ||
215 | set_thread_flag(TIF_NOTIFY_RESUME); | ||
193 | } | 216 | } |
194 | EXPORT_SYMBOL_GPL(start_thread); | 217 | EXPORT_SYMBOL_GPL(start_thread); |
195 | 218 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 8a6d20ce1978..16c6365e2b86 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
149 | unsigned long unused, | 149 | unsigned long arg, |
150 | struct task_struct *p, struct pt_regs *regs) | 150 | struct task_struct *p, struct pt_regs *regs) |
151 | { | 151 | { |
152 | int err; | 152 | int err; |
153 | struct pt_regs *childregs; | 153 | struct pt_regs *childregs; |
154 | struct task_struct *me = current; | 154 | struct task_struct *me = current; |
155 | 155 | ||
156 | childregs = ((struct pt_regs *) | 156 | p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE; |
157 | (THREAD_SIZE + task_stack_page(p))) - 1; | 157 | childregs = task_pt_regs(p); |
158 | *childregs = *regs; | ||
159 | |||
160 | childregs->ax = 0; | ||
161 | if (user_mode(regs)) | ||
162 | childregs->sp = sp; | ||
163 | else | ||
164 | childregs->sp = (unsigned long)childregs; | ||
165 | |||
166 | p->thread.sp = (unsigned long) childregs; | 158 | p->thread.sp = (unsigned long) childregs; |
167 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
168 | p->thread.usersp = me->thread.usersp; | 159 | p->thread.usersp = me->thread.usersp; |
169 | |||
170 | set_tsk_thread_flag(p, TIF_FORK); | 160 | set_tsk_thread_flag(p, TIF_FORK); |
171 | |||
172 | p->fpu_counter = 0; | 161 | p->fpu_counter = 0; |
173 | p->thread.io_bitmap_ptr = NULL; | 162 | p->thread.io_bitmap_ptr = NULL; |
174 | 163 | ||
@@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
178 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; | 167 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; |
179 | savesegment(es, p->thread.es); | 168 | savesegment(es, p->thread.es); |
180 | savesegment(ds, p->thread.ds); | 169 | savesegment(ds, p->thread.ds); |
170 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
171 | |||
172 | if (unlikely(!regs)) { | ||
173 | /* kernel thread */ | ||
174 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
175 | childregs->sp = (unsigned long)childregs; | ||
176 | childregs->ss = __KERNEL_DS; | ||
177 | childregs->bx = sp; /* function */ | ||
178 | childregs->bp = arg; | ||
179 | childregs->orig_ax = -1; | ||
180 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | ||
181 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
182 | return 0; | ||
183 | } | ||
184 | *childregs = *regs; | ||
185 | |||
186 | childregs->ax = 0; | ||
187 | childregs->sp = sp; | ||
181 | 188 | ||
182 | err = -ENOMEM; | 189 | err = -ENOMEM; |
183 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 190 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index b33144c8b309..29ad351804e9 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -840,10 +840,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
840 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) | 840 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) |
841 | fire_user_return_notifiers(); | 841 | fire_user_return_notifiers(); |
842 | 842 | ||
843 | #ifdef CONFIG_X86_32 | ||
844 | clear_thread_flag(TIF_IRET); | ||
845 | #endif /* CONFIG_X86_32 */ | ||
846 | |||
847 | rcu_user_enter(); | 843 | rcu_user_enter(); |
848 | } | 844 | } |
849 | 845 | ||
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c deleted file mode 100644 index 0b0cb5fede19..000000000000 --- a/arch/x86/kernel/sys_i386_32.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * This file contains various random system calls that | ||
3 | * have a non-standard calling sequence on the Linux/i386 | ||
4 | * platform. | ||
5 | */ | ||
6 | |||
7 | #include <linux/errno.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/fs.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <linux/sem.h> | ||
13 | #include <linux/msg.h> | ||
14 | #include <linux/shm.h> | ||
15 | #include <linux/stat.h> | ||
16 | #include <linux/syscalls.h> | ||
17 | #include <linux/mman.h> | ||
18 | #include <linux/file.h> | ||
19 | #include <linux/utsname.h> | ||
20 | #include <linux/ipc.h> | ||
21 | |||
22 | #include <linux/uaccess.h> | ||
23 | #include <linux/unistd.h> | ||
24 | |||
25 | #include <asm/syscalls.h> | ||
26 | |||
27 | /* | ||
28 | * Do a system call from kernel instead of calling sys_execve so we | ||
29 | * end up with proper pt_regs. | ||
30 | */ | ||
31 | int kernel_execve(const char *filename, | ||
32 | const char *const argv[], | ||
33 | const char *const envp[]) | ||
34 | { | ||
35 | long __res; | ||
36 | asm volatile ("int $0x80" | ||
37 | : "=a" (__res) | ||
38 | : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory"); | ||
39 | return __res; | ||
40 | } | ||
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 54abcc0baf23..5c9687b1bde6 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
@@ -561,9 +561,9 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno) | |||
561 | if ((trapno == 3) || (trapno == 1)) { | 561 | if ((trapno == 3) || (trapno == 1)) { |
562 | KVM86->regs32->ax = VM86_TRAP + (trapno << 8); | 562 | KVM86->regs32->ax = VM86_TRAP + (trapno << 8); |
563 | /* setting this flag forces the code in entry_32.S to | 563 | /* setting this flag forces the code in entry_32.S to |
564 | call save_v86_state() and change the stack pointer | 564 | the path where we call save_v86_state() and change |
565 | to KVM86->regs32 */ | 565 | the stack pointer to KVM86->regs32 */ |
566 | set_thread_flag(TIF_IRET); | 566 | set_thread_flag(TIF_NOTIFY_RESUME); |
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); | 569 | do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); |
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index 7a35a6e71d44..a47103fbc692 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
@@ -17,7 +17,7 @@ | |||
17 | 8 i386 creat sys_creat | 17 | 8 i386 creat sys_creat |
18 | 9 i386 link sys_link | 18 | 9 i386 link sys_link |
19 | 10 i386 unlink sys_unlink | 19 | 10 i386 unlink sys_unlink |
20 | 11 i386 execve ptregs_execve stub32_execve | 20 | 11 i386 execve sys_execve stub32_execve |
21 | 12 i386 chdir sys_chdir | 21 | 12 i386 chdir sys_chdir |
22 | 13 i386 time sys_time compat_sys_time | 22 | 13 i386 time sys_time compat_sys_time |
23 | 14 i386 mknod sys_mknod | 23 | 14 i386 mknod sys_mknod |
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig index aeaff8bef2f1..30c4eec033af 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
@@ -13,6 +13,7 @@ endmenu | |||
13 | config UML_X86 | 13 | config UML_X86 |
14 | def_bool y | 14 | def_bool y |
15 | select GENERIC_FIND_FIRST_BIT | 15 | select GENERIC_FIND_FIRST_BIT |
16 | select GENERIC_KERNEL_THREAD | ||
16 | 17 | ||
17 | config 64BIT | 18 | config 64BIT |
18 | bool "64-bit kernel" if SUBARCH = "x86" | 19 | bool "64-bit kernel" if SUBARCH = "x86" |
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index b5408cecac6c..232e60504b3a 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #define old_mmap sys_old_mmap | 25 | #define old_mmap sys_old_mmap |
26 | 26 | ||
27 | #define ptregs_fork sys_fork | 27 | #define ptregs_fork sys_fork |
28 | #define ptregs_execve sys_execve | ||
29 | #define ptregs_iopl sys_iopl | 28 | #define ptregs_iopl sys_iopl |
30 | #define ptregs_vm86old sys_vm86old | 29 | #define ptregs_vm86old sys_vm86old |
31 | #define ptregs_clone i386_clone | 30 | #define ptregs_clone i386_clone |
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 0d20f5526dd8..fccd81eddff1 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | ||
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h deleted file mode 100644 index af949e28cb32..000000000000 --- a/arch/xtensa/include/asm/exec.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
7 | */ | ||
8 | |||
9 | #ifndef _XTENSA_EXEC_H | ||
10 | #define _XTENSA_EXEC_H | ||
11 | |||
12 | #define arch_align_stack(x) (x) | ||
13 | |||
14 | #endif /* _XTENSA_EXEC_H */ | ||