aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 15:22:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 15:22:13 -0500
commit9977d9b379cb77e0f67bd6f4563618106e58e11d (patch)
tree0191accfddf578edb52c69c933d64521e3dce297 /arch/x86
parentcf4af01221579a4e895f43dbfc47598fbfc5a731 (diff)
parent541880d9a2c7871f6370071d55aa6662d329c51e (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull big execve/kernel_thread/fork unification series from Al Viro: "All architectures are converted to new model. Quite a bit of that stuff is actually shared with architecture trees; in such cases it's literally shared branch pulled by both, not a cherry-pick. A lot of ugliness and black magic is gone (-3KLoC total in this one): - kernel_thread()/kernel_execve()/sys_execve() redesign. We don't do syscalls from kernel anymore for either kernel_thread() or kernel_execve(): kernel_thread() is essentially clone(2) with callback run before we return to userland, the callbacks either never return or do successful do_execve() before returning. kernel_execve() is a wrapper for do_execve() - it doesn't need to do transition to user mode anymore. As a result kernel_thread() and kernel_execve() are arch-independent now - they live in kernel/fork.c and fs/exec.c resp. sys_execve() is also in fs/exec.c and it's completely architecture-independent. - daemonize() is gone, along with its parts in fs/*.c - struct pt_regs * is no longer passed to do_fork/copy_process/ copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump. - sys_fork()/sys_vfork()/sys_clone() unified; some architectures still need wrappers (ones with callee-saved registers not saved in pt_regs on syscall entry), but the main part of those suckers is in kernel/fork.c now." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits) do_coredump(): get rid of pt_regs argument print_fatal_signal(): get rid of pt_regs argument ptrace_signal(): get rid of unused arguments get rid of ptrace_signal_deliver() arguments new helper: signal_pt_regs() unify default ptrace_signal_deliver flagday: kill pt_regs argument of do_fork() death to idle_regs() don't pass regs to copy_process() flagday: don't pass regs to copy_thread() bfin: switch to generic vfork, get rid of pointless wrappers xtensa: switch to generic clone() openrisc: switch to use of generic fork and clone unicore32: switch to generic clone(2) score: switch to generic fork/vfork/clone c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone() take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h mn10300: switch to generic fork/vfork/clone h8300: switch to generic fork/vfork/clone tile: switch to generic clone() ... Conflicts: arch/microblaze/include/asm/Kbuild
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/ia32/ia32_aout.c5
-rw-r--r--arch/x86/ia32/ia32entry.S7
-rw-r--r--arch/x86/ia32/sys_ia32.c11
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/include/asm/signal.h2
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--arch/x86/include/asm/syscalls.h9
-rw-r--r--arch/x86/include/asm/unistd.h3
-rw-r--r--arch/x86/kernel/cpu/common.c9
-rw-r--r--arch/x86/kernel/entry_32.S18
-rw-r--r--arch/x86/kernel/entry_64.S22
-rw-r--r--arch/x86/kernel/process.c30
-rw-r--r--arch/x86/kernel/process_32.c12
-rw-r--r--arch/x86/kernel/process_64.c10
-rw-r--r--arch/x86/syscalls/syscall_32.tbl6
-rw-r--r--arch/x86/um/Kconfig1
-rw-r--r--arch/x86/um/shared/sysdep/syscalls.h2
-rw-r--r--arch/x86/um/sys_call_table_32.c3
-rw-r--r--arch/x86/um/syscalls_32.c15
20 files changed, 47 insertions, 123 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 037c4e30c271..9195fd80e11e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -112,6 +112,7 @@ config X86
112 select GENERIC_KERNEL_EXECVE 112 select GENERIC_KERNEL_EXECVE
113 select MODULES_USE_ELF_REL if X86_32 113 select MODULES_USE_ELF_REL if X86_32
114 select MODULES_USE_ELF_RELA if X86_64 114 select MODULES_USE_ELF_RELA if X86_64
115 select CLONE_BACKWARDS if X86_32
115 116
116config INSTRUCTION_DECODER 117config INSTRUCTION_DECODER
117 def_bool y 118 def_bool y
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 07b3a68d2d29..a703af19c281 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -35,7 +35,7 @@
35#undef WARN_OLD 35#undef WARN_OLD
36#undef CORE_DUMP /* definitely broken */ 36#undef CORE_DUMP /* definitely broken */
37 37
38static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); 38static int load_aout_binary(struct linux_binprm *);
39static int load_aout_library(struct file *); 39static int load_aout_library(struct file *);
40 40
41#ifdef CORE_DUMP 41#ifdef CORE_DUMP
@@ -260,9 +260,10 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)
260 * These are the functions used to load a.out style executables and shared 260 * These are the functions used to load a.out style executables and shared
261 * libraries. There is no binary dependent code anywhere else. 261 * libraries. There is no binary dependent code anywhere else.
262 */ 262 */
263static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) 263static int load_aout_binary(struct linux_binprm *bprm)
264{ 264{
265 unsigned long error, fd_offset, rlim; 265 unsigned long error, fd_offset, rlim;
266 struct pt_regs *regs = current_pt_regs();
266 struct exec ex; 267 struct exec ex;
267 int retval; 268 int retval;
268 269
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 076745fc8045..32e6f05ddaaa 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -467,11 +467,16 @@ GLOBAL(\label)
467 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx 467 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
468 PTREGSCALL stub32_execve, compat_sys_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
471 PTREGSCALL stub32_vfork, sys_vfork, %rdi 470 PTREGSCALL stub32_vfork, sys_vfork, %rdi
472 PTREGSCALL stub32_iopl, sys_iopl, %rsi 471 PTREGSCALL stub32_iopl, sys_iopl, %rsi
473 472
474 ALIGN 473 ALIGN
474GLOBAL(stub32_clone)
475 leaq sys_clone(%rip),%rax
476 mov %r8, %rcx
477 jmp ia32_ptregs_common
478
479 ALIGN
475ia32_ptregs_common: 480ia32_ptregs_common:
476 popq %r11 481 popq %r11
477 CFI_ENDPROC 482 CFI_ENDPROC
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 86d68d1c8806..d0b689ba7be2 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -385,17 +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_clone(unsigned int clone_flags, unsigned int newsp,
389 struct pt_regs *regs)
390{
391 void __user *parent_tid = (void __user *)regs->dx;
392 void __user *child_tid = (void __user *)regs->di;
393
394 if (!newsp)
395 newsp = regs->sp;
396 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
397}
398
399/* 388/*
400 * Some system calls that need sign extended arguments. This could be 389 * Some system calls that need sign extended arguments. This could be
401 * done by a generic wrapper. 390 * done by a generic wrapper.
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index e101b38912de..888184b2fc85 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -178,8 +178,6 @@ static inline int hlt_works(int cpu)
178 178
179extern void cpu_detect(struct cpuinfo_x86 *c); 179extern void cpu_detect(struct cpuinfo_x86 *c);
180 180
181extern struct pt_regs *idle_regs(struct pt_regs *);
182
183extern void early_cpu_init(void); 181extern void early_cpu_init(void);
184extern void identify_boot_cpu(void); 182extern void identify_boot_cpu(void);
185extern void identify_secondary_cpu(struct cpuinfo_x86 *); 183extern void identify_secondary_cpu(struct cpuinfo_x86 *);
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 323973f4abf1..0dba8b7a6ac7 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -260,8 +260,6 @@ struct pt_regs;
260 260
261#endif /* !__i386__ */ 261#endif /* !__i386__ */
262 262
263#define ptrace_signal_deliver(regs, cookie) do { } while (0)
264
265#endif /* __KERNEL__ */ 263#endif /* __KERNEL__ */
266#endif /* __ASSEMBLY__ */ 264#endif /* __ASSEMBLY__ */
267 265
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index a9a8cf3da49d..c76fae4d90be 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_clone(unsigned int, unsigned int, struct pt_regs *);
58
59long sys32_lseek(unsigned int, int, unsigned int); 57long sys32_lseek(unsigned int, int, unsigned int);
60long sys32_kill(int, int); 58long sys32_kill(int, int);
61long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int); 59long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int);
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 2be0b880417e..2f8374718aa3 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -20,15 +20,6 @@
20asmlinkage long sys_ioperm(unsigned long, unsigned long, int); 20asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
21long sys_iopl(unsigned int, struct pt_regs *); 21long sys_iopl(unsigned int, struct pt_regs *);
22 22
23/* kernel/process.c */
24int sys_fork(struct pt_regs *);
25int sys_vfork(struct pt_regs *);
26long sys_execve(const char __user *,
27 const char __user *const __user *,
28 const char __user *const __user *);
29long sys_clone(unsigned long, unsigned long, void __user *,
30 void __user *, struct pt_regs *);
31
32/* kernel/ldt.c */ 23/* kernel/ldt.c */
33asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); 24asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
34 25
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 16f3fc6ebf2e..0e7dea7d3669 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -51,6 +51,9 @@
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 53# define __ARCH_WANT_SYS_EXECVE
54# define __ARCH_WANT_SYS_FORK
55# define __ARCH_WANT_SYS_VFORK
56# define __ARCH_WANT_SYS_CLONE
54 57
55/* 58/*
56 * "Conditional" syscalls 59 * "Conditional" syscalls
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ca165ac6793b..9c3ab43a6954 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1173,15 +1173,6 @@ DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
1173DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); 1173DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
1174#endif 1174#endif
1175 1175
1176/* Make sure %fs and %gs are initialized properly in idle threads */
1177struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
1178{
1179 memset(regs, 0, sizeof(struct pt_regs));
1180 regs->fs = __KERNEL_PERCPU;
1181 regs->gs = __KERNEL_STACK_CANARY;
1182
1183 return regs;
1184}
1185#endif /* CONFIG_X86_64 */ 1176#endif /* CONFIG_X86_64 */
1186 1177
1187/* 1178/*
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 88b725aa1d52..c763116c5359 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -739,30 +739,12 @@ ENTRY(ptregs_##name) ; \
739ENDPROC(ptregs_##name) 739ENDPROC(ptregs_##name)
740 740
741PTREGSCALL1(iopl) 741PTREGSCALL1(iopl)
742PTREGSCALL0(fork)
743PTREGSCALL0(vfork)
744PTREGSCALL2(sigaltstack) 742PTREGSCALL2(sigaltstack)
745PTREGSCALL0(sigreturn) 743PTREGSCALL0(sigreturn)
746PTREGSCALL0(rt_sigreturn) 744PTREGSCALL0(rt_sigreturn)
747PTREGSCALL2(vm86) 745PTREGSCALL2(vm86)
748PTREGSCALL1(vm86old) 746PTREGSCALL1(vm86old)
749 747
750/* Clone is an oddball. The 4th arg is in %edi */
751ENTRY(ptregs_clone)
752 CFI_STARTPROC
753 leal 4(%esp),%eax
754 pushl_cfi %eax
755 pushl_cfi PT_EDI(%eax)
756 movl PT_EDX(%eax),%ecx
757 movl PT_ECX(%eax),%edx
758 movl PT_EBX(%eax),%eax
759 call sys_clone
760 addl $8,%esp
761 CFI_ADJUST_CFA_OFFSET -8
762 ret
763 CFI_ENDPROC
764ENDPROC(ptregs_clone)
765
766.macro FIXUP_ESPFIX_STACK 748.macro FIXUP_ESPFIX_STACK
767/* 749/*
768 * Switch back for ESPFIX stack to the normal zerobased stack 750 * Switch back for ESPFIX stack to the normal zerobased stack
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 31b46128a63d..70641aff0c25 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -845,9 +845,25 @@ ENTRY(\label)
845END(\label) 845END(\label)
846 .endm 846 .endm
847 847
848 PTREGSCALL stub_clone, sys_clone, %r8 848 .macro FORK_LIKE func
849 PTREGSCALL stub_fork, sys_fork, %rdi 849ENTRY(stub_\func)
850 PTREGSCALL stub_vfork, sys_vfork, %rdi 850 CFI_STARTPROC
851 popq %r11 /* save return address */
852 PARTIAL_FRAME 0
853 SAVE_REST
854 pushq %r11 /* put it back on stack */
855 FIXUP_TOP_OF_STACK %r11, 8
856 DEFAULT_FRAME 0 8 /* offset 8: return address */
857 call sys_\func
858 RESTORE_TOP_OF_STACK %r11, 8
859 ret $REST_SKIP /* pop extended registers */
860 CFI_ENDPROC
861END(stub_\func)
862 .endm
863
864 FORK_LIKE clone
865 FORK_LIKE fork
866 FORK_LIKE vfork
851 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx 867 PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
852 PTREGSCALL stub_iopl, sys_iopl, %rsi 868 PTREGSCALL stub_iopl, sys_iopl, %rsi
853 869
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 2f99e3121875..2ed787f15bf0 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -262,36 +262,6 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
262 propagate_user_return_notify(prev_p, next_p); 262 propagate_user_return_notify(prev_p, next_p);
263} 263}
264 264
265int sys_fork(struct pt_regs *regs)
266{
267 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
268}
269
270/*
271 * This is trivial, and on the face of it looks like it
272 * could equally well be done in user mode.
273 *
274 * Not so, for quite unobvious reasons - register pressure.
275 * In user mode vfork() cannot have a stack frame, and if
276 * done by calling the "clone()" system call directly, you
277 * do not have enough call-clobbered registers to hold all
278 * the information you need.
279 */
280int sys_vfork(struct pt_regs *regs)
281{
282 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
283 NULL, NULL);
284}
285
286long
287sys_clone(unsigned long clone_flags, unsigned long newsp,
288 void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
289{
290 if (!newsp)
291 newsp = regs->sp;
292 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
293}
294
295/* 265/*
296 * Idle related variables and functions 266 * Idle related variables and functions
297 */ 267 */
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 44e0bff38e72..b5a8905785e6 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -128,8 +128,7 @@ void release_thread(struct task_struct *dead_task)
128} 128}
129 129
130int copy_thread(unsigned long clone_flags, unsigned long sp, 130int copy_thread(unsigned long clone_flags, unsigned long sp,
131 unsigned long arg, 131 unsigned long arg, struct task_struct *p)
132 struct task_struct *p, struct pt_regs *regs)
133{ 132{
134 struct pt_regs *childregs = task_pt_regs(p); 133 struct pt_regs *childregs = task_pt_regs(p);
135 struct task_struct *tsk; 134 struct task_struct *tsk;
@@ -138,7 +137,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
138 p->thread.sp = (unsigned long) childregs; 137 p->thread.sp = (unsigned long) childregs;
139 p->thread.sp0 = (unsigned long) (childregs+1); 138 p->thread.sp0 = (unsigned long) (childregs+1);
140 139
141 if (unlikely(!regs)) { 140 if (unlikely(p->flags & PF_KTHREAD)) {
142 /* kernel thread */ 141 /* kernel thread */
143 memset(childregs, 0, sizeof(struct pt_regs)); 142 memset(childregs, 0, sizeof(struct pt_regs));
144 p->thread.ip = (unsigned long) ret_from_kernel_thread; 143 p->thread.ip = (unsigned long) ret_from_kernel_thread;
@@ -156,12 +155,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
156 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 155 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
157 return 0; 156 return 0;
158 } 157 }
159 *childregs = *regs; 158 *childregs = *current_pt_regs();
160 childregs->ax = 0; 159 childregs->ax = 0;
161 childregs->sp = sp; 160 if (sp)
161 childregs->sp = sp;
162 162
163 p->thread.ip = (unsigned long) ret_from_fork; 163 p->thread.ip = (unsigned long) ret_from_fork;
164 task_user_gs(p) = get_user_gs(regs); 164 task_user_gs(p) = get_user_gs(current_pt_regs());
165 165
166 p->fpu_counter = 0; 166 p->fpu_counter = 0;
167 p->thread.io_bitmap_ptr = NULL; 167 p->thread.io_bitmap_ptr = NULL;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 16c6365e2b86..6e68a6194965 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -146,8 +146,7 @@ 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 arg, 149 unsigned long arg, struct task_struct *p)
150 struct task_struct *p, struct pt_regs *regs)
151{ 150{
152 int err; 151 int err;
153 struct pt_regs *childregs; 152 struct pt_regs *childregs;
@@ -169,7 +168,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
169 savesegment(ds, p->thread.ds); 168 savesegment(ds, p->thread.ds);
170 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 169 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
171 170
172 if (unlikely(!regs)) { 171 if (unlikely(p->flags & PF_KTHREAD)) {
173 /* kernel thread */ 172 /* kernel thread */
174 memset(childregs, 0, sizeof(struct pt_regs)); 173 memset(childregs, 0, sizeof(struct pt_regs));
175 childregs->sp = (unsigned long)childregs; 174 childregs->sp = (unsigned long)childregs;
@@ -181,10 +180,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
181 childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; 180 childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
182 return 0; 181 return 0;
183 } 182 }
184 *childregs = *regs; 183 *childregs = *current_pt_regs();
185 184
186 childregs->ax = 0; 185 childregs->ax = 0;
187 childregs->sp = sp; 186 if (sp)
187 childregs->sp = sp;
188 188
189 err = -ENOMEM; 189 err = -ENOMEM;
190 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/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index a47103fbc692..ee3c220ee500 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -8,7 +8,7 @@
8# 8#
90 i386 restart_syscall sys_restart_syscall 90 i386 restart_syscall sys_restart_syscall
101 i386 exit sys_exit 101 i386 exit sys_exit
112 i386 fork ptregs_fork stub32_fork 112 i386 fork sys_fork stub32_fork
123 i386 read sys_read 123 i386 read sys_read
134 i386 write sys_write 134 i386 write sys_write
145 i386 open sys_open compat_sys_open 145 i386 open sys_open compat_sys_open
@@ -126,7 +126,7 @@
126117 i386 ipc sys_ipc sys32_ipc 126117 i386 ipc sys_ipc sys32_ipc
127118 i386 fsync sys_fsync 127118 i386 fsync sys_fsync
128119 i386 sigreturn ptregs_sigreturn stub32_sigreturn 128119 i386 sigreturn ptregs_sigreturn stub32_sigreturn
129120 i386 clone ptregs_clone stub32_clone 129120 i386 clone sys_clone stub32_clone
130121 i386 setdomainname sys_setdomainname 130121 i386 setdomainname sys_setdomainname
131122 i386 uname sys_newuname 131122 i386 uname sys_newuname
132123 i386 modify_ldt sys_modify_ldt 132123 i386 modify_ldt sys_modify_ldt
@@ -196,7 +196,7 @@
196187 i386 sendfile sys_sendfile sys32_sendfile 196187 i386 sendfile sys_sendfile sys32_sendfile
197188 i386 getpmsg 197188 i386 getpmsg
198189 i386 putpmsg 198189 i386 putpmsg
199190 i386 vfork ptregs_vfork stub32_vfork 199190 i386 vfork sys_vfork stub32_vfork
200191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit 200191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit
201192 i386 mmap2 sys_mmap_pgoff 201192 i386 mmap2 sys_mmap_pgoff
202193 i386 truncate64 sys_truncate64 sys32_truncate64 202193 i386 truncate64 sys_truncate64 sys32_truncate64
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index b0c30dae9f55..983997041963 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -25,6 +25,7 @@ config X86_32
25 select HAVE_AOUT 25 select HAVE_AOUT
26 select ARCH_WANT_IPC_PARSE_VERSION 26 select ARCH_WANT_IPC_PARSE_VERSION
27 select MODULES_USE_ELF_REL 27 select MODULES_USE_ELF_REL
28 select CLONE_BACKWARDS
28 29
29config X86_64 30config X86_64
30 def_bool 64BIT 31 def_bool 64BIT
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
index ca255a805ed9..bd9a89b67e41 100644
--- a/arch/x86/um/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -1,5 +1,3 @@
1extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
2 void __user *parent_tid, void __user *child_tid);
3#ifdef __i386__ 1#ifdef __i386__
4#include "syscalls_32.h" 2#include "syscalls_32.h"
5#else 3#else
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 232e60504b3a..812e98c098e4 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -24,13 +24,10 @@
24 24
25#define old_mmap sys_old_mmap 25#define old_mmap sys_old_mmap
26 26
27#define ptregs_fork sys_fork
28#define ptregs_iopl sys_iopl 27#define ptregs_iopl sys_iopl
29#define ptregs_vm86old sys_vm86old 28#define ptregs_vm86old sys_vm86old
30#define ptregs_clone i386_clone
31#define ptregs_vm86 sys_vm86 29#define ptregs_vm86 sys_vm86
32#define ptregs_sigaltstack sys_sigaltstack 30#define ptregs_sigaltstack sys_sigaltstack
33#define ptregs_vfork sys_vfork
34 31
35#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; 32#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
36#include <asm/syscalls_32.h> 33#include <asm/syscalls_32.h>
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index db444c7218fe..e8bcea99acdb 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -6,21 +6,6 @@
6#include <linux/syscalls.h> 6#include <linux/syscalls.h>
7#include <sysdep/syscalls.h> 7#include <sysdep/syscalls.h>
8 8
9/*
10 * The prototype on i386 is:
11 *
12 * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
13 *
14 * and the "newtls" arg. on i386 is read by copy_thread directly from the
15 * register saved on the stack.
16 */
17long i386_clone(unsigned long clone_flags, unsigned long newsp,
18 int __user *parent_tid, void *newtls, int __user *child_tid)
19{
20 return sys_clone(clone_flags, newsp, parent_tid, child_tid);
21}
22
23
24long sys_sigaction(int sig, const struct old_sigaction __user *act, 9long sys_sigaction(int sig, const struct old_sigaction __user *act,
25 struct old_sigaction __user *oact) 10 struct old_sigaction __user *oact)
26{ 11{