aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 23:02:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 23:02:25 -0400
commit42859eea96ba6beabfb0369a1eeffa3c7d2bd9cb (patch)
treefa38aeda0d6e7a4c48a882b166b8643594a1ad50
parentf59b51fe3d3092c08d7d554ecb40db24011b2ebc (diff)
parentf322220d6159455da2b5a8a596d802c8695fed30 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull generic execve() changes from Al Viro: "This introduces the generic kernel_thread() and kernel_execve() functions, and switches x86, arm, alpha, um and s390 over to them." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (26 commits) s390: convert to generic kernel_execve() s390: switch to generic kernel_thread() s390: fold kernel_thread_helper() into ret_from_fork() s390: fold execve_tail() into start_thread(), convert to generic sys_execve() um: switch to generic kernel_thread() x86, um/x86: switch to generic sys_execve and kernel_execve x86: split ret_from_fork alpha: introduce ret_from_kernel_execve(), switch to generic kernel_execve() alpha: switch to generic kernel_thread() alpha: switch to generic sys_execve() arm: get rid of execve wrapper, switch to generic execve() implementation arm: optimized current_pt_regs() arm: introduce ret_from_kernel_execve(), switch to generic kernel_execve() arm: split ret_from_fork, simplify kernel_thread() [based on patch by rmk] generic sys_execve() generic kernel_execve() new helper: current_pt_regs() preparation for generic kernel_thread() um: kill thread->forking um: let signal_delivered() do SIGTRAP on singlestepping into handler ...
-rw-r--r--arch/Kconfig3
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/alpha/include/asm/Kbuild1
-rw-r--r--arch/alpha/include/asm/exec.h6
-rw-r--r--arch/alpha/include/asm/processor.h3
-rw-r--r--arch/alpha/include/asm/unistd.h2
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c3
-rw-r--r--arch/alpha/kernel/entry.S69
-rw-r--r--arch/alpha/kernel/process.c79
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/include/asm/processor.h5
-rw-r--r--arch/arm/include/asm/ptrace.h5
-rw-r--r--arch/arm/include/asm/system.h1
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S29
-rw-r--r--arch/arm/kernel/process.c75
-rw-r--r--arch/arm/kernel/sys_arm.c63
-rw-r--r--arch/avr32/include/asm/Kbuild1
-rw-r--r--arch/avr32/include/asm/exec.h13
-rw-r--r--arch/c6x/include/asm/Kbuild1
-rw-r--r--arch/c6x/include/asm/exec.h6
-rw-r--r--arch/cris/include/asm/Kbuild1
-rw-r--r--arch/cris/include/asm/exec.h6
-rw-r--r--arch/frv/include/asm/Kbuild1
-rw-r--r--arch/frv/include/asm/exec.h17
-rw-r--r--arch/h8300/include/asm/Kbuild3
-rw-r--r--arch/h8300/include/asm/exec.h6
-rw-r--r--arch/hexagon/kernel/syscall.c1
-rw-r--r--arch/ia64/include/asm/Kbuild1
-rw-r--r--arch/ia64/include/asm/exec.h14
-rw-r--r--arch/m32r/include/asm/Kbuild3
-rw-r--r--arch/m32r/include/asm/exec.h14
-rw-r--r--arch/m68k/include/asm/Kbuild1
-rw-r--r--arch/m68k/include/asm/exec.h6
-rw-r--r--arch/microblaze/include/asm/Kbuild1
-rw-r--r--arch/microblaze/include/asm/exec.h14
-rw-r--r--arch/mn10300/include/asm/Kbuild1
-rw-r--r--arch/mn10300/include/asm/exec.h16
-rw-r--r--arch/parisc/include/asm/Kbuild1
-rw-r--r--arch/parisc/include/asm/exec.h6
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/include/asm/processor.h4
-rw-r--r--arch/s390/include/asm/unistd.h2
-rw-r--r--arch/s390/kernel/compat_linux.c26
-rw-r--r--arch/s390/kernel/compat_linux.h2
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/s390/kernel/entry.S51
-rw-r--r--arch/s390/kernel/entry.h3
-rw-r--r--arch/s390/kernel/entry64.S50
-rw-r--r--arch/s390/kernel/process.c107
-rw-r--r--arch/sh/include/asm/Kbuild1
-rw-r--r--arch/sh/include/asm/exec.h10
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/exec.h6
-rw-r--r--arch/tile/include/asm/Kbuild1
-rw-r--r--arch/tile/include/asm/exec.h20
-rw-r--r--arch/um/include/asm/processor-generic.h2
-rw-r--r--arch/um/kernel/exec.c25
-rw-r--r--arch/um/kernel/internal.h1
-rw-r--r--arch/um/kernel/process.c17
-rw-r--r--arch/um/kernel/syscall.c17
-rw-r--r--arch/unicore32/include/asm/Kbuild1
-rw-r--r--arch/unicore32/include/asm/exec.h15
-rw-r--r--arch/unicore32/kernel/sys.c1
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/ia32/sys_ia32.c15
-rw-r--r--arch/x86/include/asm/processor.h5
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--arch/x86/include/asm/syscalls.h2
-rw-r--r--arch/x86/include/asm/thread_info.h2
-rw-r--r--arch/x86/include/asm/unistd.h2
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/asm-offsets.c3
-rw-r--r--arch/x86/kernel/entry_32.S26
-rw-r--r--arch/x86/kernel/entry_64.S74
-rw-r--r--arch/x86/kernel/process.c65
-rw-r--r--arch/x86/kernel/process_32.c37
-rw-r--r--arch/x86/kernel/process_64.c35
-rw-r--r--arch/x86/kernel/signal.c4
-rw-r--r--arch/x86/kernel/sys_i386_32.c40
-rw-r--r--arch/x86/kernel/vm86_32.c6
-rw-r--r--arch/x86/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/um/Kconfig1
-rw-r--r--arch/x86/um/sys_call_table_32.c1
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--arch/xtensa/include/asm/exec.h14
-rw-r--r--fs/binfmt_elf.c1
-rw-r--r--fs/binfmt_elf_fdpic.c1
-rw-r--r--fs/exec.c61
-rw-r--r--include/linux/binfmts.h6
-rw-r--r--include/linux/compat.h8
-rw-r--r--include/linux/ptrace.h4
-rw-r--r--include/linux/sched.h3
-rw-r--r--kernel/fork.c13
96 files changed, 390 insertions, 899 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
274config GENERIC_KERNEL_THREAD
275 bool
276
274config HAVE_ARCH_SECCOMP_FILTER 277config 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
10header-y += reg.h 10header-y += reg.h
11header-y += regdef.h 11header-y += regdef.h
12header-y += sysinfo.h 12header-y += sysinfo.h
13generic-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. */
50extern void release_thread(struct task_struct *); 50extern void release_thread(struct task_struct *);
51 51
52/* Create a kernel thread without removing it from tasklists. */
53extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
54
55unsigned long get_wchan(struct task_struct *p); 52unsigned 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);
50EXPORT_SYMBOL(alpha_write_fp_reg); 50EXPORT_SYMBOL(alpha_write_fp_reg);
51EXPORT_SYMBOL(alpha_write_fp_reg_s); 51EXPORT_SYMBOL(alpha_write_fp_reg_s);
52 52
53/* entry.S */
54EXPORT_SYMBOL(kernel_thread);
55
56/* Networking helper routines. */ 53/* Networking helper routines. */
57EXPORT_SYMBOL(csum_tcpudp_magic); 54EXPORT_SYMBOL(csum_tcpudp_magic);
58EXPORT_SYMBOL(ip_compute_csum); 55EXPORT_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
617kernel_thread: 617ret_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
6371: ret /* in parent. */ 629 .globl ret_from_kernel_execve
638 630 .align 4
639 .align 4 631 .ent ret_from_kernel_execve
6402: /* Fake a system call stack frame, as we can't do system calls 632ret_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
750sys_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
759alpha_ni_syscall: 726alpha_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
275int 268int
276copy_thread(unsigned long clone_flags, unsigned long usp, 269copy_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)
386EXPORT_SYMBOL(dump_elf_task_fp); 387EXPORT_SYMBOL(dump_elf_task_fp);
387 388
388/* 389/*
389 * sys_execve() executes a new program.
390 */
391asmlinkage int
392do_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);
405out:
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
463int 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, &regs);
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}
480EXPORT_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 */
91extern 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
92ENDPROC(ret_from_fork) 92ENDPROC(ret_from_fork)
93 93
94ENTRY(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
1011: bl do_exit
102 nop
103 UNWIND(.fnend)
104ENDPROC(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 */
110ENTRY(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
116ENDPROC(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
518ENDPROC(sys_vfork_wrapper) 542ENDPROC(sys_vfork_wrapper)
519 543
520sys_execve_wrapper:
521 add r3, sp, #S_OFF
522 b sys_execve
523ENDPROC(sys_execve_wrapper)
524
525sys_clone_wrapper: 544sys_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
375asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 375asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
376asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
376 377
377int 378int
378copy_thread(unsigned long clone_flags, unsigned long stack_start, 379copy_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}
424EXPORT_SYMBOL(dump_fpu); 432EXPORT_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 */
431extern void kernel_thread_helper(void);
432asm( ".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
447extern void kernel_thread_exit(long code);
448asm( ".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 */
466pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
467{
468 struct pt_regs regs;
469
470 memset(&regs, 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, &regs, 0, NULL, NULL);
480}
481EXPORT_SYMBOL(kernel_thread);
482
483unsigned long get_wchan(struct task_struct *p) 434unsigned 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 */
65asmlinkage 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);
78out:
79 return error;
80}
81
82int 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(&regs, 0, sizeof(struct pt_regs));
90 ret = do_execve(filename,
91 (const char __user *const __user *)argv,
92 (const char __user *const __user *)envp, &regs);
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" (&regs),
117 "Ir" (sizeof(regs))
118 : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
119
120 out:
121 return ret;
122}
123EXPORT_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 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-y += exec.h
4 5
5header-y += cachectl.h 6header-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
12generic-y += dma.h 12generic-y += dma.h
13generic-y += emergency-restart.h 13generic-y += emergency-restart.h
14generic-y += errno.h 14generic-y += errno.h
15generic-y += exec.h
15generic-y += fb.h 16generic-y += fb.h
16generic-y += fcntl.h 17generic-y += fcntl.h
17generic-y += futex.h 18generic-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
9header-y += sync_serial.h 9header-y += sync_serial.h
10 10
11generic-y += clkdev.h 11generic-y += clkdev.h
12generic-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
3header-y += registers.h 3header-y += registers.h
4header-y += termios.h 4header-y += termios.h
5generic-y += clkdev.h 5generic-y += clkdev.h
6generic-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 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-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}
90EXPORT_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
14header-y += ucontext.h 14header-y += ucontext.h
15header-y += ustack.h 15header-y += ustack.h
16generic-y += clkdev.h 16generic-y += clkdev.h
17generic-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 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-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
7generic-y += device.h 7generic-y += device.h
8generic-y += emergency-restart.h 8generic-y += emergency-restart.h
9generic-y += errno.h 9generic-y += errno.h
10generic-y += exec.h
10generic-y += futex.h 11generic-y += futex.h
11generic-y += ioctl.h 12generic-y += ioctl.h
12generic-y += ipcbuf.h 13generic-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
3header-y += elf.h 3header-y += elf.h
4generic-y += clkdev.h 4generic-y += clkdev.h
5generic-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 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-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
3header-y += pdc.h 3header-y += pdc.h
4generic-y += clkdev.h 4generic-y += clkdev.h
5generic-y += word-at-a-time.h 5generic-y += word-at-a-time.h
6generic-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
139config SCHED_OMIT_FRAME_POINTER 140config 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)
35extern void s390_adjust_jiffies(void); 35extern void s390_adjust_jiffies(void);
36extern const struct seq_operations cpuinfo_op; 36extern const struct seq_operations cpuinfo_op;
37extern int sysctl_ieee_emulation_warnings; 37extern int sysctl_ieee_emulation_warnings;
38extern 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. */
152extern void release_thread(struct task_struct *); 155extern void release_thread(struct task_struct *);
153extern 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 */
439asmlinkage 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];
456out:
457 putname(filename);
458 return rc;
459}
460
461asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 435asmlinkage 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);
126long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); 126long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
127long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); 127long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
128long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
129 compat_uptr_t __user *envp);
130long sys32_init_module(void __user *umod, unsigned long len, 128long sys32_init_module(void __user *umod, unsigned long len,
131 const char __user *uargs); 129 const char __user *uargs);
132long sys32_delete_module(const char __user *name_user, unsigned int flags); 130long 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
1581ENTRY(sys_fanotify_init_wrapper) 1581ENTRY(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)
3360: 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
3411: # 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
348ENTRY(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#
346ENTRY(kernel_execve) 358ENTRY(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.
3630: 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);
58long sys_clone(unsigned long newsp, unsigned long clone_flags, 58long 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);
60long sys_vfork(void); 60long sys_vfork(void);
61void execve_tail(void);
62long sys_execve(const char __user *name, const char __user *const __user *argv,
63 const char __user *const __user *envp);
64long sys_sigsuspend(int history0, int history1, old_sigset_t mask); 61long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
65long sys_sigaction(int sig, const struct old_sigaction __user *act, 62long 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
3580: 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 3611: # 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
367ENTRY(kernel_execve) 366 lmg %r9,%r11,__PT_R9(%r11) # load gprs
368 stmg %r12,%r15,96(%r15) 367ENTRY(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 373ENTRY(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.
3820: 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
101extern void __kprobes kernel_thread_starter(void); 101extern void __kprobes kernel_thread_starter(void);
102 102
103asm(
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
113int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
114{
115 struct pt_regs regs;
116
117 memset(&regs, 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, &regs, 0, NULL, NULL);
129}
130EXPORT_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
148int copy_thread(unsigned long clone_flags, unsigned long new_stackp, 119int 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 */
263SYSCALL_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];
280out:
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 */
288int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) 247int 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
7generic-y += div64.h 7generic-y += div64.h
8generic-y += emergency-restart.h 8generic-y += emergency-restart.h
9generic-y += errno.h 9generic-y += errno.h
10generic-y += exec.h
10generic-y += fcntl.h 11generic-y += fcntl.h
11generic-y += ioctl.h 12generic-y += ioctl.h
12generic-y += ipcbuf.h 13generic-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
4generic-y += clkdev.h 4generic-y += clkdev.h
5generic-y += div64.h 5generic-y += div64.h
6generic-y += exec.h
6generic-y += local64.h 7generic-y += local64.h
7generic-y += irq_regs.h 8generic-y += irq_regs.h
8generic-y += local.h 9generic-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
13generic-y += div64.h 13generic-y += div64.h
14generic-y += emergency-restart.h 14generic-y += emergency-restart.h
15generic-y += errno.h 15generic-y += errno.h
16generic-y += exec.h
16generic-y += fb.h 17generic-y += fb.h
17generic-y += fcntl.h 18generic-y += fcntl.h
18generic-y += ioctl.h 19generic-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
66extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
67
68extern unsigned long thread_saved_pc(struct task_struct *t); 66extern unsigned long thread_saved_pc(struct task_struct *t);
69 67
70static inline void mm_copy_segments(struct mm_struct *from_mm, 68static 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
21void flush_thread(void) 20void flush_thread(void)
22{ 21{
@@ -49,27 +48,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
49} 48}
50EXPORT_SYMBOL(start_thread); 49EXPORT_SYMBOL(start_thread);
51 50
52long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) 51void __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, &current->thread.regs);
57 if (!err)
58 UML_LONGJMP(current->thread.exec_buf, 1);
59 return err;
60}
61
62long 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, &current->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 @@
1extern 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
72int 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 &current->thread.regs, 0, NULL, NULL);
80 return pid;
81}
82EXPORT_SYMBOL(kernel_thread);
83
84static inline void set_current(struct task_struct *task) 72static 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
179int copy_thread(unsigned long clone_flags, unsigned long sp, 167int 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(&current->thread.arch, &p->thread.arch); 186 arch_copy_thread(&current->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
18long sys_fork(void) 17long 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
54int 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
11generic-y += div64.h 11generic-y += div64.h
12generic-y += emergency-restart.h 12generic-y += emergency-restart.h
13generic-y += errno.h 13generic-y += errno.h
14generic-y += exec.h
14generic-y += fb.h 15generic-y += fb.h
15generic-y += fcntl.h 16generic-y += fcntl.h
16generic-y += ftrace.h 17generic-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}
107EXPORT_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. */
110SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, 109SYSCALL_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
112config INSTRUCTION_DECODER 113config 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
388asmlinkage 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
403asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, 388asmlinkage 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 */
594extern 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. */
597extern void release_thread(struct task_struct *); 592extern 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);
54asmlinkage long sys32_personality(unsigned long); 54asmlinkage long sys32_personality(unsigned long);
55asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); 55asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
56 56
57asmlinkage long sys32_execve(const char __user *, compat_uptr_t __user *,
58 compat_uptr_t __user *, struct pt_regs *);
59asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); 57asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
60 58
61long sys32_lseek(unsigned int, int, unsigned int); 59long 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 *);
25int sys_vfork(struct pt_regs *); 25int sys_vfork(struct pt_regs *);
26long sys_execve(const char __user *, 26long 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 *);
29long sys_clone(unsigned long, unsigned long, void __user *, 29long 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
23obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o 23obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
24obj-$(CONFIG_IRQ_WORK) += irq_work.o 24obj-$(CONFIG_IRQ_WORK) += irq_work.o
25obj-y += probe_roms.o 25obj-y += probe_roms.o
26obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o 26obj-$(CONFIG_X86_32) += i386_ksyms_32.o
27obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 27obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
28obj-y += syscall_$(BITS).o 28obj-y += syscall_$(BITS).o
29obj-$(CONFIG_X86_64) += vsyscall_64.o 29obj-$(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
300END(ret_from_fork) 300END(ret_from_fork)
301 301
302ENTRY(ret_from_kernel_execve)
303 movl %eax, %esp
304 movl $0,PT_EAX(%esp)
305 GET_THREAD_INFO(%ebp)
306 jmp syscall_exit
307END(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)
732PTREGSCALL1(iopl) 738PTREGSCALL1(iopl)
733PTREGSCALL0(fork) 739PTREGSCALL0(fork)
734PTREGSCALL0(vfork) 740PTREGSCALL0(vfork)
735PTREGSCALL3(execve)
736PTREGSCALL2(sigaltstack) 741PTREGSCALL2(sigaltstack)
737PTREGSCALL0(sigreturn) 742PTREGSCALL0(sigreturn)
738PTREGSCALL0(rt_sigreturn) 743PTREGSCALL0(rt_sigreturn)
@@ -1015,15 +1020,20 @@ END(spurious_interrupt_bug)
1015 */ 1020 */
1016 .popsection 1021 .popsection
1017 1022
1018ENTRY(kernel_thread_helper) 1023ENTRY(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
1026ENDPROC(kernel_thread_helper) 1036ENDPROC(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
5651:
566 subq $REST_SKIP, %rsp # move the stack pointer back
567 CFI_ADJUST_CFA_OFFSET REST_SKIP
568 movq %rbp, %rdi
569 call *%rbx
570 # exit
571 mov %eax, %edi
572 call do_exit
573 ud2 # padding for call trace
574
565 CFI_ENDPROC 575 CFI_ENDPROC
566END(ret_from_fork) 576END(ret_from_fork)
567 577
@@ -862,7 +872,6 @@ ENTRY(stub_execve)
862 PARTIAL_FRAME 0 872 PARTIAL_FRAME 0
863 SAVE_REST 873 SAVE_REST
864 FIXUP_TOP_OF_STACK %r11 874 FIXUP_TOP_OF_STACK %r11
865 movq %rsp, %rcx
866 call sys_execve 875 call sys_execve
867 RESTORE_TOP_OF_STACK %r11 876 RESTORE_TOP_OF_STACK %r11
868 movq %rax,RAX(%rsp) 877 movq %rax,RAX(%rsp)
@@ -912,8 +921,7 @@ ENTRY(stub_x32_execve)
912 PARTIAL_FRAME 0 921 PARTIAL_FRAME 0
913 SAVE_REST 922 SAVE_REST
914 FIXUP_TOP_OF_STACK %r11 923 FIXUP_TOP_OF_STACK %r11
915 movq %rsp, %rcx 924 call compat_sys_execve
916 call sys32_execve
917 RESTORE_TOP_OF_STACK %r11 925 RESTORE_TOP_OF_STACK %r11
918 movq %rax,RAX(%rsp) 926 movq %rax,RAX(%rsp)
919 RESTORE_REST 927 RESTORE_REST
@@ -1318,51 +1326,19 @@ bad_gs:
1318 jmp 2b 1326 jmp 2b
1319 .previous 1327 .previous
1320 1328
1321ENTRY(kernel_thread_helper) 1329ENTRY(ret_from_kernel_execve)
1322 pushq $0 # fake return address 1330 movq %rdi, %rsp
1323 CFI_STARTPROC 1331 movl $0, RAX(%rsp)
1324 /* 1332 // RESTORE_REST
1325 * Here we are in the child and the registers are set as they were 1333 movq 0*8(%rsp), %r15
1326 * at kernel_thread() invocation in the parent. 1334 movq 1*8(%rsp), %r14
1327 */ 1335 movq 2*8(%rsp), %r13
1328 call *%rsi 1336 movq 3*8(%rsp), %r12
1329 # exit 1337 movq 4*8(%rsp), %rbp
1330 mov %eax, %edi 1338 movq 5*8(%rsp), %rbx
1331 call do_exit 1339 addq $(6*8), %rsp
1332 ud2 # padding for call trace 1340 jmp int_ret_from_sys_call
1333 CFI_ENDPROC 1341END(ret_from_kernel_execve)
1334END(kernel_thread_helper)
1335
1336/*
1337 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
1338 *
1339 * C extern interface:
1340 * extern long execve(const char *name, char **argv, char **envp)
1341 *
1342 * asm input arguments:
1343 * rdi: name, rsi: argv, rdx: envp
1344 *
1345 * We want to fallback into:
1346 * extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
1347 *
1348 * do_sys_execve asm fallback arguments:
1349 * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
1350 */
1351ENTRY(kernel_execve)
1352 CFI_STARTPROC
1353 FAKE_STACK_FRAME $0
1354 SAVE_ALL
1355 movq %rsp,%rcx
1356 call sys_execve
1357 movq %rax, RAX(%rsp)
1358 RESTORE_REST
1359 testq %rax,%rax
1360 je int_ret_from_sys_call
1361 RESTORE_ARGS
1362 UNFAKE_STACK_FRAME
1363 ret
1364 CFI_ENDPROC
1365END(kernel_execve)
1366 1342
1367/* Call softirq on interrupt stack. Interrupts are off. */ 1343/* Call softirq on interrupt stack. Interrupts are off. */
1368ENTRY(call_softirq) 1344ENTRY(call_softirq)
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 */
300extern void kernel_thread_helper(void);
301
302/*
303 * Create a kernel thread
304 */
305int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
306{
307 struct pt_regs regs;
308
309 memset(&regs, 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, &regs, 0, NULL, NULL);
330}
331EXPORT_SYMBOL(kernel_thread);
332
333/*
334 * sys_execve() executes a new program.
335 */
336long 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 */
363unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; 298unsigned 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
59asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 59asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
60asmlinkage 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
129int copy_thread(unsigned long clone_flags, unsigned long sp, 130int 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}
194EXPORT_SYMBOL_GPL(start_thread); 217EXPORT_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
148int copy_thread(unsigned long clone_flags, unsigned long sp, 148int 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 */
31int 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 @@
178 i386 creat sys_creat 178 i386 creat sys_creat
189 i386 link sys_link 189 i386 link sys_link
1910 i386 unlink sys_unlink 1910 i386 unlink sys_unlink
2011 i386 execve ptregs_execve stub32_execve 2011 i386 execve sys_execve stub32_execve
2112 i386 chdir sys_chdir 2112 i386 chdir sys_chdir
2213 i386 time sys_time compat_sys_time 2213 i386 time sys_time compat_sys_time
2314 i386 mknod sys_mknod 2314 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
13config UML_X86 13config 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
17config 64BIT 18config 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 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3generic-y += clkdev.h 3generic-y += clkdev.h
4generic-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 */
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index e800dec958c3..fbd9f60bd763 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -36,7 +36,6 @@
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37#include <asm/param.h> 37#include <asm/param.h>
38#include <asm/page.h> 38#include <asm/page.h>
39#include <asm/exec.h>
40 39
41#ifndef user_long_t 40#ifndef user_long_t
42#define user_long_t long 41#define user_long_t long
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 262db114ff01..a46049154107 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -39,7 +39,6 @@
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
40#include <asm/param.h> 40#include <asm/param.h>
41#include <asm/pgalloc.h> 41#include <asm/pgalloc.h>
42#include <asm/exec.h>
43 42
44typedef char *elf_caddr_t; 43typedef char *elf_caddr_t;
45 44
diff --git a/fs/exec.c b/fs/exec.c
index 4f2bebc276c5..ca434534ae9a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -59,7 +59,6 @@
59#include <asm/uaccess.h> 59#include <asm/uaccess.h>
60#include <asm/mmu_context.h> 60#include <asm/mmu_context.h>
61#include <asm/tlb.h> 61#include <asm/tlb.h>
62#include <asm/exec.h>
63 62
64#include <trace/events/task.h> 63#include <trace/events/task.h>
65#include "internal.h" 64#include "internal.h"
@@ -392,7 +391,7 @@ struct user_arg_ptr {
392 union { 391 union {
393 const char __user *const __user *native; 392 const char __user *const __user *native;
394#ifdef CONFIG_COMPAT 393#ifdef CONFIG_COMPAT
395 compat_uptr_t __user *compat; 394 const compat_uptr_t __user *compat;
396#endif 395#endif
397 } ptr; 396 } ptr;
398}; 397};
@@ -1574,9 +1573,9 @@ int do_execve(const char *filename,
1574} 1573}
1575 1574
1576#ifdef CONFIG_COMPAT 1575#ifdef CONFIG_COMPAT
1577int compat_do_execve(char *filename, 1576int compat_do_execve(const char *filename,
1578 compat_uptr_t __user *__argv, 1577 const compat_uptr_t __user *__argv,
1579 compat_uptr_t __user *__envp, 1578 const compat_uptr_t __user *__envp,
1580 struct pt_regs *regs) 1579 struct pt_regs *regs)
1581{ 1580{
1582 struct user_arg_ptr argv = { 1581 struct user_arg_ptr argv = {
@@ -1658,3 +1657,55 @@ int get_dumpable(struct mm_struct *mm)
1658{ 1657{
1659 return __get_dumpable(mm->flags); 1658 return __get_dumpable(mm->flags);
1660} 1659}
1660
1661#ifdef __ARCH_WANT_SYS_EXECVE
1662SYSCALL_DEFINE3(execve,
1663 const char __user *, filename,
1664 const char __user *const __user *, argv,
1665 const char __user *const __user *, envp)
1666{
1667 const char *path = getname(filename);
1668 int error = PTR_ERR(path);
1669 if (!IS_ERR(path)) {
1670 error = do_execve(path, argv, envp, current_pt_regs());
1671 putname(path);
1672 }
1673 return error;
1674}
1675#ifdef CONFIG_COMPAT
1676asmlinkage long compat_sys_execve(const char __user * filename,
1677 const compat_uptr_t __user * argv,
1678 const compat_uptr_t __user * envp)
1679{
1680 const char *path = getname(filename);
1681 int error = PTR_ERR(path);
1682 if (!IS_ERR(path)) {
1683 error = compat_do_execve(path, argv, envp, current_pt_regs());
1684 putname(path);
1685 }
1686 return error;
1687}
1688#endif
1689#endif
1690
1691#ifdef __ARCH_WANT_KERNEL_EXECVE
1692int kernel_execve(const char *filename,
1693 const char *const argv[],
1694 const char *const envp[])
1695{
1696 struct pt_regs *p = current_pt_regs();
1697 int ret;
1698
1699 ret = do_execve(filename,
1700 (const char __user *const __user *)argv,
1701 (const char __user *const __user *)envp, p);
1702 if (ret < 0)
1703 return ret;
1704
1705 /*
1706 * We were successful. We won't be returning to our caller, but
1707 * instead to user space by manipulating the kernel stack.
1708 */
1709 ret_from_kernel_execve(p);
1710}
1711#endif
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 37935c2d2e8f..26531f32bbb2 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -19,6 +19,8 @@ struct pt_regs;
19 19
20#ifdef __KERNEL__ 20#ifdef __KERNEL__
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/unistd.h>
23#include <asm/exec.h>
22 24
23#define CORENAME_MAX_SIZE 128 25#define CORENAME_MAX_SIZE 128
24 26
@@ -135,5 +137,9 @@ extern void install_exec_creds(struct linux_binprm *bprm);
135extern void set_binfmt(struct linux_binfmt *new); 137extern void set_binfmt(struct linux_binfmt *new);
136extern void free_bprm(struct linux_binprm *); 138extern void free_bprm(struct linux_binprm *);
137 139
140#ifdef __ARCH_WANT_KERNEL_EXECVE
141extern void ret_from_kernel_execve(struct pt_regs *normal) __noreturn;
142#endif
143
138#endif /* __KERNEL__ */ 144#endif /* __KERNEL__ */
139#endif /* _LINUX_BINFMTS_H */ 145#endif /* _LINUX_BINFMTS_H */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 3f53d002c7c5..d0ced1011f2f 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -284,8 +284,12 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
284 const struct compat_iovec __user *vec, 284 const struct compat_iovec __user *vec,
285 unsigned long vlen, u32 pos_low, u32 pos_high); 285 unsigned long vlen, u32 pos_low, u32 pos_high);
286 286
287int compat_do_execve(char *filename, compat_uptr_t __user *argv, 287int compat_do_execve(const char *filename, const compat_uptr_t __user *argv,
288 compat_uptr_t __user *envp, struct pt_regs *regs); 288 const compat_uptr_t __user *envp, struct pt_regs *regs);
289#ifdef __ARCH_WANT_SYS_EXECVE
290asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
291 const compat_uptr_t __user *envp);
292#endif
289 293
290asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, 294asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
291 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 295 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 3db698aee34c..1d24ffad59c5 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -401,6 +401,10 @@ static inline void user_single_step_siginfo(struct task_struct *tsk,
401#define arch_ptrace_stop(code, info) do { } while (0) 401#define arch_ptrace_stop(code, info) do { } while (0)
402#endif 402#endif
403 403
404#ifndef current_pt_regs
405#define current_pt_regs() task_pt_regs(current)
406#endif
407
404extern int task_current_syscall(struct task_struct *target, long *callno, 408extern int task_current_syscall(struct task_struct *target, long *callno,
405 unsigned long args[6], unsigned int maxargs, 409 unsigned long args[6], unsigned int maxargs,
406 unsigned long *sp, unsigned long *pc); 410 unsigned long *sp, unsigned long *pc);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c2070e92a9d6..a83ca5816ecb 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2332,6 +2332,9 @@ extern int do_execve(const char *,
2332 const char __user * const __user *, struct pt_regs *); 2332 const char __user * const __user *, struct pt_regs *);
2333extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); 2333extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
2334struct task_struct *fork_idle(int); 2334struct task_struct *fork_idle(int);
2335#ifdef CONFIG_GENERIC_KERNEL_THREAD
2336extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
2337#endif
2335 2338
2336extern void set_task_comm(struct task_struct *tsk, char *from); 2339extern void set_task_comm(struct task_struct *tsk, char *from);
2337extern char *get_task_comm(char *to, struct task_struct *tsk); 2340extern char *get_task_comm(char *to, struct task_struct *tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index 1cd7d581b3b2..8b20ab7d3aa2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1584,7 +1584,7 @@ long do_fork(unsigned long clone_flags,
1584 * requested, no event is reported; otherwise, report if the event 1584 * requested, no event is reported; otherwise, report if the event
1585 * for the type of forking is enabled. 1585 * for the type of forking is enabled.
1586 */ 1586 */
1587 if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) { 1587 if (!(clone_flags & CLONE_UNTRACED) && likely(user_mode(regs))) {
1588 if (clone_flags & CLONE_VFORK) 1588 if (clone_flags & CLONE_VFORK)
1589 trace = PTRACE_EVENT_VFORK; 1589 trace = PTRACE_EVENT_VFORK;
1590 else if ((clone_flags & CSIGNAL) != SIGCHLD) 1590 else if ((clone_flags & CSIGNAL) != SIGCHLD)
@@ -1634,6 +1634,17 @@ long do_fork(unsigned long clone_flags,
1634 return nr; 1634 return nr;
1635} 1635}
1636 1636
1637#ifdef CONFIG_GENERIC_KERNEL_THREAD
1638/*
1639 * Create a kernel thread.
1640 */
1641pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
1642{
1643 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, NULL,
1644 (unsigned long)arg, NULL, NULL);
1645}
1646#endif
1647
1637#ifndef ARCH_MIN_MMSTRUCT_ALIGN 1648#ifndef ARCH_MIN_MMSTRUCT_ALIGN
1638#define ARCH_MIN_MMSTRUCT_ALIGN 0 1649#define ARCH_MIN_MMSTRUCT_ALIGN 0
1639#endif 1650#endif