diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
commit | 9977d9b379cb77e0f67bd6f4563618106e58e11d (patch) | |
tree | 0191accfddf578edb52c69c933d64521e3dce297 /arch | |
parent | cf4af01221579a4e895f43dbfc47598fbfc5a731 (diff) | |
parent | 541880d9a2c7871f6370071d55aa6662d329c51e (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')
246 files changed, 1226 insertions, 3912 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index cc74aaea116c..34884faf98cd 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -342,4 +342,18 @@ config MODULES_USE_ELF_REL | |||
342 | Modules only use ELF REL relocations. Modules with ELF RELA | 342 | Modules only use ELF REL relocations. Modules with ELF RELA |
343 | relocations will give an error. | 343 | relocations will give an error. |
344 | 344 | ||
345 | # | ||
346 | # ABI hall of shame | ||
347 | # | ||
348 | config CLONE_BACKWARDS | ||
349 | bool | ||
350 | help | ||
351 | Architecture has tls passed as the 4th argument of clone(2), | ||
352 | not the 5th one. | ||
353 | |||
354 | config CLONE_BACKWARDS2 | ||
355 | bool | ||
356 | help | ||
357 | Architecture has the first two arguments of clone(2) swapped. | ||
358 | |||
345 | source "kernel/gcov/Kconfig" | 359 | source "kernel/gcov/Kconfig" |
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h index b87755a19554..b4c5b2fbb647 100644 --- a/arch/alpha/include/asm/ptrace.h +++ b/arch/alpha/include/asm/ptrace.h | |||
@@ -78,6 +78,7 @@ struct switch_stack { | |||
78 | 78 | ||
79 | #define current_pt_regs() \ | 79 | #define current_pt_regs() \ |
80 | ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) | 80 | ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) |
81 | #define signal_pt_regs current_pt_regs | ||
81 | 82 | ||
82 | #define force_successful_syscall_return() (current_pt_regs()->r0 = 0) | 83 | #define force_successful_syscall_return() (current_pt_regs()->r0 = 0) |
83 | 84 | ||
diff --git a/arch/alpha/include/asm/signal.h b/arch/alpha/include/asm/signal.h index a9388300abb1..45552862cc10 100644 --- a/arch/alpha/include/asm/signal.h +++ b/arch/alpha/include/asm/signal.h | |||
@@ -164,9 +164,6 @@ struct sigstack { | |||
164 | 164 | ||
165 | #ifdef __KERNEL__ | 165 | #ifdef __KERNEL__ |
166 | #include <asm/sigcontext.h> | 166 | #include <asm/sigcontext.h> |
167 | |||
168 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
169 | |||
170 | #endif | 167 | #endif |
171 | 168 | ||
172 | #endif | 169 | #endif |
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 7826e227e4d0..eb3a4664ced2 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h | |||
@@ -482,6 +482,9 @@ | |||
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 | 484 | #define __ARCH_WANT_SYS_EXECVE |
485 | #define __ARCH_WANT_SYS_FORK | ||
486 | #define __ARCH_WANT_SYS_VFORK | ||
487 | #define __ARCH_WANT_SYS_CLONE | ||
485 | 488 | ||
486 | /* "Conditional" syscalls. What we want is | 489 | /* "Conditional" syscalls. What we want is |
487 | 490 | ||
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c index d1f474d1d44d..9525660c93c0 100644 --- a/arch/alpha/kernel/binfmt_loader.c +++ b/arch/alpha/kernel/binfmt_loader.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #include <linux/binfmts.h> | 5 | #include <linux/binfmts.h> |
6 | #include <linux/a.out.h> | 6 | #include <linux/a.out.h> |
7 | 7 | ||
8 | static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs) | 8 | static int load_binary(struct linux_binprm *bprm) |
9 | { | 9 | { |
10 | struct exec *eh = (struct exec *)bprm->buf; | 10 | struct exec *eh = (struct exec *)bprm->buf; |
11 | unsigned long loader; | 11 | unsigned long loader; |
@@ -37,7 +37,7 @@ static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
37 | retval = prepare_binprm(bprm); | 37 | retval = prepare_binprm(bprm); |
38 | if (retval < 0) | 38 | if (retval < 0) |
39 | return retval; | 39 | return retval; |
40 | return search_binary_handler(bprm,regs); | 40 | return search_binary_handler(bprm); |
41 | } | 41 | } |
42 | 42 | ||
43 | static struct linux_binfmt loader_format = { | 43 | static struct linux_binfmt loader_format = { |
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index a7607832dd4f..f62a994ef126 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S | |||
@@ -612,47 +612,24 @@ ret_from_kernel_thread: | |||
612 | * Special system calls. Most of these are special in that they either | 612 | * Special system calls. Most of these are special in that they either |
613 | * have to play switch_stack games or in some way use the pt_regs struct. | 613 | * have to play switch_stack games or in some way use the pt_regs struct. |
614 | */ | 614 | */ |
615 | .align 4 | ||
616 | .globl sys_fork | ||
617 | .ent sys_fork | ||
618 | sys_fork: | ||
619 | .prologue 0 | ||
620 | mov $sp, $21 | ||
621 | bsr $1, do_switch_stack | ||
622 | bis $31, SIGCHLD, $16 | ||
623 | mov $31, $17 | ||
624 | mov $31, $18 | ||
625 | mov $31, $19 | ||
626 | mov $31, $20 | ||
627 | jsr $26, alpha_clone | ||
628 | bsr $1, undo_switch_stack | ||
629 | ret | ||
630 | .end sys_fork | ||
631 | 615 | ||
616 | .macro fork_like name | ||
632 | .align 4 | 617 | .align 4 |
633 | .globl sys_clone | 618 | .globl alpha_\name |
634 | .ent sys_clone | 619 | .ent alpha_\name |
635 | sys_clone: | 620 | alpha_\name: |
636 | .prologue 0 | 621 | .prologue 0 |
637 | mov $sp, $21 | ||
638 | bsr $1, do_switch_stack | 622 | bsr $1, do_switch_stack |
639 | /* $16, $17, $18, $19, $20 come from the user. */ | 623 | jsr $26, sys_\name |
640 | jsr $26, alpha_clone | 624 | ldq $26, 56($sp) |
641 | bsr $1, undo_switch_stack | 625 | lda $sp, SWITCH_STACK_SIZE($sp) |
642 | ret | 626 | ret |
643 | .end sys_clone | 627 | .end alpha_\name |
628 | .endm | ||
644 | 629 | ||
645 | .align 4 | 630 | fork_like fork |
646 | .globl sys_vfork | 631 | fork_like vfork |
647 | .ent sys_vfork | 632 | fork_like clone |
648 | sys_vfork: | ||
649 | .prologue 0 | ||
650 | mov $sp, $16 | ||
651 | bsr $1, do_switch_stack | ||
652 | jsr $26, alpha_vfork | ||
653 | bsr $1, undo_switch_stack | ||
654 | ret | ||
655 | .end sys_vfork | ||
656 | 633 | ||
657 | .align 4 | 634 | .align 4 |
658 | .globl sys_sigreturn | 635 | .globl sys_sigreturn |
@@ -661,8 +638,6 @@ sys_sigreturn: | |||
661 | .prologue 0 | 638 | .prologue 0 |
662 | lda $9, ret_from_straced | 639 | lda $9, ret_from_straced |
663 | cmpult $26, $9, $9 | 640 | cmpult $26, $9, $9 |
664 | mov $sp, $17 | ||
665 | lda $18, -SWITCH_STACK_SIZE($sp) | ||
666 | lda $sp, -SWITCH_STACK_SIZE($sp) | 641 | lda $sp, -SWITCH_STACK_SIZE($sp) |
667 | jsr $26, do_sigreturn | 642 | jsr $26, do_sigreturn |
668 | bne $9, 1f | 643 | bne $9, 1f |
@@ -678,8 +653,6 @@ sys_rt_sigreturn: | |||
678 | .prologue 0 | 653 | .prologue 0 |
679 | lda $9, ret_from_straced | 654 | lda $9, ret_from_straced |
680 | cmpult $26, $9, $9 | 655 | cmpult $26, $9, $9 |
681 | mov $sp, $17 | ||
682 | lda $18, -SWITCH_STACK_SIZE($sp) | ||
683 | lda $sp, -SWITCH_STACK_SIZE($sp) | 656 | lda $sp, -SWITCH_STACK_SIZE($sp) |
684 | jsr $26, do_rt_sigreturn | 657 | jsr $26, do_rt_sigreturn |
685 | bne $9, 1f | 658 | bne $9, 1f |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 51987dcf79b8..b5d0d0923699 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -235,51 +235,28 @@ release_thread(struct task_struct *dead_task) | |||
235 | } | 235 | } |
236 | 236 | ||
237 | /* | 237 | /* |
238 | * "alpha_clone()".. By the time we get here, the | ||
239 | * non-volatile registers have also been saved on the | ||
240 | * stack. We do some ugly pointer stuff here.. (see | ||
241 | * also copy_thread) | ||
242 | * | ||
243 | * Notice that "fork()" is implemented in terms of clone, | ||
244 | * with parameters (SIGCHLD, 0). | ||
245 | */ | ||
246 | int | ||
247 | alpha_clone(unsigned long clone_flags, unsigned long usp, | ||
248 | int __user *parent_tid, int __user *child_tid, | ||
249 | unsigned long tls_value, struct pt_regs *regs) | ||
250 | { | ||
251 | if (!usp) | ||
252 | usp = rdusp(); | ||
253 | |||
254 | return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid); | ||
255 | } | ||
256 | |||
257 | int | ||
258 | alpha_vfork(struct pt_regs *regs) | ||
259 | { | ||
260 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), | ||
261 | regs, 0, NULL, NULL); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Copy an alpha thread.. | 238 | * Copy an alpha thread.. |
266 | */ | 239 | */ |
267 | 240 | ||
268 | int | 241 | int |
269 | copy_thread(unsigned long clone_flags, unsigned long usp, | 242 | copy_thread(unsigned long clone_flags, unsigned long usp, |
270 | unsigned long arg, | 243 | unsigned long arg, |
271 | struct task_struct * p, struct pt_regs * regs) | 244 | struct task_struct *p) |
272 | { | 245 | { |
273 | extern void ret_from_fork(void); | 246 | extern void ret_from_fork(void); |
274 | extern void ret_from_kernel_thread(void); | 247 | extern void ret_from_kernel_thread(void); |
275 | 248 | ||
276 | struct thread_info *childti = task_thread_info(p); | 249 | struct thread_info *childti = task_thread_info(p); |
277 | struct pt_regs *childregs = task_pt_regs(p); | 250 | struct pt_regs *childregs = task_pt_regs(p); |
251 | struct pt_regs *regs = current_pt_regs(); | ||
278 | struct switch_stack *childstack, *stack; | 252 | struct switch_stack *childstack, *stack; |
279 | unsigned long settls; | 253 | unsigned long settls; |
280 | 254 | ||
281 | childstack = ((struct switch_stack *) childregs) - 1; | 255 | childstack = ((struct switch_stack *) childregs) - 1; |
282 | if (unlikely(!regs)) { | 256 | childti->pcb.ksp = (unsigned long) childstack; |
257 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
258 | |||
259 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
283 | /* kernel thread */ | 260 | /* kernel thread */ |
284 | memset(childstack, 0, | 261 | memset(childstack, 0, |
285 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | 262 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
@@ -288,12 +265,17 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
288 | childstack->r10 = arg; | 265 | childstack->r10 = arg; |
289 | childregs->hae = alpha_mv.hae_cache, | 266 | childregs->hae = alpha_mv.hae_cache, |
290 | childti->pcb.usp = 0; | 267 | childti->pcb.usp = 0; |
291 | childti->pcb.ksp = (unsigned long) childstack; | ||
292 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
293 | return 0; | 268 | return 0; |
294 | } | 269 | } |
270 | /* Note: if CLONE_SETTLS is not set, then we must inherit the | ||
271 | value from the parent, which will have been set by the block | ||
272 | copy in dup_task_struct. This is non-intuitive, but is | ||
273 | required for proper operation in the case of a threaded | ||
274 | application calling fork. */ | ||
275 | if (clone_flags & CLONE_SETTLS) | ||
276 | childti->pcb.unique = regs->r20; | ||
277 | childti->pcb.usp = usp ?: rdusp(); | ||
295 | *childregs = *regs; | 278 | *childregs = *regs; |
296 | settls = regs->r20; | ||
297 | childregs->r0 = 0; | 279 | childregs->r0 = 0; |
298 | childregs->r19 = 0; | 280 | childregs->r19 = 0; |
299 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ | 281 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ |
@@ -301,22 +283,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
301 | stack = ((struct switch_stack *) regs) - 1; | 283 | stack = ((struct switch_stack *) regs) - 1; |
302 | *childstack = *stack; | 284 | *childstack = *stack; |
303 | childstack->r26 = (unsigned long) ret_from_fork; | 285 | childstack->r26 = (unsigned long) ret_from_fork; |
304 | childti->pcb.usp = usp; | ||
305 | childti->pcb.ksp = (unsigned long) childstack; | ||
306 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
307 | |||
308 | /* Set a new TLS for the child thread? Peek back into the | ||
309 | syscall arguments that we saved on syscall entry. Oops, | ||
310 | except we'd have clobbered it with the parent/child set | ||
311 | of r20. Read the saved copy. */ | ||
312 | /* Note: if CLONE_SETTLS is not set, then we must inherit the | ||
313 | value from the parent, which will have been set by the block | ||
314 | copy in dup_task_struct. This is non-intuitive, but is | ||
315 | required for proper operation in the case of a threaded | ||
316 | application calling fork. */ | ||
317 | if (clone_flags & CLONE_SETTLS) | ||
318 | childti->pcb.unique = settls; | ||
319 | |||
320 | return 0; | 286 | return 0; |
321 | } | 287 | } |
322 | 288 | ||
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 32575f85507d..336393c9c11f 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
@@ -160,10 +160,10 @@ extern char compile_time_assert | |||
160 | #define INSN_CALLSYS 0x00000083 | 160 | #define INSN_CALLSYS 0x00000083 |
161 | 161 | ||
162 | static long | 162 | static long |
163 | restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | 163 | restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) |
164 | struct switch_stack *sw) | ||
165 | { | 164 | { |
166 | unsigned long usp; | 165 | unsigned long usp; |
166 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | ||
167 | long i, err = __get_user(regs->pc, &sc->sc_pc); | 167 | long i, err = __get_user(regs->pc, &sc->sc_pc); |
168 | 168 | ||
169 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 169 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
@@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
215 | registers and transfer control from userland. */ | 215 | registers and transfer control from userland. */ |
216 | 216 | ||
217 | asmlinkage void | 217 | asmlinkage void |
218 | do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, | 218 | do_sigreturn(struct sigcontext __user *sc) |
219 | struct switch_stack *sw) | ||
220 | { | 219 | { |
220 | struct pt_regs *regs = current_pt_regs(); | ||
221 | sigset_t set; | 221 | sigset_t set; |
222 | 222 | ||
223 | /* Verify that it's a good sigcontext before using it */ | 223 | /* Verify that it's a good sigcontext before using it */ |
@@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, | |||
228 | 228 | ||
229 | set_current_blocked(&set); | 229 | set_current_blocked(&set); |
230 | 230 | ||
231 | if (restore_sigcontext(sc, regs, sw)) | 231 | if (restore_sigcontext(sc, regs)) |
232 | goto give_sigsegv; | 232 | goto give_sigsegv; |
233 | 233 | ||
234 | /* Send SIGTRAP if we're single-stepping: */ | 234 | /* Send SIGTRAP if we're single-stepping: */ |
@@ -249,9 +249,9 @@ give_sigsegv: | |||
249 | } | 249 | } |
250 | 250 | ||
251 | asmlinkage void | 251 | asmlinkage void |
252 | do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, | 252 | do_rt_sigreturn(struct rt_sigframe __user *frame) |
253 | struct switch_stack *sw) | ||
254 | { | 253 | { |
254 | struct pt_regs *regs = current_pt_regs(); | ||
255 | sigset_t set; | 255 | sigset_t set; |
256 | 256 | ||
257 | /* Verify that it's a good ucontext_t before using it */ | 257 | /* Verify that it's a good ucontext_t before using it */ |
@@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, | |||
262 | 262 | ||
263 | set_current_blocked(&set); | 263 | set_current_blocked(&set); |
264 | 264 | ||
265 | if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) | 265 | if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) |
266 | goto give_sigsegv; | 266 | goto give_sigsegv; |
267 | 267 | ||
268 | /* Send SIGTRAP if we're single-stepping: */ | 268 | /* Send SIGTRAP if we're single-stepping: */ |
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 2ac6b45c3e00..4284ec798ec9 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S | |||
@@ -12,7 +12,7 @@ | |||
12 | sys_call_table: | 12 | sys_call_table: |
13 | .quad alpha_ni_syscall /* 0 */ | 13 | .quad alpha_ni_syscall /* 0 */ |
14 | .quad sys_exit | 14 | .quad sys_exit |
15 | .quad sys_fork | 15 | .quad alpha_fork |
16 | .quad sys_read | 16 | .quad sys_read |
17 | .quad sys_write | 17 | .quad sys_write |
18 | .quad alpha_ni_syscall /* 5 */ | 18 | .quad alpha_ni_syscall /* 5 */ |
@@ -76,7 +76,7 @@ sys_call_table: | |||
76 | .quad sys_getpgrp | 76 | .quad sys_getpgrp |
77 | .quad sys_getpagesize | 77 | .quad sys_getpagesize |
78 | .quad alpha_ni_syscall /* 65 */ | 78 | .quad alpha_ni_syscall /* 65 */ |
79 | .quad sys_vfork | 79 | .quad alpha_vfork |
80 | .quad sys_newstat | 80 | .quad sys_newstat |
81 | .quad sys_newlstat | 81 | .quad sys_newlstat |
82 | .quad alpha_ni_syscall | 82 | .quad alpha_ni_syscall |
@@ -330,7 +330,7 @@ sys_call_table: | |||
330 | .quad sys_ni_syscall /* 309: old get_kernel_syms */ | 330 | .quad sys_ni_syscall /* 309: old get_kernel_syms */ |
331 | .quad sys_syslog /* 310 */ | 331 | .quad sys_syslog /* 310 */ |
332 | .quad sys_reboot | 332 | .quad sys_reboot |
333 | .quad sys_clone | 333 | .quad alpha_clone |
334 | .quad sys_uselib | 334 | .quad sys_uselib |
335 | .quad sys_mlock | 335 | .quad sys_mlock |
336 | .quad sys_munlock /* 315 */ | 336 | .quad sys_munlock /* 315 */ |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d7d7c2fc5388..08330d9e6a9c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -57,6 +57,7 @@ config ARM | |||
57 | select SYS_SUPPORTS_APM_EMULATION | 57 | select SYS_SUPPORTS_APM_EMULATION |
58 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND | 58 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND |
59 | select MODULES_USE_ELF_REL | 59 | select MODULES_USE_ELF_REL |
60 | select CLONE_BACKWARDS | ||
60 | help | 61 | help |
61 | The ARM series is a line of low-power-consumption RISC chip designs | 62 | The ARM series is a line of low-power-consumption RISC chip designs |
62 | licensed by ARM Ltd and targeted at embedded applications and | 63 | licensed by ARM Ltd and targeted at embedded applications and |
diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h index 5a7963dbd3fb..9a0ea6ab988f 100644 --- a/arch/arm/include/asm/signal.h +++ b/arch/arm/include/asm/signal.h | |||
@@ -35,5 +35,4 @@ struct k_sigaction { | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | #include <asm/sigcontext.h> | 37 | #include <asm/sigcontext.h> |
38 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
39 | #endif | 38 | #endif |
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 8f60b6e6bd41..7cd13cc62624 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
@@ -42,6 +42,9 @@ | |||
42 | #define __ARCH_WANT_SYS_SOCKETCALL | 42 | #define __ARCH_WANT_SYS_SOCKETCALL |
43 | #endif | 43 | #endif |
44 | #define __ARCH_WANT_SYS_EXECVE | 44 | #define __ARCH_WANT_SYS_EXECVE |
45 | #define __ARCH_WANT_SYS_FORK | ||
46 | #define __ARCH_WANT_SYS_VFORK | ||
47 | #define __ARCH_WANT_SYS_CLONE | ||
45 | 48 | ||
46 | /* | 49 | /* |
47 | * "Conditional" syscalls | 50 | * "Conditional" syscalls |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 831cd38c8d99..5935b6a02e6e 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | /* 0 */ CALL(sys_restart_syscall) | 12 | /* 0 */ CALL(sys_restart_syscall) |
13 | CALL(sys_exit) | 13 | CALL(sys_exit) |
14 | CALL(sys_fork_wrapper) | 14 | CALL(sys_fork) |
15 | CALL(sys_read) | 15 | CALL(sys_read) |
16 | CALL(sys_write) | 16 | CALL(sys_write) |
17 | /* 5 */ CALL(sys_open) | 17 | /* 5 */ CALL(sys_open) |
@@ -129,7 +129,7 @@ | |||
129 | CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) | 129 | CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) |
130 | CALL(sys_fsync) | 130 | CALL(sys_fsync) |
131 | CALL(sys_sigreturn_wrapper) | 131 | CALL(sys_sigreturn_wrapper) |
132 | /* 120 */ CALL(sys_clone_wrapper) | 132 | /* 120 */ CALL(sys_clone) |
133 | CALL(sys_setdomainname) | 133 | CALL(sys_setdomainname) |
134 | CALL(sys_newuname) | 134 | CALL(sys_newuname) |
135 | CALL(sys_ni_syscall) /* modify_ldt */ | 135 | CALL(sys_ni_syscall) /* modify_ldt */ |
@@ -199,7 +199,7 @@ | |||
199 | CALL(sys_sendfile) | 199 | CALL(sys_sendfile) |
200 | CALL(sys_ni_syscall) /* getpmsg */ | 200 | CALL(sys_ni_syscall) /* getpmsg */ |
201 | CALL(sys_ni_syscall) /* putpmsg */ | 201 | CALL(sys_ni_syscall) /* putpmsg */ |
202 | /* 190 */ CALL(sys_vfork_wrapper) | 202 | /* 190 */ CALL(sys_vfork) |
203 | CALL(sys_getrlimit) | 203 | CALL(sys_getrlimit) |
204 | CALL(sys_mmap2) | 204 | CALL(sys_mmap2) |
205 | CALL(ABI(sys_truncate64, sys_oabi_truncate64)) | 205 | CALL(ABI(sys_truncate64, sys_oabi_truncate64)) |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 804153c0a9cf..a6c301e90a3b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -502,22 +502,6 @@ sys_syscall: | |||
502 | b sys_ni_syscall | 502 | b sys_ni_syscall |
503 | ENDPROC(sys_syscall) | 503 | ENDPROC(sys_syscall) |
504 | 504 | ||
505 | sys_fork_wrapper: | ||
506 | add r0, sp, #S_OFF | ||
507 | b sys_fork | ||
508 | ENDPROC(sys_fork_wrapper) | ||
509 | |||
510 | sys_vfork_wrapper: | ||
511 | add r0, sp, #S_OFF | ||
512 | b sys_vfork | ||
513 | ENDPROC(sys_vfork_wrapper) | ||
514 | |||
515 | sys_clone_wrapper: | ||
516 | add ip, sp, #S_OFF | ||
517 | str ip, [sp, #4] | ||
518 | b sys_clone | ||
519 | ENDPROC(sys_clone_wrapper) | ||
520 | |||
521 | sys_sigreturn_wrapper: | 505 | sys_sigreturn_wrapper: |
522 | add r0, sp, #S_OFF | 506 | add r0, sp, #S_OFF |
523 | mov why, #0 @ prevent syscall restart handling | 507 | mov why, #0 @ prevent syscall restart handling |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 44bc0b327e2b..c6dec5fc20aa 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -376,17 +376,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | |||
376 | 376 | ||
377 | int | 377 | int |
378 | copy_thread(unsigned long clone_flags, unsigned long stack_start, | 378 | copy_thread(unsigned long clone_flags, unsigned long stack_start, |
379 | unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) | 379 | unsigned long stk_sz, struct task_struct *p) |
380 | { | 380 | { |
381 | struct thread_info *thread = task_thread_info(p); | 381 | struct thread_info *thread = task_thread_info(p); |
382 | struct pt_regs *childregs = task_pt_regs(p); | 382 | struct pt_regs *childregs = task_pt_regs(p); |
383 | 383 | ||
384 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); | 384 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); |
385 | 385 | ||
386 | if (likely(regs)) { | 386 | if (likely(!(p->flags & PF_KTHREAD))) { |
387 | *childregs = *regs; | 387 | *childregs = *current_pt_regs(); |
388 | childregs->ARM_r0 = 0; | 388 | childregs->ARM_r0 = 0; |
389 | childregs->ARM_sp = stack_start; | 389 | if (stack_start) |
390 | childregs->ARM_sp = stack_start; | ||
390 | } else { | 391 | } else { |
391 | memset(childregs, 0, sizeof(struct pt_regs)); | 392 | memset(childregs, 0, sizeof(struct pt_regs)); |
392 | thread->cpu_context.r4 = stk_sz; | 393 | thread->cpu_context.r4 = stk_sz; |
@@ -399,7 +400,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
399 | clear_ptrace_hw_breakpoint(p); | 400 | clear_ptrace_hw_breakpoint(p); |
400 | 401 | ||
401 | if (clone_flags & CLONE_SETTLS) | 402 | if (clone_flags & CLONE_SETTLS) |
402 | thread->tp_value = regs->ARM_r3; | 403 | thread->tp_value = childregs->ARM_r3; |
403 | 404 | ||
404 | thread_notify(THREAD_NOTIFY_COPY, thread); | 405 | thread_notify(THREAD_NOTIFY_COPY, thread); |
405 | 406 | ||
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index c2a898aa57aa..3151f5623d0e 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -28,37 +28,6 @@ | |||
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | /* Fork a new task - this creates a new program thread. | ||
32 | * This is called indirectly via a small wrapper | ||
33 | */ | ||
34 | asmlinkage int sys_fork(struct pt_regs *regs) | ||
35 | { | ||
36 | #ifdef CONFIG_MMU | ||
37 | return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); | ||
38 | #else | ||
39 | /* can not support in nommu mode */ | ||
40 | return(-EINVAL); | ||
41 | #endif | ||
42 | } | ||
43 | |||
44 | /* Clone a task - this clones the calling program thread. | ||
45 | * This is called indirectly via a small wrapper | ||
46 | */ | ||
47 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
48 | int __user *parent_tidptr, int tls_val, | ||
49 | int __user *child_tidptr, struct pt_regs *regs) | ||
50 | { | ||
51 | if (!newsp) | ||
52 | newsp = regs->ARM_sp; | ||
53 | |||
54 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); | ||
55 | } | ||
56 | |||
57 | asmlinkage int sys_vfork(struct pt_regs *regs) | ||
58 | { | ||
59 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); | ||
60 | } | ||
61 | |||
62 | /* | 31 | /* |
63 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle | 32 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle |
64 | * with a different argument ordering. | 33 | * with a different argument ordering. |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 2adf340b8589..f9ccff915918 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -33,6 +33,7 @@ config ARM64 | |||
33 | select RTC_LIB | 33 | select RTC_LIB |
34 | select SPARSE_IRQ | 34 | select SPARSE_IRQ |
35 | select SYSCTL_EXCEPTION_TRACE | 35 | select SYSCTL_EXCEPTION_TRACE |
36 | select CLONE_BACKWARDS | ||
36 | help | 37 | help |
37 | ARM 64-bit (AArch64) Linux support. | 38 | ARM 64-bit (AArch64) Linux support. |
38 | 39 | ||
diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h index a1b00cd6f786..20d63b290665 100644 --- a/arch/arm64/include/asm/syscalls.h +++ b/arch/arm64/include/asm/syscalls.h | |||
@@ -27,12 +27,6 @@ asmlinkage long sys_rt_sigreturn_wrapper(void); | |||
27 | asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, | 27 | asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, |
28 | stack_t __user *uoss); | 28 | stack_t __user *uoss); |
29 | 29 | ||
30 | /* | ||
31 | * AArch64 sys_clone implementation has a different prototype than the generic | ||
32 | * one (additional TLS value argument). | ||
33 | */ | ||
34 | #define sys_clone sys_clone | ||
35 | |||
36 | #include <asm-generic/syscalls.h> | 30 | #include <asm-generic/syscalls.h> |
37 | 31 | ||
38 | #endif /* __ASM_SYSCALLS_H */ | 32 | #endif /* __ASM_SYSCALLS_H */ |
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 43064a8bd99e..d69aeea6da1e 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h | |||
@@ -24,6 +24,9 @@ | |||
24 | #define __ARCH_WANT_SYS_SIGPROCMASK | 24 | #define __ARCH_WANT_SYS_SIGPROCMASK |
25 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 25 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
26 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE | 26 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE |
27 | #define __ARCH_WANT_SYS_FORK | ||
28 | #define __ARCH_WANT_SYS_VFORK | ||
27 | #endif | 29 | #endif |
28 | #define __ARCH_WANT_SYS_EXECVE | 30 | #define __ARCH_WANT_SYS_EXECVE |
31 | #define __ARCH_WANT_SYS_CLONE | ||
29 | #include <uapi/asm/unistd.h> | 32 | #include <uapi/asm/unistd.h> |
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 50104e8ce55d..58432625fdb3 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | __SYSCALL(0, sys_restart_syscall) | 24 | __SYSCALL(0, sys_restart_syscall) |
25 | __SYSCALL(1, sys_exit) | 25 | __SYSCALL(1, sys_exit) |
26 | __SYSCALL(2, compat_sys_fork) | 26 | __SYSCALL(2, sys_fork) |
27 | __SYSCALL(3, sys_read) | 27 | __SYSCALL(3, sys_read) |
28 | __SYSCALL(4, sys_write) | 28 | __SYSCALL(4, sys_write) |
29 | __SYSCALL(5, compat_sys_open) | 29 | __SYSCALL(5, compat_sys_open) |
@@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper) | |||
211 | __SYSCALL(187, compat_sys_sendfile) | 211 | __SYSCALL(187, compat_sys_sendfile) |
212 | __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ | 212 | __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ |
213 | __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ | 213 | __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ |
214 | __SYSCALL(190, compat_sys_vfork) | 214 | __SYSCALL(190, sys_vfork) |
215 | __SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */ | 215 | __SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */ |
216 | __SYSCALL(192, sys_mmap_pgoff) | 216 | __SYSCALL(192, sys_mmap_pgoff) |
217 | __SYSCALL(193, compat_sys_truncate64_wrapper) | 217 | __SYSCALL(193, compat_sys_truncate64_wrapper) |
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 8a5f3341861e..cb0956bc96ed 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c | |||
@@ -234,16 +234,15 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
234 | asmlinkage void ret_from_fork(void) asm("ret_from_fork"); | 234 | asmlinkage void ret_from_fork(void) asm("ret_from_fork"); |
235 | 235 | ||
236 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, | 236 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, |
237 | unsigned long stk_sz, struct task_struct *p, | 237 | unsigned long stk_sz, struct task_struct *p) |
238 | struct pt_regs *regs) | ||
239 | { | 238 | { |
240 | struct pt_regs *childregs = task_pt_regs(p); | 239 | struct pt_regs *childregs = task_pt_regs(p); |
241 | unsigned long tls = p->thread.tp_value; | 240 | unsigned long tls = p->thread.tp_value; |
242 | 241 | ||
243 | memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); | 242 | memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); |
244 | 243 | ||
245 | if (likely(regs)) { | 244 | if (likely(!(p->flags & PF_KTHREAD))) { |
246 | *childregs = *regs; | 245 | *childregs = *current_pt_regs(); |
247 | childregs->regs[0] = 0; | 246 | childregs->regs[0] = 0; |
248 | if (is_compat_thread(task_thread_info(p))) { | 247 | if (is_compat_thread(task_thread_info(p))) { |
249 | if (stack_start) | 248 | if (stack_start) |
@@ -266,7 +265,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
266 | * for the new thread. | 265 | * for the new thread. |
267 | */ | 266 | */ |
268 | if (clone_flags & CLONE_SETTLS) | 267 | if (clone_flags & CLONE_SETTLS) |
269 | tls = regs->regs[3]; | 268 | tls = childregs->regs[3]; |
270 | } else { | 269 | } else { |
271 | memset(childregs, 0, sizeof(struct pt_regs)); | 270 | memset(childregs, 0, sizeof(struct pt_regs)); |
272 | childregs->pstate = PSR_MODE_EL1h; | 271 | childregs->pstate = PSR_MODE_EL1h; |
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index 4364df85050e..8292a9b090f8 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c | |||
@@ -26,17 +26,6 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/syscalls.h> | 27 | #include <linux/syscalls.h> |
28 | 28 | ||
29 | /* | ||
30 | * Clone a task - this clones the calling program thread. | ||
31 | */ | ||
32 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
33 | int __user *parent_tidptr, unsigned long tls_val, | ||
34 | int __user *child_tidptr) | ||
35 | { | ||
36 | return do_fork(clone_flags, newsp, current_pt_regs(), 0, | ||
37 | parent_tidptr, child_tidptr); | ||
38 | } | ||
39 | |||
40 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | 29 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, |
41 | unsigned long prot, unsigned long flags, | 30 | unsigned long prot, unsigned long flags, |
42 | unsigned long fd, off_t off) | 31 | unsigned long fd, off_t off) |
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 6fabc1912da0..f7b05edf8ce3 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c | |||
@@ -28,17 +28,6 @@ | |||
28 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
29 | #include <asm/unistd32.h> | 29 | #include <asm/unistd32.h> |
30 | 30 | ||
31 | asmlinkage int compat_sys_fork(void) | ||
32 | { | ||
33 | return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL); | ||
34 | } | ||
35 | |||
36 | asmlinkage int compat_sys_vfork(void) | ||
37 | { | ||
38 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, | ||
39 | current_pt_regs(), 0, NULL, NULL); | ||
40 | } | ||
41 | |||
42 | asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, | 31 | asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, |
43 | struct compat_timespec __user *interval) | 32 | struct compat_timespec __user *interval) |
44 | { | 33 | { |
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index c2bbc9a72222..202d71a15be1 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -17,6 +17,8 @@ config AVR32 | |||
17 | select GENERIC_CLOCKEVENTS | 17 | select GENERIC_CLOCKEVENTS |
18 | select HAVE_MOD_ARCH_SPECIFIC | 18 | select HAVE_MOD_ARCH_SPECIFIC |
19 | select MODULES_USE_ELF_RELA | 19 | select MODULES_USE_ELF_RELA |
20 | select GENERIC_KERNEL_THREAD | ||
21 | select GENERIC_KERNEL_EXECVE | ||
20 | help | 22 | help |
21 | AVR32 is a high-performance 32-bit RISC microprocessor core, | 23 | AVR32 is a high-performance 32-bit RISC microprocessor core, |
22 | designed for cost-sensitive embedded applications, with particular | 24 | designed for cost-sensitive embedded applications, with particular |
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 87d8baccc60e..48d71c5c898a 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h | |||
@@ -142,9 +142,6 @@ struct task_struct; | |||
142 | /* Free all resources held by a thread */ | 142 | /* Free all resources held by a thread */ |
143 | extern void release_thread(struct task_struct *); | 143 | extern void release_thread(struct task_struct *); |
144 | 144 | ||
145 | /* Create a kernel thread without removing it from tasklists */ | ||
146 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
147 | |||
148 | /* Return saved PC of a blocked thread */ | 145 | /* Return saved PC of a blocked thread */ |
149 | #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) | 146 | #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) |
150 | 147 | ||
diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h index 4d502fd6bad3..9326d182e9e5 100644 --- a/arch/avr32/include/asm/signal.h +++ b/arch/avr32/include/asm/signal.h | |||
@@ -37,6 +37,4 @@ struct k_sigaction { | |||
37 | #include <asm/sigcontext.h> | 37 | #include <asm/sigcontext.h> |
38 | #undef __HAVE_ARCH_SIG_BITOPS | 38 | #undef __HAVE_ARCH_SIG_BITOPS |
39 | 39 | ||
40 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
41 | |||
42 | #endif | 40 | #endif |
diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h index 157b4bd3d5e5..f05a9804e8e2 100644 --- a/arch/avr32/include/asm/unistd.h +++ b/arch/avr32/include/asm/unistd.h | |||
@@ -39,6 +39,10 @@ | |||
39 | #define __ARCH_WANT_SYS_GETPGRP | 39 | #define __ARCH_WANT_SYS_GETPGRP |
40 | #define __ARCH_WANT_SYS_RT_SIGACTION | 40 | #define __ARCH_WANT_SYS_RT_SIGACTION |
41 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 41 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
42 | #define __ARCH_WANT_SYS_EXECVE | ||
43 | #define __ARCH_WANT_SYS_FORK | ||
44 | #define __ARCH_WANT_SYS_VFORK | ||
45 | #define __ARCH_WANT_SYS_CLONE | ||
42 | 46 | ||
43 | /* | 47 | /* |
44 | * "Conditional" syscalls | 48 | * "Conditional" syscalls |
diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 9e2c465ef3a6..119a2e41defe 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile | |||
@@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds | |||
7 | obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o | 7 | obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o |
8 | obj-y += syscall_table.o syscall-stubs.o irq.o | 8 | obj-y += syscall_table.o syscall-stubs.o irq.o |
9 | obj-y += setup.o traps.o ocd.o ptrace.o | 9 | obj-y += setup.o traps.o ocd.o ptrace.o |
10 | obj-y += signal.o sys_avr32.o process.o time.o | 10 | obj-y += signal.o process.o time.o |
11 | obj-y += switch_to.o cpu.o | 11 | obj-y += switch_to.o cpu.o |
12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o | 12 | obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o |
13 | obj-$(CONFIG_KPROBES) += kprobes.o | 13 | obj-$(CONFIG_KPROBES) += kprobes.o |
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index df2884181313..9899d3cc6f03 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S | |||
@@ -251,13 +251,15 @@ syscall_badsys: | |||
251 | .global ret_from_fork | 251 | .global ret_from_fork |
252 | ret_from_fork: | 252 | ret_from_fork: |
253 | call schedule_tail | 253 | call schedule_tail |
254 | mov r12, 0 | ||
255 | rjmp syscall_return | ||
254 | 256 | ||
255 | /* check for syscall tracing */ | 257 | .global ret_from_kernel_thread |
256 | get_thread_info r0 | 258 | ret_from_kernel_thread: |
257 | ld.w r1, r0[TI_flags] | 259 | call schedule_tail |
258 | andl r1, _TIF_ALLWORK_MASK, COH | 260 | mov r12, r0 |
259 | brne syscall_exit_work | 261 | mov lr, r2 /* syscall_return */ |
260 | rjmp syscall_exit_cont | 262 | mov pc, r1 |
261 | 263 | ||
262 | syscall_trace_enter: | 264 | syscall_trace_enter: |
263 | pushm r8-r12 | 265 | pushm r8-r12 |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 1bb0a8abd79b..fd78f58ea79a 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -69,44 +69,6 @@ void machine_restart(char *cmd) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * PC is actually discarded when returning from a system call -- the | ||
73 | * return address must be stored in LR. This function will make sure | ||
74 | * LR points to do_exit before starting the thread. | ||
75 | * | ||
76 | * Also, when returning from fork(), r12 is 0, so we must copy the | ||
77 | * argument as well. | ||
78 | * | ||
79 | * r0 : The argument to the main thread function | ||
80 | * r1 : The address of do_exit | ||
81 | * r2 : The address of the main thread function | ||
82 | */ | ||
83 | asmlinkage extern void kernel_thread_helper(void); | ||
84 | __asm__(" .type kernel_thread_helper, @function\n" | ||
85 | "kernel_thread_helper:\n" | ||
86 | " mov r12, r0\n" | ||
87 | " mov lr, r2\n" | ||
88 | " mov pc, r1\n" | ||
89 | " .size kernel_thread_helper, . - kernel_thread_helper"); | ||
90 | |||
91 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
92 | { | ||
93 | struct pt_regs regs; | ||
94 | |||
95 | memset(®s, 0, sizeof(regs)); | ||
96 | |||
97 | regs.r0 = (unsigned long)arg; | ||
98 | regs.r1 = (unsigned long)fn; | ||
99 | regs.r2 = (unsigned long)do_exit; | ||
100 | regs.lr = (unsigned long)kernel_thread_helper; | ||
101 | regs.pc = (unsigned long)kernel_thread_helper; | ||
102 | regs.sr = MODE_SUPERVISOR; | ||
103 | |||
104 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, | ||
105 | 0, ®s, 0, NULL, NULL); | ||
106 | } | ||
107 | EXPORT_SYMBOL(kernel_thread); | ||
108 | |||
109 | /* | ||
110 | * Free current thread data structures etc | 72 | * Free current thread data structures etc |
111 | */ | 73 | */ |
112 | void exit_thread(void) | 74 | void exit_thread(void) |
@@ -332,26 +294,32 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
332 | } | 294 | } |
333 | 295 | ||
334 | asmlinkage void ret_from_fork(void); | 296 | asmlinkage void ret_from_fork(void); |
297 | asmlinkage void ret_from_kernel_thread(void); | ||
298 | asmlinkage void syscall_return(void); | ||
335 | 299 | ||
336 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 300 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
337 | unsigned long unused, | 301 | unsigned long arg, |
338 | struct task_struct *p, struct pt_regs *regs) | 302 | struct task_struct *p) |
339 | { | 303 | { |
340 | struct pt_regs *childregs; | 304 | struct pt_regs *childregs = task_pt_regs(p); |
341 | 305 | ||
342 | childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; | 306 | if (unlikely(p->flags & PF_KTHREAD)) { |
343 | *childregs = *regs; | 307 | memset(childregs, 0, sizeof(struct pt_regs)); |
344 | 308 | p->thread.cpu_context.r0 = arg; | |
345 | if (user_mode(regs)) | 309 | p->thread.cpu_context.r1 = usp; /* fn */ |
346 | childregs->sp = usp; | 310 | p->thread.cpu_context.r2 = syscall_return; |
347 | else | 311 | p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; |
348 | childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; | 312 | childregs->sr = MODE_SUPERVISOR; |
349 | 313 | } else { | |
350 | childregs->r12 = 0; /* Set return value for child */ | 314 | *childregs = *current_pt_regs(); |
315 | if (usp) | ||
316 | childregs->sp = usp; | ||
317 | childregs->r12 = 0; /* Set return value for child */ | ||
318 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; | ||
319 | } | ||
351 | 320 | ||
352 | p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; | 321 | p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; |
353 | p->thread.cpu_context.ksp = (unsigned long)childregs; | 322 | p->thread.cpu_context.ksp = (unsigned long)childregs; |
354 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; | ||
355 | 323 | ||
356 | clear_tsk_thread_flag(p, TIF_DEBUG); | 324 | clear_tsk_thread_flag(p, TIF_DEBUG); |
357 | if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) | 325 | if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) |
@@ -360,49 +328,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
360 | return 0; | 328 | return 0; |
361 | } | 329 | } |
362 | 330 | ||
363 | /* r12-r8 are dummy parameters to force the compiler to use the stack */ | ||
364 | asmlinkage int sys_fork(struct pt_regs *regs) | ||
365 | { | ||
366 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
367 | } | ||
368 | |||
369 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
370 | void __user *parent_tidptr, void __user *child_tidptr, | ||
371 | struct pt_regs *regs) | ||
372 | { | ||
373 | if (!newsp) | ||
374 | newsp = regs->sp; | ||
375 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, | ||
376 | child_tidptr); | ||
377 | } | ||
378 | |||
379 | asmlinkage int sys_vfork(struct pt_regs *regs) | ||
380 | { | ||
381 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, | ||
382 | 0, NULL, NULL); | ||
383 | } | ||
384 | |||
385 | asmlinkage int sys_execve(const char __user *ufilename, | ||
386 | const char __user *const __user *uargv, | ||
387 | const char __user *const __user *uenvp, | ||
388 | struct pt_regs *regs) | ||
389 | { | ||
390 | int error; | ||
391 | struct filename *filename; | ||
392 | |||
393 | filename = getname(ufilename); | ||
394 | error = PTR_ERR(filename); | ||
395 | if (IS_ERR(filename)) | ||
396 | goto out; | ||
397 | |||
398 | error = do_execve(filename->name, uargv, uenvp, regs); | ||
399 | putname(filename); | ||
400 | |||
401 | out: | ||
402 | return error; | ||
403 | } | ||
404 | |||
405 | |||
406 | /* | 331 | /* |
407 | * This function is supposed to answer the question "who called | 332 | * This function is supposed to answer the question "who called |
408 | * schedule()?" | 333 | * schedule()?" |
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c deleted file mode 100644 index 62635a09ae3e..000000000000 --- a/arch/avr32/kernel/sys_avr32.c +++ /dev/null | |||
@@ -1,24 +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 | #include <linux/unistd.h> | ||
9 | |||
10 | int kernel_execve(const char *file, | ||
11 | const char *const *argv, | ||
12 | const char *const *envp) | ||
13 | { | ||
14 | register long scno asm("r8") = __NR_execve; | ||
15 | register long sc1 asm("r12") = (long)file; | ||
16 | register long sc2 asm("r11") = (long)argv; | ||
17 | register long sc3 asm("r10") = (long)envp; | ||
18 | |||
19 | asm volatile("scall" | ||
20 | : "=r"(sc1) | ||
21 | : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3) | ||
22 | : "cc", "memory"); | ||
23 | return sc1; | ||
24 | } | ||
diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 0447a3e2ba64..275aab9731fd 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S | |||
@@ -32,30 +32,6 @@ __sys_rt_sigreturn: | |||
32 | mov r12, sp | 32 | mov r12, sp |
33 | rjmp sys_rt_sigreturn | 33 | rjmp sys_rt_sigreturn |
34 | 34 | ||
35 | .global __sys_fork | ||
36 | .type __sys_fork,@function | ||
37 | __sys_fork: | ||
38 | mov r12, sp | ||
39 | rjmp sys_fork | ||
40 | |||
41 | .global __sys_clone | ||
42 | .type __sys_clone,@function | ||
43 | __sys_clone: | ||
44 | mov r8, sp | ||
45 | rjmp sys_clone | ||
46 | |||
47 | .global __sys_vfork | ||
48 | .type __sys_vfork,@function | ||
49 | __sys_vfork: | ||
50 | mov r12, sp | ||
51 | rjmp sys_vfork | ||
52 | |||
53 | .global __sys_execve | ||
54 | .type __sys_execve,@function | ||
55 | __sys_execve: | ||
56 | mov r9, sp | ||
57 | rjmp sys_execve | ||
58 | |||
59 | .global __sys_mmap2 | 35 | .global __sys_mmap2 |
60 | .type __sys_mmap2,@function | 36 | .type __sys_mmap2,@function |
61 | __sys_mmap2: | 37 | __sys_mmap2: |
diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 6eba53530d1c..f27bb878da6b 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S | |||
@@ -15,7 +15,7 @@ | |||
15 | sys_call_table: | 15 | sys_call_table: |
16 | .long sys_restart_syscall | 16 | .long sys_restart_syscall |
17 | .long sys_exit | 17 | .long sys_exit |
18 | .long __sys_fork | 18 | .long sys_fork |
19 | .long sys_read | 19 | .long sys_read |
20 | .long sys_write | 20 | .long sys_write |
21 | .long sys_open /* 5 */ | 21 | .long sys_open /* 5 */ |
@@ -24,7 +24,7 @@ sys_call_table: | |||
24 | .long sys_creat | 24 | .long sys_creat |
25 | .long sys_link | 25 | .long sys_link |
26 | .long sys_unlink /* 10 */ | 26 | .long sys_unlink /* 10 */ |
27 | .long __sys_execve | 27 | .long sys_execve |
28 | .long sys_chdir | 28 | .long sys_chdir |
29 | .long sys_time | 29 | .long sys_time |
30 | .long sys_mknod | 30 | .long sys_mknod |
@@ -57,7 +57,7 @@ sys_call_table: | |||
57 | .long sys_dup | 57 | .long sys_dup |
58 | .long sys_pipe | 58 | .long sys_pipe |
59 | .long sys_times | 59 | .long sys_times |
60 | .long __sys_clone | 60 | .long sys_clone |
61 | .long sys_brk /* 45 */ | 61 | .long sys_brk /* 45 */ |
62 | .long sys_setgid | 62 | .long sys_setgid |
63 | .long sys_getgid | 63 | .long sys_getgid |
@@ -127,7 +127,7 @@ sys_call_table: | |||
127 | .long sys_newuname | 127 | .long sys_newuname |
128 | .long sys_adjtimex | 128 | .long sys_adjtimex |
129 | .long sys_mprotect | 129 | .long sys_mprotect |
130 | .long __sys_vfork | 130 | .long sys_vfork |
131 | .long sys_init_module /* 115 */ | 131 | .long sys_init_module /* 115 */ |
132 | .long sys_delete_module | 132 | .long sys_delete_module |
133 | .long sys_quotactl | 133 | .long sys_quotactl |
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index b6f3ad5441c5..ab9ff4075f4d 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig | |||
@@ -45,6 +45,8 @@ config BLACKFIN | |||
45 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS | 45 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS |
46 | select HAVE_MOD_ARCH_SPECIFIC | 46 | select HAVE_MOD_ARCH_SPECIFIC |
47 | select MODULES_USE_ELF_RELA | 47 | select MODULES_USE_ELF_RELA |
48 | select GENERIC_KERNEL_THREAD | ||
49 | select GENERIC_KERNEL_EXECVE | ||
48 | 50 | ||
49 | config GENERIC_CSUM | 51 | config GENERIC_CSUM |
50 | def_bool y | 52 | def_bool y |
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 4ef7cfe43ceb..d0e72e9475a6 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h | |||
@@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
75 | { | 75 | { |
76 | } | 76 | } |
77 | 77 | ||
78 | extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); | ||
79 | |||
80 | /* | 78 | /* |
81 | * Free current thread data structures etc.. | 79 | * Free current thread data structures etc.. |
82 | */ | 80 | */ |
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h index 5b2a0748d7d3..460514a1a4e1 100644 --- a/arch/blackfin/include/asm/unistd.h +++ b/arch/blackfin/include/asm/unistd.h | |||
@@ -446,6 +446,8 @@ | |||
446 | #define __ARCH_WANT_SYS_NICE | 446 | #define __ARCH_WANT_SYS_NICE |
447 | #define __ARCH_WANT_SYS_RT_SIGACTION | 447 | #define __ARCH_WANT_SYS_RT_SIGACTION |
448 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 448 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
449 | #define __ARCH_WANT_SYS_EXECVE | ||
450 | #define __ARCH_WANT_SYS_VFORK | ||
449 | 451 | ||
450 | /* | 452 | /* |
451 | * "Conditional" syscalls | 453 | * "Conditional" syscalls |
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S index f33792cc1a0d..4071265fc4fe 100644 --- a/arch/blackfin/kernel/entry.S +++ b/arch/blackfin/kernel/entry.S | |||
@@ -46,53 +46,14 @@ ENTRY(_ret_from_fork) | |||
46 | SP += -12; | 46 | SP += -12; |
47 | pseudo_long_call _schedule_tail, p5; | 47 | pseudo_long_call _schedule_tail, p5; |
48 | SP += 12; | 48 | SP += 12; |
49 | r0 = [sp + PT_IPEND]; | 49 | p1 = [sp++]; |
50 | cc = bittst(r0,1); | 50 | r0 = [sp++]; |
51 | if cc jump .Lin_kernel; | 51 | cc = p1 == 0; |
52 | if cc jump .Lfork; | ||
53 | sp += -12; | ||
54 | call (p1); | ||
55 | sp += 12; | ||
56 | .Lfork: | ||
52 | RESTORE_CONTEXT | 57 | RESTORE_CONTEXT |
53 | rti; | 58 | rti; |
54 | .Lin_kernel: | ||
55 | bitclr(r0,1); | ||
56 | [sp + PT_IPEND] = r0; | ||
57 | /* do a 'fake' RTI by jumping to [RETI] | ||
58 | * to avoid clearing supervisor mode in child | ||
59 | */ | ||
60 | r0 = [sp + PT_PC]; | ||
61 | [sp + PT_P0] = r0; | ||
62 | |||
63 | RESTORE_ALL_SYS | ||
64 | jump (p0); | ||
65 | ENDPROC(_ret_from_fork) | 59 | ENDPROC(_ret_from_fork) |
66 | |||
67 | ENTRY(_sys_vfork) | ||
68 | r0 = sp; | ||
69 | r0 += 24; | ||
70 | [--sp] = rets; | ||
71 | SP += -12; | ||
72 | pseudo_long_call _bfin_vfork, p2; | ||
73 | SP += 12; | ||
74 | rets = [sp++]; | ||
75 | rts; | ||
76 | ENDPROC(_sys_vfork) | ||
77 | |||
78 | ENTRY(_sys_clone) | ||
79 | r0 = sp; | ||
80 | r0 += 24; | ||
81 | [--sp] = rets; | ||
82 | SP += -12; | ||
83 | pseudo_long_call _bfin_clone, p2; | ||
84 | SP += 12; | ||
85 | rets = [sp++]; | ||
86 | rts; | ||
87 | ENDPROC(_sys_clone) | ||
88 | |||
89 | ENTRY(_sys_rt_sigreturn) | ||
90 | r0 = sp; | ||
91 | r0 += 24; | ||
92 | [--sp] = rets; | ||
93 | SP += -12; | ||
94 | pseudo_long_call _do_rt_sigreturn, p2; | ||
95 | SP += 12; | ||
96 | rets = [sp++]; | ||
97 | rts; | ||
98 | ENDPROC(_sys_rt_sigreturn) | ||
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index bb1cc721fcf7..3e16ad9b0a99 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -102,40 +102,6 @@ void cpu_idle(void) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * This gets run with P1 containing the | ||
106 | * function to call, and R1 containing | ||
107 | * the "args". Note P0 is clobbered on the way here. | ||
108 | */ | ||
109 | void kernel_thread_helper(void); | ||
110 | __asm__(".section .text\n" | ||
111 | ".align 4\n" | ||
112 | "_kernel_thread_helper:\n\t" | ||
113 | "\tsp += -12;\n\t" | ||
114 | "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous"); | ||
115 | |||
116 | /* | ||
117 | * Create a kernel thread. | ||
118 | */ | ||
119 | pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) | ||
120 | { | ||
121 | struct pt_regs regs; | ||
122 | |||
123 | memset(®s, 0, sizeof(regs)); | ||
124 | |||
125 | regs.r1 = (unsigned long)arg; | ||
126 | regs.p1 = (unsigned long)fn; | ||
127 | regs.pc = (unsigned long)kernel_thread_helper; | ||
128 | regs.orig_p0 = -1; | ||
129 | /* Set bit 2 to tell ret_from_fork we should be returning to kernel | ||
130 | mode. */ | ||
131 | regs.ipend = 0x8002; | ||
132 | __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):); | ||
133 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, | ||
134 | NULL); | ||
135 | } | ||
136 | EXPORT_SYMBOL(kernel_thread); | ||
137 | |||
138 | /* | ||
139 | * Do necessary setup to start up a newly executed thread. | 105 | * Do necessary setup to start up a newly executed thread. |
140 | * | 106 | * |
141 | * pass the data segment into user programs if it exists, | 107 | * pass the data segment into user programs if it exists, |
@@ -161,70 +127,48 @@ void flush_thread(void) | |||
161 | { | 127 | { |
162 | } | 128 | } |
163 | 129 | ||
164 | asmlinkage int bfin_vfork(struct pt_regs *regs) | 130 | asmlinkage int bfin_clone(unsigned long clone_flags, unsigned long newsp) |
165 | { | ||
166 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, | ||
167 | NULL); | ||
168 | } | ||
169 | |||
170 | asmlinkage int bfin_clone(struct pt_regs *regs) | ||
171 | { | 131 | { |
172 | unsigned long clone_flags; | ||
173 | unsigned long newsp; | ||
174 | |||
175 | #ifdef __ARCH_SYNC_CORE_DCACHE | 132 | #ifdef __ARCH_SYNC_CORE_DCACHE |
176 | if (current->nr_cpus_allowed == num_possible_cpus()) | 133 | if (current->nr_cpus_allowed == num_possible_cpus()) |
177 | set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); | 134 | set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); |
178 | #endif | 135 | #endif |
179 | 136 | if (newsp) | |
180 | /* syscall2 puts clone_flags in r0 and usp in r1 */ | ||
181 | clone_flags = regs->r0; | ||
182 | newsp = regs->r1; | ||
183 | if (!newsp) | ||
184 | newsp = rdusp(); | ||
185 | else | ||
186 | newsp -= 12; | 137 | newsp -= 12; |
187 | return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); | 138 | return do_fork(clone_flags, newsp, 0, NULL, NULL); |
188 | } | 139 | } |
189 | 140 | ||
190 | int | 141 | int |
191 | copy_thread(unsigned long clone_flags, | 142 | copy_thread(unsigned long clone_flags, |
192 | unsigned long usp, unsigned long topstk, | 143 | unsigned long usp, unsigned long topstk, |
193 | struct task_struct *p, struct pt_regs *regs) | 144 | struct task_struct *p) |
194 | { | 145 | { |
195 | struct pt_regs *childregs; | 146 | struct pt_regs *childregs; |
147 | unsigned long *v; | ||
196 | 148 | ||
197 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 149 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; |
198 | *childregs = *regs; | 150 | v = ((unsigned long *)childregs) - 2; |
199 | childregs->r0 = 0; | 151 | if (unlikely(p->flags & PF_KTHREAD)) { |
152 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
153 | v[0] = usp; | ||
154 | v[1] = topstk; | ||
155 | childregs->orig_p0 = -1; | ||
156 | childregs->ipend = 0x8000; | ||
157 | __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); | ||
158 | p->thread.usp = 0; | ||
159 | } else { | ||
160 | *childregs = *current_pt_regs(); | ||
161 | childregs->r0 = 0; | ||
162 | p->thread.usp = usp ? : rdusp(); | ||
163 | v[0] = v[1] = 0; | ||
164 | } | ||
200 | 165 | ||
201 | p->thread.usp = usp; | 166 | p->thread.ksp = (unsigned long)v; |
202 | p->thread.ksp = (unsigned long)childregs; | ||
203 | p->thread.pc = (unsigned long)ret_from_fork; | 167 | p->thread.pc = (unsigned long)ret_from_fork; |
204 | 168 | ||
205 | return 0; | 169 | return 0; |
206 | } | 170 | } |
207 | 171 | ||
208 | /* | ||
209 | * sys_execve() executes a new program. | ||
210 | */ | ||
211 | asmlinkage int sys_execve(const char __user *name, | ||
212 | const char __user *const __user *argv, | ||
213 | const char __user *const __user *envp) | ||
214 | { | ||
215 | int error; | ||
216 | struct filename *filename; | ||
217 | struct pt_regs *regs = (struct pt_regs *)((&name) + 6); | ||
218 | |||
219 | filename = getname(name); | ||
220 | error = PTR_ERR(filename); | ||
221 | if (IS_ERR(filename)) | ||
222 | return error; | ||
223 | error = do_execve(filename->name, argv, envp, regs); | ||
224 | putname(filename); | ||
225 | return error; | ||
226 | } | ||
227 | |||
228 | unsigned long get_wchan(struct task_struct *p) | 172 | unsigned long get_wchan(struct task_struct *p) |
229 | { | 173 | { |
230 | unsigned long fp, pc; | 174 | unsigned long fp, pc; |
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index 6ed20a1a4af9..84b4be05840c 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
@@ -82,9 +82,9 @@ rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *p | |||
82 | return err; | 82 | return err; |
83 | } | 83 | } |
84 | 84 | ||
85 | asmlinkage int do_rt_sigreturn(unsigned long __unused) | 85 | asmlinkage int sys_rt_sigreturn(void) |
86 | { | 86 | { |
87 | struct pt_regs *regs = (struct pt_regs *)__unused; | 87 | struct pt_regs *regs = current_pt_regs(); |
88 | unsigned long usp = rdusp(); | 88 | unsigned long usp = rdusp(); |
89 | struct rt_sigframe *frame = (struct rt_sigframe *)(usp); | 89 | struct rt_sigframe *frame = (struct rt_sigframe *)(usp); |
90 | sigset_t set; | 90 | sigset_t set; |
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 1c3d2c5bb0bb..86b5a095c5a1 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
@@ -530,61 +530,6 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
530 | jump .Lsyscall_really_exit; | 530 | jump .Lsyscall_really_exit; |
531 | ENDPROC(_trap) | 531 | ENDPROC(_trap) |
532 | 532 | ||
533 | ENTRY(_kernel_execve) | ||
534 | link SIZEOF_PTREGS; | ||
535 | p0 = sp; | ||
536 | r3 = SIZEOF_PTREGS / 4; | ||
537 | r4 = 0(x); | ||
538 | .Lclear_regs: | ||
539 | [p0++] = r4; | ||
540 | r3 += -1; | ||
541 | cc = r3 == 0; | ||
542 | if !cc jump .Lclear_regs (bp); | ||
543 | |||
544 | p0 = sp; | ||
545 | sp += -16; | ||
546 | [sp + 12] = p0; | ||
547 | pseudo_long_call _do_execve, p5; | ||
548 | SP += 16; | ||
549 | cc = r0 == 0; | ||
550 | if ! cc jump .Lexecve_failed; | ||
551 | /* Success. Copy our temporary pt_regs to the top of the kernel | ||
552 | * stack and do a normal exception return. | ||
553 | */ | ||
554 | r1 = sp; | ||
555 | r0 = (-KERNEL_STACK_SIZE) (x); | ||
556 | r1 = r1 & r0; | ||
557 | p2 = r1; | ||
558 | p3 = [p2]; | ||
559 | r0 = KERNEL_STACK_SIZE - 4 (z); | ||
560 | p1 = r0; | ||
561 | p1 = p1 + p2; | ||
562 | |||
563 | p0 = fp; | ||
564 | r4 = [p0--]; | ||
565 | r3 = SIZEOF_PTREGS / 4; | ||
566 | .Lcopy_regs: | ||
567 | r4 = [p0--]; | ||
568 | [p1--] = r4; | ||
569 | r3 += -1; | ||
570 | cc = r3 == 0; | ||
571 | if ! cc jump .Lcopy_regs (bp); | ||
572 | |||
573 | r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); | ||
574 | p1 = r0; | ||
575 | p1 = p1 + p2; | ||
576 | sp = p1; | ||
577 | r0 = syscfg; | ||
578 | [SP + PT_SYSCFG] = r0; | ||
579 | [p3 + (TASK_THREAD + THREAD_KSP)] = sp; | ||
580 | |||
581 | RESTORE_CONTEXT; | ||
582 | rti; | ||
583 | .Lexecve_failed: | ||
584 | unlink; | ||
585 | rts; | ||
586 | ENDPROC(_kernel_execve) | ||
587 | |||
588 | ENTRY(_system_call) | 533 | ENTRY(_system_call) |
589 | /* Store IPEND */ | 534 | /* Store IPEND */ |
590 | p2.l = lo(IPEND); | 535 | p2.l = lo(IPEND); |
@@ -1486,7 +1431,7 @@ ENTRY(_sys_call_table) | |||
1486 | .long _sys_ni_syscall /* old sys_ipc */ | 1431 | .long _sys_ni_syscall /* old sys_ipc */ |
1487 | .long _sys_fsync | 1432 | .long _sys_fsync |
1488 | .long _sys_ni_syscall /* old sys_sigreturn */ | 1433 | .long _sys_ni_syscall /* old sys_sigreturn */ |
1489 | .long _sys_clone /* 120 */ | 1434 | .long _bfin_clone /* 120 */ |
1490 | .long _sys_setdomainname | 1435 | .long _sys_setdomainname |
1491 | .long _sys_newuname | 1436 | .long _sys_newuname |
1492 | .long _sys_ni_syscall /* old sys_modify_ldt */ | 1437 | .long _sys_ni_syscall /* old sys_modify_ldt */ |
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index aee1b569ee6e..66eab3703c75 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig | |||
@@ -18,6 +18,7 @@ config C6X | |||
18 | select OF_EARLY_FLATTREE | 18 | select OF_EARLY_FLATTREE |
19 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
20 | select GENERIC_KERNEL_THREAD | 20 | select GENERIC_KERNEL_THREAD |
21 | select GENERIC_KERNEL_EXECVE | ||
21 | select MODULES_USE_ELF_RELA | 22 | select MODULES_USE_ELF_RELA |
22 | 23 | ||
23 | config MMU | 24 | config MMU |
diff --git a/arch/c6x/include/asm/syscalls.h b/arch/c6x/include/asm/syscalls.h index e7b8991dc07c..df3d05feb153 100644 --- a/arch/c6x/include/asm/syscalls.h +++ b/arch/c6x/include/asm/syscalls.h | |||
@@ -41,10 +41,6 @@ extern long sys_fallocate_c6x(int fd, int mode, | |||
41 | u32 len_lo, u32 len_hi); | 41 | u32 len_lo, u32 len_hi); |
42 | extern int sys_cache_sync(unsigned long s, unsigned long e); | 42 | extern int sys_cache_sync(unsigned long s, unsigned long e); |
43 | 43 | ||
44 | struct pt_regs; | ||
45 | |||
46 | extern asmlinkage long sys_c6x_clone(struct pt_regs *regs); | ||
47 | |||
48 | #include <asm-generic/syscalls.h> | 44 | #include <asm-generic/syscalls.h> |
49 | 45 | ||
50 | #endif /* __ASM_C6X_SYSCALLS_H */ | 46 | #endif /* __ASM_C6X_SYSCALLS_H */ |
diff --git a/arch/c6x/include/uapi/asm/unistd.h b/arch/c6x/include/uapi/asm/unistd.h index 4ff747d12dad..f3987a8703d9 100644 --- a/arch/c6x/include/uapi/asm/unistd.h +++ b/arch/c6x/include/uapi/asm/unistd.h | |||
@@ -14,8 +14,8 @@ | |||
14 | * more details. | 14 | * more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define __ARCH_WANT_KERNEL_EXECVE | ||
18 | #define __ARCH_WANT_SYS_EXECVE | 17 | #define __ARCH_WANT_SYS_EXECVE |
18 | #define __ARCH_WANT_SYS_CLONE | ||
19 | 19 | ||
20 | /* Use the standard ABI for syscalls. */ | 20 | /* Use the standard ABI for syscalls. */ |
21 | #include <asm-generic/unistd.h> | 21 | #include <asm-generic/unistd.h> |
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S index 0ed6157dd256..5239057de4c4 100644 --- a/arch/c6x/kernel/entry.S +++ b/arch/c6x/kernel/entry.S | |||
@@ -415,19 +415,9 @@ ENTRY(ret_from_kernel_thread) | |||
415 | 0: | 415 | 0: |
416 | B .S2 B10 /* call fn */ | 416 | B .S2 B10 /* call fn */ |
417 | LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ | 417 | LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ |
418 | MVKL .S2 sys_exit,B11 | 418 | ADDKPC .S2 ret_from_fork_2,B3,3 |
419 | MVKH .S2 sys_exit,B11 | ||
420 | ADDKPC .S2 0f,B3,1 | ||
421 | 0: | ||
422 | BNOP .S2 B11,5 /* jump to sys_exit */ | ||
423 | ENDPROC(ret_from_kernel_thread) | 419 | ENDPROC(ret_from_kernel_thread) |
424 | 420 | ||
425 | ENTRY(ret_from_kernel_execve) | ||
426 | GET_THREAD_INFO A12 | ||
427 | BNOP .S2 syscall_exit,4 | ||
428 | ADD .D2X A4,-8,SP | ||
429 | ENDPROC(ret_from_kernel_execve) | ||
430 | |||
431 | ;; | 421 | ;; |
432 | ;; These are the interrupt handlers, responsible for calling c6x_do_IRQ() | 422 | ;; These are the interrupt handlers, responsible for calling c6x_do_IRQ() |
433 | ;; | 423 | ;; |
@@ -624,18 +614,6 @@ ENDPROC(sys_sigaltstack) | |||
624 | ;; Special system calls | 614 | ;; Special system calls |
625 | ;; return address is in B3 | 615 | ;; return address is in B3 |
626 | ;; | 616 | ;; |
627 | ENTRY(sys_clone) | ||
628 | ADD .D1X SP,8,A4 | ||
629 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
630 | || MVKL .S1 sys_c6x_clone,A0 | ||
631 | MVKH .S1 sys_c6x_clone,A0 | ||
632 | BNOP .S2X A0,5 | ||
633 | #else | ||
634 | || B .S2 sys_c6x_clone | ||
635 | NOP 5 | ||
636 | #endif | ||
637 | ENDPROC(sys_clone) | ||
638 | |||
639 | ENTRY(sys_rt_sigreturn) | 617 | ENTRY(sys_rt_sigreturn) |
640 | ADD .D1X SP,8,A4 | 618 | ADD .D1X SP,8,A4 |
641 | #ifdef CONFIG_C6X_BIG_KERNEL | 619 | #ifdef CONFIG_C6X_BIG_KERNEL |
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c index 2770d9a9a84e..6434df476f77 100644 --- a/arch/c6x/kernel/process.c +++ b/arch/c6x/kernel/process.c | |||
@@ -112,22 +112,6 @@ void exit_thread(void) | |||
112 | { | 112 | { |
113 | } | 113 | } |
114 | 114 | ||
115 | SYSCALL_DEFINE1(c6x_clone, struct pt_regs *, regs) | ||
116 | { | ||
117 | unsigned long clone_flags; | ||
118 | unsigned long newsp; | ||
119 | |||
120 | /* syscall puts clone_flags in A4 and usp in B4 */ | ||
121 | clone_flags = regs->orig_a4; | ||
122 | if (regs->b4) | ||
123 | newsp = regs->b4; | ||
124 | else | ||
125 | newsp = regs->sp; | ||
126 | |||
127 | return do_fork(clone_flags, newsp, regs, 0, (int __user *)regs->a6, | ||
128 | (int __user *)regs->b6); | ||
129 | } | ||
130 | |||
131 | /* | 115 | /* |
132 | * Do necessary setup to start up a newly executed thread. | 116 | * Do necessary setup to start up a newly executed thread. |
133 | */ | 117 | */ |
@@ -155,13 +139,13 @@ void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp) | |||
155 | */ | 139 | */ |
156 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 140 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
157 | unsigned long ustk_size, | 141 | unsigned long ustk_size, |
158 | struct task_struct *p, struct pt_regs *regs) | 142 | struct task_struct *p) |
159 | { | 143 | { |
160 | struct pt_regs *childregs; | 144 | struct pt_regs *childregs; |
161 | 145 | ||
162 | childregs = task_pt_regs(p); | 146 | childregs = task_pt_regs(p); |
163 | 147 | ||
164 | if (!regs) { | 148 | if (unlikely(p->flags & PF_KTHREAD)) { |
165 | /* case of __kernel_thread: we return to supervisor space */ | 149 | /* case of __kernel_thread: we return to supervisor space */ |
166 | memset(childregs, 0, sizeof(struct pt_regs)); | 150 | memset(childregs, 0, sizeof(struct pt_regs)); |
167 | childregs->sp = (unsigned long)(childregs + 1); | 151 | childregs->sp = (unsigned long)(childregs + 1); |
@@ -170,8 +154,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
170 | childregs->a1 = ustk_size; /* argument */ | 154 | childregs->a1 = ustk_size; /* argument */ |
171 | } else { | 155 | } else { |
172 | /* Otherwise use the given stack */ | 156 | /* Otherwise use the given stack */ |
173 | *childregs = *regs; | 157 | *childregs = *current_pt_regs(); |
174 | childregs->sp = usp; | 158 | if (usp) |
159 | childregs->sp = usp; | ||
175 | p->thread.pc = (unsigned long) ret_from_fork; | 160 | p->thread.pc = (unsigned long) ret_from_fork; |
176 | } | 161 | } |
177 | 162 | ||
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index a67244473a39..0cac6a49f230 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig | |||
@@ -49,6 +49,9 @@ config CRIS | |||
49 | select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 | 49 | select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 |
50 | select GENERIC_CMOS_UPDATE | 50 | select GENERIC_CMOS_UPDATE |
51 | select MODULES_USE_ELF_RELA | 51 | select MODULES_USE_ELF_RELA |
52 | select GENERIC_KERNEL_THREAD | ||
53 | select GENERIC_KERNEL_EXECVE | ||
54 | select CLONE_BACKWARDS2 | ||
52 | 55 | ||
53 | config HZ | 56 | config HZ |
54 | int | 57 | int |
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index 592fbe9dfb62..897bba67bf7a 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S | |||
@@ -35,6 +35,7 @@ | |||
35 | .globl system_call | 35 | .globl system_call |
36 | .globl ret_from_intr | 36 | .globl ret_from_intr |
37 | .globl ret_from_fork | 37 | .globl ret_from_fork |
38 | .globl ret_from_kernel_thread | ||
38 | .globl resume | 39 | .globl resume |
39 | .globl multiple_interrupt | 40 | .globl multiple_interrupt |
40 | .globl hwbreakpoint | 41 | .globl hwbreakpoint |
@@ -81,7 +82,14 @@ ret_from_fork: | |||
81 | jsr schedule_tail | 82 | jsr schedule_tail |
82 | ba ret_from_sys_call | 83 | ba ret_from_sys_call |
83 | nop | 84 | nop |
84 | 85 | ||
86 | ret_from_kernel_thread: | ||
87 | jsr schedule_tail | ||
88 | move.d $r2, $r10 ; argument is here | ||
89 | jsr $r1 ; call the payload | ||
90 | moveq 0, $r9 ; no syscall restarts, TYVM... | ||
91 | ba ret_from_sys_call | ||
92 | |||
85 | ret_from_intr: | 93 | ret_from_intr: |
86 | ;; check for resched if preemptive kernel or if we're going back to user-mode | 94 | ;; check for resched if preemptive kernel or if we're going back to user-mode |
87 | ;; this test matches the user_regs(regs) macro | 95 | ;; this test matches the user_regs(regs) macro |
@@ -586,13 +594,6 @@ _ugdb_handle_breakpoint: | |||
586 | ba do_sigtrap ; SIGTRAP the offending process. | 594 | ba do_sigtrap ; SIGTRAP the offending process. |
587 | pop $dccr ; Restore dccr in delay slot. | 595 | pop $dccr ; Restore dccr in delay slot. |
588 | 596 | ||
589 | .global kernel_execve | ||
590 | kernel_execve: | ||
591 | move.d __NR_execve, $r9 | ||
592 | break 13 | ||
593 | ret | ||
594 | nop | ||
595 | |||
596 | .data | 597 | .data |
597 | 598 | ||
598 | hw_bp_trigs: | 599 | hw_bp_trigs: |
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 15ac7150371f..b1018750cffb 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <arch/svinto.h> | 17 | #include <arch/svinto.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <arch/system.h> | 19 | #include <arch/system.h> |
20 | #include <linux/ptrace.h> | ||
20 | 21 | ||
21 | #ifdef CONFIG_ETRAX_GPIO | 22 | #ifdef CONFIG_ETRAX_GPIO |
22 | void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ | 23 | void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ |
@@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t) | |||
81 | return task_pt_regs(t)->irp; | 82 | return task_pt_regs(t)->irp; |
82 | } | 83 | } |
83 | 84 | ||
84 | static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) | ||
85 | { | ||
86 | fn(arg); | ||
87 | do_exit(-1); /* Should never be called, return bad exit value */ | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Create a kernel thread | ||
92 | */ | ||
93 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
94 | { | ||
95 | struct pt_regs regs; | ||
96 | |||
97 | memset(®s, 0, sizeof(regs)); | ||
98 | |||
99 | /* Don't use r10 since that is set to 0 in copy_thread */ | ||
100 | regs.r11 = (unsigned long)fn; | ||
101 | regs.r12 = (unsigned long)arg; | ||
102 | regs.irp = (unsigned long)kernel_thread_helper; | ||
103 | regs.dccr = 1 << I_DCCR_BITNR; | ||
104 | |||
105 | /* Ok, create the new process.. */ | ||
106 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
107 | } | ||
108 | |||
109 | /* setup the child's kernel stack with a pt_regs and switch_stack on it. | 85 | /* setup the child's kernel stack with a pt_regs and switch_stack on it. |
110 | * it will be un-nested during _resume and _ret_from_sys_call when the | 86 | * it will be un-nested during _resume and _ret_from_sys_call when the |
111 | * new thread is scheduled. | 87 | * new thread is scheduled. |
@@ -115,29 +91,34 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
115 | * | 91 | * |
116 | */ | 92 | */ |
117 | asmlinkage void ret_from_fork(void); | 93 | asmlinkage void ret_from_fork(void); |
94 | asmlinkage void ret_from_kernel_thread(void); | ||
118 | 95 | ||
119 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 96 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
120 | unsigned long unused, | 97 | unsigned long arg, struct task_struct *p) |
121 | struct task_struct *p, struct pt_regs *regs) | ||
122 | { | 98 | { |
123 | struct pt_regs * childregs; | 99 | struct pt_regs *childregs = task_pt_regs(p); |
124 | struct switch_stack *swstack; | 100 | struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; |
125 | 101 | ||
126 | /* put the pt_regs structure at the end of the new kernel stack page and fix it up | 102 | /* put the pt_regs structure at the end of the new kernel stack page and fix it up |
127 | * remember that the task_struct doubles as the kernel stack for the task | 103 | * remember that the task_struct doubles as the kernel stack for the task |
128 | */ | 104 | */ |
129 | 105 | ||
130 | childregs = task_pt_regs(p); | 106 | if (unlikely(p->flags & PF_KTHREAD)) { |
131 | 107 | memset(swstack, 0, | |
132 | *childregs = *regs; /* struct copy of pt_regs */ | 108 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
133 | 109 | swstack->r1 = usp; | |
134 | p->set_child_tid = p->clear_child_tid = NULL; | 110 | swstack->r2 = arg; |
111 | childregs->dccr = 1 << I_DCCR_BITNR; | ||
112 | swstack->return_ip = (unsigned long) ret_from_kernel_thread; | ||
113 | p->thread.ksp = (unsigned long) swstack; | ||
114 | p->thread.usp = 0; | ||
115 | return 0; | ||
116 | } | ||
117 | *childregs = *current_pt_regs(); /* struct copy of pt_regs */ | ||
135 | 118 | ||
136 | childregs->r10 = 0; /* child returns 0 after a fork/clone */ | 119 | childregs->r10 = 0; /* child returns 0 after a fork/clone */ |
137 | |||
138 | /* put the switch stack right below the pt_regs */ | ||
139 | 120 | ||
140 | swstack = ((struct switch_stack *)childregs) - 1; | 121 | /* put the switch stack right below the pt_regs */ |
141 | 122 | ||
142 | swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ | 123 | swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ |
143 | 124 | ||
@@ -147,7 +128,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
147 | 128 | ||
148 | /* fix the user-mode stackpointer */ | 129 | /* fix the user-mode stackpointer */ |
149 | 130 | ||
150 | p->thread.usp = usp; | 131 | p->thread.usp = usp ?: rdusp(); |
151 | 132 | ||
152 | /* and the kernel-mode one */ | 133 | /* and the kernel-mode one */ |
153 | 134 | ||
@@ -161,70 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
161 | return 0; | 142 | return 0; |
162 | } | 143 | } |
163 | 144 | ||
164 | /* | ||
165 | * Be aware of the "magic" 7th argument in the four system-calls below. | ||
166 | * They need the latest stackframe, which is put as the 7th argument by | ||
167 | * entry.S. The previous arguments are dummies or actually used, but need | ||
168 | * to be defined to reach the 7th argument. | ||
169 | * | ||
170 | * N.B.: Another method to get the stackframe is to use current_regs(). But | ||
171 | * it returns the latest stack-frame stacked when going from _user mode_ and | ||
172 | * some of these (at least sys_clone) are called from kernel-mode sometimes | ||
173 | * (for example during kernel_thread, above) and thus cannot use it. Thus, | ||
174 | * to be sure not to get any surprises, we use the method for the other calls | ||
175 | * as well. | ||
176 | */ | ||
177 | |||
178 | asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, | ||
179 | struct pt_regs *regs) | ||
180 | { | ||
181 | return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
182 | } | ||
183 | |||
184 | /* if newusp is 0, we just grab the old usp */ | ||
185 | /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ | ||
186 | asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, | ||
187 | int* parent_tid, int* child_tid, long mof, long srp, | ||
188 | struct pt_regs *regs) | ||
189 | { | ||
190 | if (!newusp) | ||
191 | newusp = rdusp(); | ||
192 | return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); | ||
193 | } | ||
194 | |||
195 | /* vfork is a system call in i386 because of register-pressure - maybe | ||
196 | * we can remove it and handle it in libc but we put it here until then. | ||
197 | */ | ||
198 | |||
199 | asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, | ||
200 | struct pt_regs *regs) | ||
201 | { | ||
202 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * sys_execve() executes a new program. | ||
207 | */ | ||
208 | asmlinkage int sys_execve(const char *fname, | ||
209 | const char *const *argv, | ||
210 | const char *const *envp, | ||
211 | long r13, long mof, long srp, | ||
212 | struct pt_regs *regs) | ||
213 | { | ||
214 | int error; | ||
215 | struct filename *filename; | ||
216 | |||
217 | filename = getname(fname); | ||
218 | error = PTR_ERR(filename); | ||
219 | |||
220 | if (IS_ERR(filename)) | ||
221 | goto out; | ||
222 | error = do_execve(filename->name, argv, envp, regs); | ||
223 | putname(filename); | ||
224 | out: | ||
225 | return error; | ||
226 | } | ||
227 | |||
228 | unsigned long get_wchan(struct task_struct *p) | 145 | unsigned long get_wchan(struct task_struct *p) |
229 | { | 146 | { |
230 | #if 0 | 147 | #if 0 |
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index c3ea4694fbaf..faa644111feb 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S | |||
@@ -31,6 +31,7 @@ | |||
31 | .globl system_call | 31 | .globl system_call |
32 | .globl ret_from_intr | 32 | .globl ret_from_intr |
33 | .globl ret_from_fork | 33 | .globl ret_from_fork |
34 | .globl ret_from_kernel_thread | ||
34 | .globl resume | 35 | .globl resume |
35 | .globl multiple_interrupt | 36 | .globl multiple_interrupt |
36 | .globl nmi_interrupt | 37 | .globl nmi_interrupt |
@@ -84,6 +85,18 @@ ret_from_fork: | |||
84 | nop | 85 | nop |
85 | .size ret_from_fork, . - ret_from_fork | 86 | .size ret_from_fork, . - ret_from_fork |
86 | 87 | ||
88 | .type ret_from_kernel_thread,@function | ||
89 | ret_from_kernel_thread: | ||
90 | jsr schedule_tail | ||
91 | nop | ||
92 | move.d $r2, $r10 | ||
93 | jsr $r1 | ||
94 | nop | ||
95 | moveq 0, $r9 ; no syscall restarts, TYVM... | ||
96 | ba ret_from_sys_call | ||
97 | nop | ||
98 | .size ret_from_kernel_thread, . - ret_from_kernel_thread | ||
99 | |||
87 | .type ret_from_intr,@function | 100 | .type ret_from_intr,@function |
88 | ret_from_intr: | 101 | ret_from_intr: |
89 | ;; Check for resched if preemptive kernel, or if we're going back to | 102 | ;; Check for resched if preemptive kernel, or if we're going back to |
@@ -531,15 +544,6 @@ _ugdb_handle_exception: | |||
531 | ba do_sigtrap ; SIGTRAP the offending process. | 544 | ba do_sigtrap ; SIGTRAP the offending process. |
532 | move.d [$sp+], $r0 ; Restore R0 in delay slot. | 545 | move.d [$sp+], $r0 ; Restore R0 in delay slot. |
533 | 546 | ||
534 | .global kernel_execve | ||
535 | .type kernel_execve,@function | ||
536 | kernel_execve: | ||
537 | move.d __NR_execve, $r9 | ||
538 | break 13 | ||
539 | ret | ||
540 | nop | ||
541 | .size kernel_execve, . - kernel_execve | ||
542 | |||
543 | .data | 547 | .data |
544 | 548 | ||
545 | .section .rodata,"a" | 549 | .section .rodata,"a" |
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 4e9992246359..2b23ef0e4452 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <hwregs/reg_map.h> | 16 | #include <hwregs/reg_map.h> |
17 | #include <hwregs/timer_defs.h> | 17 | #include <hwregs/timer_defs.h> |
18 | #include <hwregs/intr_vect_defs.h> | 18 | #include <hwregs/intr_vect_defs.h> |
19 | #include <linux/ptrace.h> | ||
19 | 20 | ||
20 | extern void stop_watchdog(void); | 21 | extern void stop_watchdog(void); |
21 | 22 | ||
@@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t) | |||
94 | return task_pt_regs(t)->erp; | 95 | return task_pt_regs(t)->erp; |
95 | } | 96 | } |
96 | 97 | ||
97 | static void | ||
98 | kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) | ||
99 | { | ||
100 | fn(arg); | ||
101 | do_exit(-1); /* Should never be called, return bad exit value. */ | ||
102 | } | ||
103 | |||
104 | /* Create a kernel thread. */ | ||
105 | int | ||
106 | kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
107 | { | ||
108 | struct pt_regs regs; | ||
109 | |||
110 | memset(®s, 0, sizeof(regs)); | ||
111 | |||
112 | /* Don't use r10 since that is set to 0 in copy_thread. */ | ||
113 | regs.r11 = (unsigned long) fn; | ||
114 | regs.r12 = (unsigned long) arg; | ||
115 | regs.erp = (unsigned long) kernel_thread_helper; | ||
116 | regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); | ||
117 | |||
118 | /* Create the new process. */ | ||
119 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
120 | } | ||
121 | |||
122 | /* | 98 | /* |
123 | * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. | 99 | * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. |
124 | * It will be unnested during _resume and _ret_from_sys_call when the new thread | 100 | * It will be unnested during _resume and _ret_from_sys_call when the new thread |
@@ -129,34 +105,42 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
129 | */ | 105 | */ |
130 | 106 | ||
131 | extern asmlinkage void ret_from_fork(void); | 107 | extern asmlinkage void ret_from_fork(void); |
108 | extern asmlinkage void ret_from_kernel_thread(void); | ||
132 | 109 | ||
133 | int | 110 | int |
134 | copy_thread(unsigned long clone_flags, unsigned long usp, | 111 | copy_thread(unsigned long clone_flags, unsigned long usp, |
135 | unsigned long unused, | 112 | unsigned long arg, struct task_struct *p) |
136 | struct task_struct *p, struct pt_regs *regs) | ||
137 | { | 113 | { |
138 | struct pt_regs *childregs; | 114 | struct pt_regs *childregs = task_pt_regs(p); |
139 | struct switch_stack *swstack; | 115 | struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; |
140 | 116 | ||
141 | /* | 117 | /* |
142 | * Put the pt_regs structure at the end of the new kernel stack page and | 118 | * Put the pt_regs structure at the end of the new kernel stack page and |
143 | * fix it up. Note: the task_struct doubles as the kernel stack for the | 119 | * fix it up. Note: the task_struct doubles as the kernel stack for the |
144 | * task. | 120 | * task. |
145 | */ | 121 | */ |
146 | childregs = task_pt_regs(p); | 122 | if (unlikely(p->flags & PF_KTHREAD)) { |
147 | *childregs = *regs; /* Struct copy of pt_regs. */ | 123 | memset(swstack, 0, |
148 | p->set_child_tid = p->clear_child_tid = NULL; | 124 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
125 | swstack->r1 = usp; | ||
126 | swstack->r2 = arg; | ||
127 | childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); | ||
128 | swstack->return_ip = (unsigned long) ret_from_kernel_thread; | ||
129 | p->thread.ksp = (unsigned long) swstack; | ||
130 | p->thread.usp = 0; | ||
131 | return 0; | ||
132 | } | ||
133 | *childregs = *current_pt_regs(); /* Struct copy of pt_regs. */ | ||
149 | childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ | 134 | childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ |
150 | 135 | ||
151 | /* Set a new TLS ? | 136 | /* Set a new TLS ? |
152 | * The TLS is in $mof because it is the 5th argument to sys_clone. | 137 | * The TLS is in $mof because it is the 5th argument to sys_clone. |
153 | */ | 138 | */ |
154 | if (p->mm && (clone_flags & CLONE_SETTLS)) { | 139 | if (p->mm && (clone_flags & CLONE_SETTLS)) { |
155 | task_thread_info(p)->tls = regs->mof; | 140 | task_thread_info(p)->tls = childregs->mof; |
156 | } | 141 | } |
157 | 142 | ||
158 | /* Put the switch stack right below the pt_regs. */ | 143 | /* Put the switch stack right below the pt_regs. */ |
159 | swstack = ((struct switch_stack *) childregs) - 1; | ||
160 | 144 | ||
161 | /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ | 145 | /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ |
162 | swstack->r9 = 0; | 146 | swstack->r9 = 0; |
@@ -168,76 +152,12 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
168 | swstack->return_ip = (unsigned long) ret_from_fork; | 152 | swstack->return_ip = (unsigned long) ret_from_fork; |
169 | 153 | ||
170 | /* Fix the user-mode and kernel-mode stackpointer. */ | 154 | /* Fix the user-mode and kernel-mode stackpointer. */ |
171 | p->thread.usp = usp; | 155 | p->thread.usp = usp ?: rdusp(); |
172 | p->thread.ksp = (unsigned long) swstack; | 156 | p->thread.ksp = (unsigned long) swstack; |
173 | 157 | ||
174 | return 0; | 158 | return 0; |
175 | } | 159 | } |
176 | 160 | ||
177 | /* | ||
178 | * Be aware of the "magic" 7th argument in the four system-calls below. | ||
179 | * They need the latest stackframe, which is put as the 7th argument by | ||
180 | * entry.S. The previous arguments are dummies or actually used, but need | ||
181 | * to be defined to reach the 7th argument. | ||
182 | * | ||
183 | * N.B.: Another method to get the stackframe is to use current_regs(). But | ||
184 | * it returns the latest stack-frame stacked when going from _user mode_ and | ||
185 | * some of these (at least sys_clone) are called from kernel-mode sometimes | ||
186 | * (for example during kernel_thread, above) and thus cannot use it. Thus, | ||
187 | * to be sure not to get any surprises, we use the method for the other calls | ||
188 | * as well. | ||
189 | */ | ||
190 | asmlinkage int | ||
191 | sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, | ||
192 | struct pt_regs *regs) | ||
193 | { | ||
194 | return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
195 | } | ||
196 | |||
197 | /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ | ||
198 | asmlinkage int | ||
199 | sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid, | ||
200 | unsigned long tls, long srp, struct pt_regs *regs) | ||
201 | { | ||
202 | if (!newusp) | ||
203 | newusp = rdusp(); | ||
204 | |||
205 | return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * vfork is a system call in i386 because of register-pressure - maybe | ||
210 | * we can remove it and handle it in libc but we put it here until then. | ||
211 | */ | ||
212 | asmlinkage int | ||
213 | sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, | ||
214 | struct pt_regs *regs) | ||
215 | { | ||
216 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
217 | } | ||
218 | |||
219 | /* sys_execve() executes a new program. */ | ||
220 | asmlinkage int | ||
221 | sys_execve(const char *fname, | ||
222 | const char *const *argv, | ||
223 | const char *const *envp, long r13, long mof, long srp, | ||
224 | struct pt_regs *regs) | ||
225 | { | ||
226 | int error; | ||
227 | struct filename *filename; | ||
228 | |||
229 | filename = getname(fname); | ||
230 | error = PTR_ERR(filename); | ||
231 | |||
232 | if (IS_ERR(filename)) | ||
233 | goto out; | ||
234 | |||
235 | error = do_execve(filename->name, argv, envp, regs); | ||
236 | putname(filename); | ||
237 | out: | ||
238 | return error; | ||
239 | } | ||
240 | |||
241 | unsigned long | 161 | unsigned long |
242 | get_wchan(struct task_struct *p) | 162 | get_wchan(struct task_struct *p) |
243 | { | 163 | { |
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h index ef4e1bc3efc8..675823f70c0f 100644 --- a/arch/cris/include/asm/processor.h +++ b/arch/cris/include/asm/processor.h | |||
@@ -49,8 +49,6 @@ struct task_struct; | |||
49 | #define task_pt_regs(task) user_regs(task_thread_info(task)) | 49 | #define task_pt_regs(task) user_regs(task_thread_info(task)) |
50 | #define current_regs() task_pt_regs(current) | 50 | #define current_regs() task_pt_regs(current) |
51 | 51 | ||
52 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
53 | |||
54 | unsigned long get_wchan(struct task_struct *p); | 52 | unsigned long get_wchan(struct task_struct *p); |
55 | 53 | ||
56 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) | 54 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) |
diff --git a/arch/cris/include/asm/signal.h b/arch/cris/include/asm/signal.h index ea6af9aad76c..72dbbf59dfae 100644 --- a/arch/cris/include/asm/signal.h +++ b/arch/cris/include/asm/signal.h | |||
@@ -152,12 +152,6 @@ typedef struct sigaltstack { | |||
152 | 152 | ||
153 | #ifdef __KERNEL__ | 153 | #ifdef __KERNEL__ |
154 | #include <asm/sigcontext.h> | 154 | #include <asm/sigcontext.h> |
155 | |||
156 | /* here we could define asm-optimized sigaddset, sigdelset etc. operations. | ||
157 | * if we don't, generic ones are used from linux/signal.h | ||
158 | */ | ||
159 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
160 | |||
161 | #endif /* __KERNEL__ */ | 155 | #endif /* __KERNEL__ */ |
162 | 156 | ||
163 | #endif | 157 | #endif |
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h index 51873a446f87..f27b542e0ebc 100644 --- a/arch/cris/include/asm/unistd.h +++ b/arch/cris/include/asm/unistd.h | |||
@@ -371,6 +371,10 @@ | |||
371 | #define __ARCH_WANT_SYS_SIGPROCMASK | 371 | #define __ARCH_WANT_SYS_SIGPROCMASK |
372 | #define __ARCH_WANT_SYS_RT_SIGACTION | 372 | #define __ARCH_WANT_SYS_RT_SIGACTION |
373 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 373 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
374 | #define __ARCH_WANT_SYS_EXECVE | ||
375 | #define __ARCH_WANT_SYS_FORK | ||
376 | #define __ARCH_WANT_SYS_VFORK | ||
377 | #define __ARCH_WANT_SYS_CLONE | ||
374 | 378 | ||
375 | /* | 379 | /* |
376 | * "Conditional" syscalls | 380 | * "Conditional" syscalls |
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 7ac000f6a888..5868cee20ebd 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c | |||
@@ -30,7 +30,6 @@ extern void __negdi2(void); | |||
30 | extern void iounmap(volatile void * __iomem); | 30 | extern void iounmap(volatile void * __iomem); |
31 | 31 | ||
32 | /* Platform dependent support */ | 32 | /* Platform dependent support */ |
33 | EXPORT_SYMBOL(kernel_thread); | ||
34 | EXPORT_SYMBOL(get_cmos_time); | 33 | EXPORT_SYMBOL(get_cmos_time); |
35 | EXPORT_SYMBOL(loops_per_usec); | 34 | EXPORT_SYMBOL(loops_per_usec); |
36 | 35 | ||
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index 2358634cacca..1807d8ea8cb5 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h | |||
@@ -30,6 +30,9 @@ | |||
30 | #define __ARCH_WANT_SYS_RT_SIGACTION | 30 | #define __ARCH_WANT_SYS_RT_SIGACTION |
31 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 31 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
32 | #define __ARCH_WANT_SYS_EXECVE | 32 | #define __ARCH_WANT_SYS_EXECVE |
33 | #define __ARCH_WANT_SYS_FORK | ||
34 | #define __ARCH_WANT_SYS_VFORK | ||
35 | #define __ARCH_WANT_SYS_CLONE | ||
33 | 36 | ||
34 | /* | 37 | /* |
35 | * "Conditional" syscalls | 38 | * "Conditional" syscalls |
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 7e33215f1d8f..23916b2a12a2 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c | |||
@@ -139,42 +139,12 @@ inline unsigned long user_stack(const struct pt_regs *regs) | |||
139 | return user_mode(regs) ? regs->sp : 0; | 139 | return user_mode(regs) ? regs->sp : 0; |
140 | } | 140 | } |
141 | 141 | ||
142 | asmlinkage int sys_fork(void) | ||
143 | { | ||
144 | #ifndef CONFIG_MMU | ||
145 | /* fork almost works, enough to trick you into looking elsewhere:-( */ | ||
146 | return -EINVAL; | ||
147 | #else | ||
148 | return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL); | ||
149 | #endif | ||
150 | } | ||
151 | |||
152 | asmlinkage int sys_vfork(void) | ||
153 | { | ||
154 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0, | ||
155 | NULL, NULL); | ||
156 | } | ||
157 | |||
158 | /*****************************************************************************/ | ||
159 | /* | ||
160 | * clone a process | ||
161 | * - tlsptr is retrieved by copy_thread() | ||
162 | */ | ||
163 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
164 | int __user *parent_tidptr, int __user *child_tidptr, | ||
165 | int __user *tlsptr) | ||
166 | { | ||
167 | if (!newsp) | ||
168 | newsp = user_stack(__frame); | ||
169 | return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr); | ||
170 | } /* end sys_clone() */ | ||
171 | |||
172 | /* | 142 | /* |
173 | * set up the kernel stack and exception frames for a new process | 143 | * set up the kernel stack and exception frames for a new process |
174 | */ | 144 | */ |
175 | int copy_thread(unsigned long clone_flags, | 145 | int copy_thread(unsigned long clone_flags, |
176 | unsigned long usp, unsigned long arg, | 146 | unsigned long usp, unsigned long arg, |
177 | struct task_struct *p, struct pt_regs *regs) | 147 | struct task_struct *p) |
178 | { | 148 | { |
179 | struct pt_regs *childregs; | 149 | struct pt_regs *childregs; |
180 | 150 | ||
@@ -182,9 +152,7 @@ int copy_thread(unsigned long clone_flags, | |||
182 | (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); | 152 | (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); |
183 | 153 | ||
184 | /* set up the userspace frame (the only place that the USP is stored) */ | 154 | /* set up the userspace frame (the only place that the USP is stored) */ |
185 | *childregs = *__kernel_frame0_ptr; | 155 | *childregs = *current_pt_regs(); |
186 | |||
187 | p->set_child_tid = p->clear_child_tid = NULL; | ||
188 | 156 | ||
189 | p->thread.frame = childregs; | 157 | p->thread.frame = childregs; |
190 | p->thread.curr = p; | 158 | p->thread.curr = p; |
@@ -193,18 +161,15 @@ int copy_thread(unsigned long clone_flags, | |||
193 | p->thread.lr = 0; | 161 | p->thread.lr = 0; |
194 | p->thread.frame0 = childregs; | 162 | p->thread.frame0 = childregs; |
195 | 163 | ||
196 | if (unlikely(!regs)) { | 164 | if (unlikely(p->flags & PF_KTHREAD)) { |
197 | childregs->gr9 = usp; /* function */ | 165 | childregs->gr9 = usp; /* function */ |
198 | childregs->gr8 = arg; | 166 | childregs->gr8 = arg; |
199 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | 167 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
200 | save_user_regs(p->thread.user); | 168 | save_user_regs(p->thread.user); |
201 | return 0; | 169 | return 0; |
202 | } | 170 | } |
203 | 171 | if (usp) | |
204 | /* set up the userspace frame (the only place that the USP is stored) */ | 172 | childregs->sp = usp; |
205 | *childregs = *regs; | ||
206 | |||
207 | childregs->sp = usp; | ||
208 | childregs->next_frame = NULL; | 173 | childregs->next_frame = NULL; |
209 | 174 | ||
210 | p->thread.pc = (unsigned long) ret_from_fork; | 175 | p->thread.pc = (unsigned long) ret_from_fork; |
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 98fabd10e95f..04bef4d25b4a 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
@@ -8,6 +8,8 @@ config H8300 | |||
8 | select GENERIC_IRQ_SHOW | 8 | select GENERIC_IRQ_SHOW |
9 | select GENERIC_CPU_DEVICES | 9 | select GENERIC_CPU_DEVICES |
10 | select MODULES_USE_ELF_RELA | 10 | select MODULES_USE_ELF_RELA |
11 | select GENERIC_KERNEL_THREAD | ||
12 | select GENERIC_KERNEL_EXECVE | ||
11 | 13 | ||
12 | config SYMBOL_PREFIX | 14 | config SYMBOL_PREFIX |
13 | string | 15 | string |
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h index 4c9f6f87b617..4b0ca49bb463 100644 --- a/arch/h8300/include/asm/processor.h +++ b/arch/h8300/include/asm/processor.h | |||
@@ -107,8 +107,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
107 | { | 107 | { |
108 | } | 108 | } |
109 | 109 | ||
110 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
111 | |||
112 | /* | 110 | /* |
113 | * Free current thread data structures etc.. | 111 | * Free current thread data structures etc.. |
114 | */ | 112 | */ |
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h index d09c440bdba7..7468589a128b 100644 --- a/arch/h8300/include/asm/ptrace.h +++ b/arch/h8300/include/asm/ptrace.h | |||
@@ -60,6 +60,9 @@ struct pt_regs { | |||
60 | #define user_mode(regs) (!((regs)->ccr & PS_S)) | 60 | #define user_mode(regs) (!((regs)->ccr & PS_S)) |
61 | #define instruction_pointer(regs) ((regs)->pc) | 61 | #define instruction_pointer(regs) ((regs)->pc) |
62 | #define profile_pc(regs) instruction_pointer(regs) | 62 | #define profile_pc(regs) instruction_pointer(regs) |
63 | #define current_pt_regs() ((struct pt_regs *) \ | ||
64 | (THREAD_SIZE + (unsigned long)current_thread_info()) - 1) | ||
65 | #define signal_pt_regs() ((struct pt_regs *)current->thread.esp0) | ||
63 | #endif /* __KERNEL__ */ | 66 | #endif /* __KERNEL__ */ |
64 | #endif /* __ASSEMBLY__ */ | 67 | #endif /* __ASSEMBLY__ */ |
65 | #endif /* _H8300_PTRACE_H */ | 68 | #endif /* _H8300_PTRACE_H */ |
diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h index fd8b66e40dca..c43c0a7d2c2e 100644 --- a/arch/h8300/include/asm/signal.h +++ b/arch/h8300/include/asm/signal.h | |||
@@ -154,8 +154,6 @@ typedef struct sigaltstack { | |||
154 | #include <asm/sigcontext.h> | 154 | #include <asm/sigcontext.h> |
155 | #undef __HAVE_ARCH_SIG_BITOPS | 155 | #undef __HAVE_ARCH_SIG_BITOPS |
156 | 156 | ||
157 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
158 | |||
159 | #endif /* __KERNEL__ */ | 157 | #endif /* __KERNEL__ */ |
160 | 158 | ||
161 | #endif /* _H8300_SIGNAL_H */ | 159 | #endif /* _H8300_SIGNAL_H */ |
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h index 5cd882801d79..c2c2f5c7d6bf 100644 --- a/arch/h8300/include/asm/unistd.h +++ b/arch/h8300/include/asm/unistd.h | |||
@@ -356,6 +356,10 @@ | |||
356 | #define __ARCH_WANT_SYS_SIGPROCMASK | 356 | #define __ARCH_WANT_SYS_SIGPROCMASK |
357 | #define __ARCH_WANT_SYS_RT_SIGACTION | 357 | #define __ARCH_WANT_SYS_RT_SIGACTION |
358 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 358 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
359 | #define __ARCH_WANT_SYS_EXECVE | ||
360 | #define __ARCH_WANT_SYS_FORK | ||
361 | #define __ARCH_WANT_SYS_VFORK | ||
362 | #define __ARCH_WANT_SYS_CLONE | ||
359 | 363 | ||
360 | /* | 364 | /* |
361 | * "Conditional" syscalls | 365 | * "Conditional" syscalls |
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S index ca7431690300..617a6878787f 100644 --- a/arch/h8300/kernel/entry.S +++ b/arch/h8300/kernel/entry.S | |||
@@ -158,6 +158,7 @@ INTERRUPTS = 128 | |||
158 | .globl SYMBOL_NAME(system_call) | 158 | .globl SYMBOL_NAME(system_call) |
159 | .globl SYMBOL_NAME(ret_from_exception) | 159 | .globl SYMBOL_NAME(ret_from_exception) |
160 | .globl SYMBOL_NAME(ret_from_fork) | 160 | .globl SYMBOL_NAME(ret_from_fork) |
161 | .globl SYMBOL_NAME(ret_from_kernel_thread) | ||
161 | .globl SYMBOL_NAME(ret_from_interrupt) | 162 | .globl SYMBOL_NAME(ret_from_interrupt) |
162 | .globl SYMBOL_NAME(interrupt_redirect_table) | 163 | .globl SYMBOL_NAME(interrupt_redirect_table) |
163 | .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) | 164 | .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) |
@@ -330,6 +331,14 @@ SYMBOL_NAME_LABEL(ret_from_fork) | |||
330 | jsr @SYMBOL_NAME(schedule_tail) | 331 | jsr @SYMBOL_NAME(schedule_tail) |
331 | jmp @SYMBOL_NAME(ret_from_exception) | 332 | jmp @SYMBOL_NAME(ret_from_exception) |
332 | 333 | ||
334 | SYMBOL_NAME_LABEL(ret_from_kernel_thread) | ||
335 | mov.l er2,er0 | ||
336 | jsr @SYMBOL_NAME(schedule_tail) | ||
337 | mov.l @(LER4:16,sp),er0 | ||
338 | mov.l @(LER5:16,sp),er1 | ||
339 | jsr @er1 | ||
340 | jmp @SYMBOL_NAME(ret_from_exception) | ||
341 | |||
333 | SYMBOL_NAME_LABEL(resume) | 342 | SYMBOL_NAME_LABEL(resume) |
334 | /* | 343 | /* |
335 | * Beware - when entering resume, offset of tss is in d1, | 344 | * Beware - when entering resume, offset of tss is in d1, |
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c index 6866bd9c7fb4..53d7c0e4bd83 100644 --- a/arch/h8300/kernel/h8300_ksyms.c +++ b/arch/h8300/kernel/h8300_ksyms.c | |||
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(strncmp); | |||
33 | 33 | ||
34 | EXPORT_SYMBOL(ip_fast_csum); | 34 | EXPORT_SYMBOL(ip_fast_csum); |
35 | 35 | ||
36 | EXPORT_SYMBOL(kernel_thread); | ||
37 | EXPORT_SYMBOL(enable_irq); | 36 | EXPORT_SYMBOL(enable_irq); |
38 | EXPORT_SYMBOL(disable_irq); | 37 | EXPORT_SYMBOL(disable_irq); |
39 | 38 | ||
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index e8dc1393a13a..b609f63f1590 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c | |||
@@ -47,6 +47,7 @@ void (*pm_power_off)(void) = NULL; | |||
47 | EXPORT_SYMBOL(pm_power_off); | 47 | EXPORT_SYMBOL(pm_power_off); |
48 | 48 | ||
49 | asmlinkage void ret_from_fork(void); | 49 | asmlinkage void ret_from_fork(void); |
50 | asmlinkage void ret_from_kernel_thread(void); | ||
50 | 51 | ||
51 | /* | 52 | /* |
52 | * The idle loop on an H8/300.. | 53 | * The idle loop on an H8/300.. |
@@ -122,113 +123,34 @@ void show_regs(struct pt_regs * regs) | |||
122 | printk("\n"); | 123 | printk("\n"); |
123 | } | 124 | } |
124 | 125 | ||
125 | /* | ||
126 | * Create a kernel thread | ||
127 | */ | ||
128 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
129 | { | ||
130 | long retval; | ||
131 | long clone_arg; | ||
132 | mm_segment_t fs; | ||
133 | |||
134 | fs = get_fs(); | ||
135 | set_fs (KERNEL_DS); | ||
136 | clone_arg = flags | CLONE_VM; | ||
137 | __asm__("mov.l sp,er3\n\t" | ||
138 | "sub.l er2,er2\n\t" | ||
139 | "mov.l %2,er1\n\t" | ||
140 | "mov.l %1,er0\n\t" | ||
141 | "trapa #0\n\t" | ||
142 | "cmp.l sp,er3\n\t" | ||
143 | "beq 1f\n\t" | ||
144 | "mov.l %4,er0\n\t" | ||
145 | "mov.l %3,er1\n\t" | ||
146 | "jsr @er1\n\t" | ||
147 | "mov.l %5,er0\n\t" | ||
148 | "trapa #0\n" | ||
149 | "1:\n\t" | ||
150 | "mov.l er0,%0" | ||
151 | :"=r"(retval) | ||
152 | :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit) | ||
153 | :"er0","er1","er2","er3"); | ||
154 | set_fs (fs); | ||
155 | return retval; | ||
156 | } | ||
157 | |||
158 | void flush_thread(void) | 126 | void flush_thread(void) |
159 | { | 127 | { |
160 | } | 128 | } |
161 | 129 | ||
162 | /* | ||
163 | * "h8300_fork()".. By the time we get here, the | ||
164 | * non-volatile registers have also been saved on the | ||
165 | * stack. We do some ugly pointer stuff here.. (see | ||
166 | * also copy_thread) | ||
167 | */ | ||
168 | |||
169 | asmlinkage int h8300_fork(struct pt_regs *regs) | ||
170 | { | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | asmlinkage int h8300_vfork(struct pt_regs *regs) | ||
175 | { | ||
176 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
177 | } | ||
178 | |||
179 | asmlinkage int h8300_clone(struct pt_regs *regs) | ||
180 | { | ||
181 | unsigned long clone_flags; | ||
182 | unsigned long newsp; | ||
183 | |||
184 | /* syscall2 puts clone_flags in er1 and usp in er2 */ | ||
185 | clone_flags = regs->er1; | ||
186 | newsp = regs->er2; | ||
187 | if (!newsp) | ||
188 | newsp = rdusp(); | ||
189 | return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); | ||
190 | |||
191 | } | ||
192 | |||
193 | int copy_thread(unsigned long clone_flags, | 130 | int copy_thread(unsigned long clone_flags, |
194 | unsigned long usp, unsigned long topstk, | 131 | unsigned long usp, unsigned long topstk, |
195 | struct task_struct * p, struct pt_regs * regs) | 132 | struct task_struct * p) |
196 | { | 133 | { |
197 | struct pt_regs * childregs; | 134 | struct pt_regs * childregs; |
198 | 135 | ||
199 | childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; | 136 | childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; |
200 | 137 | ||
201 | *childregs = *regs; | 138 | if (unlikely(p->flags & PF_KTHREAD)) { |
139 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
140 | childregs->retpc = (unsigned long) ret_from_kernel_thread; | ||
141 | childregs->er4 = topstk; /* arg */ | ||
142 | childregs->er5 = usp; /* fn */ | ||
143 | p->thread.ksp = (unsigned long)childregs; | ||
144 | } | ||
145 | *childregs = *current_pt_regs(); | ||
202 | childregs->retpc = (unsigned long) ret_from_fork; | 146 | childregs->retpc = (unsigned long) ret_from_fork; |
203 | childregs->er0 = 0; | 147 | childregs->er0 = 0; |
204 | 148 | p->thread.usp = usp ?: rdusp(); | |
205 | p->thread.usp = usp; | ||
206 | p->thread.ksp = (unsigned long)childregs; | 149 | p->thread.ksp = (unsigned long)childregs; |
207 | 150 | ||
208 | return 0; | 151 | return 0; |
209 | } | 152 | } |
210 | 153 | ||
211 | /* | ||
212 | * sys_execve() executes a new program. | ||
213 | */ | ||
214 | asmlinkage int sys_execve(const char *name, | ||
215 | const char *const *argv, | ||
216 | const char *const *envp, | ||
217 | int dummy, ...) | ||
218 | { | ||
219 | int error; | ||
220 | struct filename *filename; | ||
221 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | ||
222 | |||
223 | filename = getname(name); | ||
224 | error = PTR_ERR(filename); | ||
225 | if (IS_ERR(filename)) | ||
226 | return error; | ||
227 | error = do_execve(filename->name, argv, envp, regs); | ||
228 | putname(filename); | ||
229 | return error; | ||
230 | } | ||
231 | |||
232 | unsigned long thread_saved_pc(struct task_struct *tsk) | 154 | unsigned long thread_saved_pc(struct task_struct *tsk) |
233 | { | 155 | { |
234 | return ((struct pt_regs *)tsk->thread.esp0)->pc; | 156 | return ((struct pt_regs *)tsk->thread.esp0)->pc; |
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c index 4bdc7311784e..bf350cb7f597 100644 --- a/arch/h8300/kernel/sys_h8300.c +++ b/arch/h8300/kernel/sys_h8300.c | |||
@@ -46,29 +46,3 @@ asmlinkage void syscall_print(void *dummy,...) | |||
46 | ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); | 46 | ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); |
47 | } | 47 | } |
48 | #endif | 48 | #endif |
49 | |||
50 | /* | ||
51 | * Do a system call from kernel instead of calling sys_execve so we | ||
52 | * end up with proper pt_regs. | ||
53 | */ | ||
54 | asmlinkage | ||
55 | int kernel_execve(const char *filename, | ||
56 | const char *const argv[], | ||
57 | const char *const envp[]) | ||
58 | { | ||
59 | register long res __asm__("er0"); | ||
60 | register const char *const *_c __asm__("er3") = envp; | ||
61 | register const char *const *_b __asm__("er2") = argv; | ||
62 | register const char * _a __asm__("er1") = filename; | ||
63 | __asm__ __volatile__ ("mov.l %1,er0\n\t" | ||
64 | "trapa #0\n\t" | ||
65 | : "=r" (res) | ||
66 | : "g" (__NR_execve), | ||
67 | "g" (_a), | ||
68 | "g" (_b), | ||
69 | "g" (_c) | ||
70 | : "cc", "memory"); | ||
71 | return res; | ||
72 | } | ||
73 | |||
74 | |||
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 9d77e715a2ed..b74dd0ade58d 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -340,21 +340,12 @@ SYMBOL_NAME_LABEL(sys_call_table) | |||
340 | bra SYMBOL_NAME(syscall_trampoline):8 | 340 | bra SYMBOL_NAME(syscall_trampoline):8 |
341 | .endm | 341 | .endm |
342 | 342 | ||
343 | SYMBOL_NAME_LABEL(sys_clone) | ||
344 | call_sp h8300_clone | ||
345 | |||
346 | SYMBOL_NAME_LABEL(sys_sigreturn) | 343 | SYMBOL_NAME_LABEL(sys_sigreturn) |
347 | call_sp do_sigreturn | 344 | call_sp do_sigreturn |
348 | 345 | ||
349 | SYMBOL_NAME_LABEL(sys_rt_sigreturn) | 346 | SYMBOL_NAME_LABEL(sys_rt_sigreturn) |
350 | call_sp do_rt_sigreturn | 347 | call_sp do_rt_sigreturn |
351 | 348 | ||
352 | SYMBOL_NAME_LABEL(sys_fork) | ||
353 | call_sp h8300_fork | ||
354 | |||
355 | SYMBOL_NAME_LABEL(sys_vfork) | ||
356 | call_sp h8300_vfork | ||
357 | |||
358 | SYMBOL_NAME_LABEL(syscall_trampoline) | 349 | SYMBOL_NAME_LABEL(syscall_trampoline) |
359 | mov.l sp,er0 | 350 | mov.l sp,er0 |
360 | jmp @er6 | 351 | jmp @er6 |
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 0744f7d7b1fd..e418803b6c8e 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig | |||
@@ -31,6 +31,8 @@ config HEXAGON | |||
31 | select GENERIC_CLOCKEVENTS | 31 | select GENERIC_CLOCKEVENTS |
32 | select GENERIC_CLOCKEVENTS_BROADCAST | 32 | select GENERIC_CLOCKEVENTS_BROADCAST |
33 | select MODULES_USE_ELF_RELA | 33 | select MODULES_USE_ELF_RELA |
34 | select GENERIC_KERNEL_THREAD | ||
35 | select GENERIC_KERNEL_EXECVE | ||
34 | ---help--- | 36 | ---help--- |
35 | Qualcomm Hexagon is a processor architecture designed for high | 37 | Qualcomm Hexagon is a processor architecture designed for high |
36 | performance and low power across a wide variety of applications. | 38 | performance and low power across a wide variety of applications. |
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h index a03323ab9d44..6dd5d3706869 100644 --- a/arch/hexagon/include/asm/processor.h +++ b/arch/hexagon/include/asm/processor.h | |||
@@ -34,7 +34,6 @@ | |||
34 | struct task_struct; | 34 | struct task_struct; |
35 | 35 | ||
36 | /* this is defined in arch/process.c */ | 36 | /* this is defined in arch/process.c */ |
37 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
38 | extern unsigned long thread_saved_pc(struct task_struct *tsk); | 37 | extern unsigned long thread_saved_pc(struct task_struct *tsk); |
39 | 38 | ||
40 | extern void start_thread(struct pt_regs *, unsigned long, unsigned long); | 39 | extern void start_thread(struct pt_regs *, unsigned long, unsigned long); |
diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h index fb0e9d48faa6..4af9c7b6f13a 100644 --- a/arch/hexagon/include/asm/syscall.h +++ b/arch/hexagon/include/asm/syscall.h | |||
@@ -25,14 +25,6 @@ typedef long (*syscall_fn)(unsigned long, unsigned long, | |||
25 | unsigned long, unsigned long, | 25 | unsigned long, unsigned long, |
26 | unsigned long, unsigned long); | 26 | unsigned long, unsigned long); |
27 | 27 | ||
28 | asmlinkage int sys_execve(char __user *ufilename, char __user * __user *argv, | ||
29 | char __user * __user *envp); | ||
30 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
31 | unsigned long parent_tidp, unsigned long child_tidp); | ||
32 | |||
33 | #define sys_execve sys_execve | ||
34 | #define sys_clone sys_clone | ||
35 | |||
36 | #include <asm-generic/syscalls.h> | 28 | #include <asm-generic/syscalls.h> |
37 | 29 | ||
38 | extern void *sys_call_table[]; | 30 | extern void *sys_call_table[]; |
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h index 8ef784047a74..1ffce0c6ee07 100644 --- a/arch/hexagon/include/uapi/asm/ptrace.h +++ b/arch/hexagon/include/uapi/asm/ptrace.h | |||
@@ -32,4 +32,8 @@ | |||
32 | extern int regs_query_register_offset(const char *name); | 32 | extern int regs_query_register_offset(const char *name); |
33 | extern const char *regs_query_register_name(unsigned int offset); | 33 | extern const char *regs_query_register_name(unsigned int offset); |
34 | 34 | ||
35 | #define current_pt_regs() \ | ||
36 | ((struct pt_regs *) \ | ||
37 | ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | ||
38 | |||
35 | #endif | 39 | #endif |
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h index 81312d6a52e6..2af81533bd0f 100644 --- a/arch/hexagon/include/uapi/asm/unistd.h +++ b/arch/hexagon/include/uapi/asm/unistd.h | |||
@@ -27,5 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define sys_mmap2 sys_mmap_pgoff | 29 | #define sys_mmap2 sys_mmap_pgoff |
30 | #define __ARCH_WANT_SYS_EXECVE | ||
31 | #define __ARCH_WANT_SYS_CLONE | ||
30 | 32 | ||
31 | #include <asm-generic/unistd.h> | 33 | #include <asm-generic/unistd.h> |
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile index 536aec093e62..6c19501b487c 100644 --- a/arch/hexagon/kernel/Makefile +++ b/arch/hexagon/kernel/Makefile | |||
@@ -3,8 +3,7 @@ extra-y := head.o vmlinux.lds | |||
3 | obj-$(CONFIG_SMP) += smp.o topology.o | 3 | obj-$(CONFIG_SMP) += smp.o topology.o |
4 | 4 | ||
5 | obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o | 5 | obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o |
6 | obj-y += process.o syscall.o trampoline.o reset.o ptrace.o | 6 | obj-y += process.o trampoline.o reset.o ptrace.o vdso.o |
7 | obj-y += vdso.o | ||
8 | 7 | ||
9 | obj-$(CONFIG_KGDB) += kgdb.o | 8 | obj-$(CONFIG_KGDB) += kgdb.o |
10 | obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o | 9 | obj-$(CONFIG_MODULES) += module.o hexagon_ksyms.o |
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index 9f6d7411b574..06ae9ffcabd5 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c | |||
@@ -26,33 +26,6 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * Kernel thread creation. The desired kernel function is "wrapped" | ||
30 | * in the kernel_thread_helper function, which does cleanup | ||
31 | * afterwards. | ||
32 | */ | ||
33 | static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
34 | { | ||
35 | do_exit(fn(arg)); | ||
36 | } | ||
37 | |||
38 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
39 | { | ||
40 | struct pt_regs regs; | ||
41 | |||
42 | memset(®s, 0, sizeof(regs)); | ||
43 | /* | ||
44 | * Yes, we're exploting illicit knowledge of the ABI here. | ||
45 | */ | ||
46 | regs.r00 = (unsigned long) arg; | ||
47 | regs.r01 = (unsigned long) fn; | ||
48 | pt_set_elr(®s, (unsigned long)kernel_thread_helper); | ||
49 | pt_set_kmode(®s); | ||
50 | |||
51 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
52 | } | ||
53 | EXPORT_SYMBOL(kernel_thread); | ||
54 | |||
55 | /* | ||
56 | * Program thread launch. Often defined as a macro in processor.h, | 29 | * Program thread launch. Often defined as a macro in processor.h, |
57 | * but we're shooting for a small footprint and it's not an inner-loop | 30 | * but we're shooting for a small footprint and it's not an inner-loop |
58 | * performance-critical operation. | 31 | * performance-critical operation. |
@@ -114,8 +87,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
114 | * Copy architecture-specific thread state | 87 | * Copy architecture-specific thread state |
115 | */ | 88 | */ |
116 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 89 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
117 | unsigned long unused, struct task_struct *p, | 90 | unsigned long arg, struct task_struct *p) |
118 | struct pt_regs *regs) | ||
119 | { | 91 | { |
120 | struct thread_info *ti = task_thread_info(p); | 92 | struct thread_info *ti = task_thread_info(p); |
121 | struct hexagon_switch_stack *ss; | 93 | struct hexagon_switch_stack *ss; |
@@ -125,61 +97,51 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
125 | childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) - | 97 | childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) - |
126 | sizeof(*childregs)); | 98 | sizeof(*childregs)); |
127 | 99 | ||
128 | memcpy(childregs, regs, sizeof(*childregs)); | ||
129 | ti->regs = childregs; | 100 | ti->regs = childregs; |
130 | 101 | ||
131 | /* | 102 | /* |
132 | * Establish kernel stack pointer and initial PC for new thread | 103 | * Establish kernel stack pointer and initial PC for new thread |
104 | * Note that unlike the usual situation, we do not copy the | ||
105 | * parent's callee-saved here; those are in pt_regs and whatever | ||
106 | * we leave here will be overridden on return to userland. | ||
133 | */ | 107 | */ |
134 | ss = (struct hexagon_switch_stack *) ((unsigned long) childregs - | 108 | ss = (struct hexagon_switch_stack *) ((unsigned long) childregs - |
135 | sizeof(*ss)); | 109 | sizeof(*ss)); |
136 | ss->lr = (unsigned long)ret_from_fork; | 110 | ss->lr = (unsigned long)ret_from_fork; |
137 | p->thread.switch_sp = ss; | 111 | p->thread.switch_sp = ss; |
112 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
113 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
114 | /* r24 <- fn, r25 <- arg */ | ||
115 | ss->r2524 = usp | ((u64)arg << 32); | ||
116 | pt_set_kmode(childregs); | ||
117 | return 0; | ||
118 | } | ||
119 | memcpy(childregs, current_pt_regs(), sizeof(*childregs)); | ||
120 | ss->r2524 = 0; | ||
138 | 121 | ||
139 | /* If User mode thread, set pt_reg stack pointer as per parameter */ | 122 | if (usp) |
140 | if (user_mode(childregs)) { | ||
141 | pt_set_rte_sp(childregs, usp); | 123 | pt_set_rte_sp(childregs, usp); |
142 | 124 | ||
143 | /* Child sees zero return value */ | 125 | /* Child sees zero return value */ |
144 | childregs->r00 = 0; | 126 | childregs->r00 = 0; |
145 | 127 | ||
146 | /* | 128 | /* |
147 | * The clone syscall has the C signature: | 129 | * The clone syscall has the C signature: |
148 | * int [r0] clone(int flags [r0], | 130 | * int [r0] clone(int flags [r0], |
149 | * void *child_frame [r1], | 131 | * void *child_frame [r1], |
150 | * void *parent_tid [r2], | 132 | * void *parent_tid [r2], |
151 | * void *child_tid [r3], | 133 | * void *child_tid [r3], |
152 | * void *thread_control_block [r4]); | 134 | * void *thread_control_block [r4]); |
153 | * ugp is used to provide TLS support. | 135 | * ugp is used to provide TLS support. |
154 | */ | 136 | */ |
155 | if (clone_flags & CLONE_SETTLS) | 137 | if (clone_flags & CLONE_SETTLS) |
156 | childregs->ugp = childregs->r04; | 138 | childregs->ugp = childregs->r04; |
157 | |||
158 | /* | ||
159 | * Parent sees new pid -- not necessary, not even possible at | ||
160 | * this point in the fork process | ||
161 | * Might also want to set things like ti->addr_limit | ||
162 | */ | ||
163 | } else { | ||
164 | /* | ||
165 | * If kernel thread, resume stack is kernel stack base. | ||
166 | * Note that this is pointer arithmetic on pt_regs * | ||
167 | */ | ||
168 | pt_set_rte_sp(childregs, (unsigned long)(childregs + 1)); | ||
169 | /* | ||
170 | * We need the current thread_info fast path pointer | ||
171 | * set up in pt_regs. The register to be used is | ||
172 | * parametric for assembler code, but the mechanism | ||
173 | * doesn't drop neatly into C. Needs to be fixed. | ||
174 | */ | ||
175 | childregs->THREADINFO_REG = (unsigned long) ti; | ||
176 | } | ||
177 | 139 | ||
178 | /* | 140 | /* |
179 | * thread_info pointer is pulled out of task_struct "stack" | 141 | * Parent sees new pid -- not necessary, not even possible at |
180 | * field on switch_to. | 142 | * this point in the fork process |
143 | * Might also want to set things like ti->addr_limit | ||
181 | */ | 144 | */ |
182 | p->stack = (void *)ti; | ||
183 | 145 | ||
184 | return 0; | 146 | return 0; |
185 | } | 147 | } |
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c index 5047b8b879c0..fe0d1373165d 100644 --- a/arch/hexagon/kernel/signal.c +++ b/arch/hexagon/kernel/signal.c | |||
@@ -249,14 +249,14 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
249 | */ | 249 | */ |
250 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) | 250 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) |
251 | { | 251 | { |
252 | struct pt_regs *regs = current_thread_info()->regs; | 252 | struct pt_regs *regs = current_pt_regs(); |
253 | 253 | ||
254 | return do_sigaltstack(uss, uoss, regs->r29); | 254 | return do_sigaltstack(uss, uoss, regs->r29); |
255 | } | 255 | } |
256 | 256 | ||
257 | asmlinkage int sys_rt_sigreturn(void) | 257 | asmlinkage int sys_rt_sigreturn(void) |
258 | { | 258 | { |
259 | struct pt_regs *regs = current_thread_info()->regs; | 259 | struct pt_regs *regs = current_pt_regs(); |
260 | struct rt_sigframe __user *frame; | 260 | struct rt_sigframe __user *frame; |
261 | sigset_t blocked; | 261 | sigset_t blocked; |
262 | 262 | ||
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c deleted file mode 100644 index 319fa6494f58..000000000000 --- a/arch/hexagon/kernel/syscall.c +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | /* | ||
2 | * Hexagon system calls | ||
3 | * | ||
4 | * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | ||
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 and | ||
8 | * only version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | * 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/file.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/linkage.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/syscalls.h> | ||
29 | #include <linux/unistd.h> | ||
30 | #include <asm/mman.h> | ||
31 | #include <asm/registers.h> | ||
32 | |||
33 | /* | ||
34 | * System calls with architecture-specific wrappers. | ||
35 | * See signal.c for signal-related system call wrappers. | ||
36 | */ | ||
37 | |||
38 | asmlinkage int sys_execve(char __user *ufilename, | ||
39 | const char __user *const __user *argv, | ||
40 | const char __user *const __user *envp) | ||
41 | { | ||
42 | struct pt_regs *pregs = current_thread_info()->regs; | ||
43 | struct filename *filename; | ||
44 | int retval; | ||
45 | |||
46 | filename = getname(ufilename); | ||
47 | retval = PTR_ERR(filename); | ||
48 | if (IS_ERR(filename)) | ||
49 | return retval; | ||
50 | |||
51 | retval = do_execve(filename->name, argv, envp, pregs); | ||
52 | putname(filename); | ||
53 | |||
54 | return retval; | ||
55 | } | ||
56 | |||
57 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
58 | unsigned long parent_tidp, unsigned long child_tidp) | ||
59 | { | ||
60 | struct pt_regs *pregs = current_thread_info()->regs; | ||
61 | |||
62 | if (!newsp) | ||
63 | newsp = pregs->SP; | ||
64 | return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp, | ||
65 | (int __user *)child_tidp); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Do a system call from the kernel, so as to have a proper pt_regs | ||
70 | * and recycle the sys_execvpe infrustructure. | ||
71 | */ | ||
72 | int kernel_execve(const char *filename, | ||
73 | const char *const argv[], const char *const envp[]) | ||
74 | { | ||
75 | register unsigned long __a0 asm("r0") = (unsigned long) filename; | ||
76 | register unsigned long __a1 asm("r1") = (unsigned long) argv; | ||
77 | register unsigned long __a2 asm("r2") = (unsigned long) envp; | ||
78 | int retval; | ||
79 | |||
80 | __asm__ volatile( | ||
81 | " R6 = #%4;\n" | ||
82 | " trap0(#1);\n" | ||
83 | " %0 = R0;\n" | ||
84 | : "=r" (retval) | ||
85 | : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) | ||
86 | ); | ||
87 | |||
88 | return retval; | ||
89 | } | ||
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S index cd71673ac259..425e50c694f7 100644 --- a/arch/hexagon/kernel/vm_entry.S +++ b/arch/hexagon/kernel/vm_entry.S | |||
@@ -266,4 +266,8 @@ _K_enter_machcheck: | |||
266 | .globl ret_from_fork | 266 | .globl ret_from_fork |
267 | ret_from_fork: | 267 | ret_from_fork: |
268 | call schedule_tail | 268 | call schedule_tail |
269 | P0 = cmp.eq(R24, #0); | ||
270 | if P0 jump return_from_syscall | ||
271 | R0 = R25; | ||
272 | callr R24 | ||
269 | jump return_from_syscall | 273 | jump return_from_syscall |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 3279646120e3..670600468128 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -42,6 +42,8 @@ config IA64 | |||
42 | select GENERIC_TIME_VSYSCALL_OLD | 42 | select GENERIC_TIME_VSYSCALL_OLD |
43 | select HAVE_MOD_ARCH_SPECIFIC | 43 | select HAVE_MOD_ARCH_SPECIFIC |
44 | select MODULES_USE_ELF_RELA | 44 | select MODULES_USE_ELF_RELA |
45 | select GENERIC_KERNEL_THREAD | ||
46 | select GENERIC_KERNEL_EXECVE | ||
45 | default y | 47 | default y |
46 | help | 48 | help |
47 | The Itanium Processor Family is Intel's 64-bit successor to | 49 | The Itanium Processor Family is Intel's 64-bit successor to |
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 944152a50912..e0a899a1a8a6 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h | |||
@@ -340,22 +340,6 @@ struct task_struct; | |||
340 | */ | 340 | */ |
341 | #define release_thread(dead_task) | 341 | #define release_thread(dead_task) |
342 | 342 | ||
343 | /* | ||
344 | * This is the mechanism for creating a new kernel thread. | ||
345 | * | ||
346 | * NOTE 1: Only a kernel-only process (ie the swapper or direct | ||
347 | * descendants who haven't done an "execve()") should use this: it | ||
348 | * will work within a system call from a "real" process, but the | ||
349 | * process memory space will not be free'd until both the parent and | ||
350 | * the child have exited. | ||
351 | * | ||
352 | * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get | ||
353 | * into trouble in init/main.c when the child thread returns to | ||
354 | * do_basic_setup() and the timing is such that free_initmem() has | ||
355 | * been called already. | ||
356 | */ | ||
357 | extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); | ||
358 | |||
359 | /* Get wait channel for task P. */ | 343 | /* Get wait channel for task P. */ |
360 | extern unsigned long get_wchan (struct task_struct *p); | 344 | extern unsigned long get_wchan (struct task_struct *p); |
361 | 345 | ||
diff --git a/arch/ia64/include/asm/signal.h b/arch/ia64/include/asm/signal.h index aecda5b9eb4e..3a1b20e74c5c 100644 --- a/arch/ia64/include/asm/signal.h +++ b/arch/ia64/include/asm/signal.h | |||
@@ -38,7 +38,5 @@ struct k_sigaction { | |||
38 | 38 | ||
39 | # include <asm/sigcontext.h> | 39 | # include <asm/sigcontext.h> |
40 | 40 | ||
41 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
42 | |||
43 | # endif /* !__ASSEMBLY__ */ | 41 | # endif /* !__ASSEMBLY__ */ |
44 | #endif /* _ASM_IA64_SIGNAL_H */ | 42 | #endif /* _ASM_IA64_SIGNAL_H */ |
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index 8b3ff2f5b861..1574bca86138 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #define __ARCH_WANT_SYS_RT_SIGACTION | 30 | #define __ARCH_WANT_SYS_RT_SIGACTION |
31 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 31 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
32 | #define __ARCH_WANT_SYS_EXECVE | ||
32 | 33 | ||
33 | #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) | 34 | #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) |
34 | 35 | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 1ccbe12a4d84..e25b784a2b72 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -61,14 +61,13 @@ ENTRY(ia64_execve) | |||
61 | * Allocate 8 input registers since ptrace() may clobber them | 61 | * Allocate 8 input registers since ptrace() may clobber them |
62 | */ | 62 | */ |
63 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | 63 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) |
64 | alloc loc1=ar.pfs,8,2,4,0 | 64 | alloc loc1=ar.pfs,8,2,3,0 |
65 | mov loc0=rp | 65 | mov loc0=rp |
66 | .body | 66 | .body |
67 | mov out0=in0 // filename | 67 | mov out0=in0 // filename |
68 | ;; // stop bit between alloc and call | 68 | ;; // stop bit between alloc and call |
69 | mov out1=in1 // argv | 69 | mov out1=in1 // argv |
70 | mov out2=in2 // envp | 70 | mov out2=in2 // envp |
71 | add out3=16,sp // regs | ||
72 | br.call.sptk.many rp=sys_execve | 71 | br.call.sptk.many rp=sys_execve |
73 | .ret0: | 72 | .ret0: |
74 | cmp4.ge p6,p7=r8,r0 | 73 | cmp4.ge p6,p7=r8,r0 |
@@ -76,7 +75,6 @@ ENTRY(ia64_execve) | |||
76 | sxt4 r8=r8 // return 64-bit result | 75 | sxt4 r8=r8 // return 64-bit result |
77 | ;; | 76 | ;; |
78 | stf.spill [sp]=f0 | 77 | stf.spill [sp]=f0 |
79 | (p6) cmp.ne pKStk,pUStk=r0,r0 // a successful execve() lands us in user-mode... | ||
80 | mov rp=loc0 | 78 | mov rp=loc0 |
81 | (p6) mov ar.pfs=r0 // clear ar.pfs on success | 79 | (p6) mov ar.pfs=r0 // clear ar.pfs on success |
82 | (p7) br.ret.sptk.many rp | 80 | (p7) br.ret.sptk.many rp |
@@ -118,13 +116,12 @@ GLOBAL_ENTRY(sys_clone2) | |||
118 | mov loc1=r16 // save ar.pfs across do_fork | 116 | mov loc1=r16 // save ar.pfs across do_fork |
119 | .body | 117 | .body |
120 | mov out1=in1 | 118 | mov out1=in1 |
121 | mov out3=in2 | 119 | mov out2=in2 |
122 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT | 120 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT |
123 | mov out4=in3 // parent_tidptr: valid only w/CLONE_PARENT_SETTID | 121 | mov out3=in3 // parent_tidptr: valid only w/CLONE_PARENT_SETTID |
124 | ;; | 122 | ;; |
125 | (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() | 123 | (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() |
126 | mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID | 124 | mov out4=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID |
127 | adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s | ||
128 | mov out0=in0 // out0 = clone_flags | 125 | mov out0=in0 // out0 = clone_flags |
129 | br.call.sptk.many rp=do_fork | 126 | br.call.sptk.many rp=do_fork |
130 | .ret1: .restore sp | 127 | .ret1: .restore sp |
@@ -150,13 +147,12 @@ GLOBAL_ENTRY(sys_clone) | |||
150 | mov loc1=r16 // save ar.pfs across do_fork | 147 | mov loc1=r16 // save ar.pfs across do_fork |
151 | .body | 148 | .body |
152 | mov out1=in1 | 149 | mov out1=in1 |
153 | mov out3=16 // stacksize (compensates for 16-byte scratch area) | 150 | mov out2=16 // stacksize (compensates for 16-byte scratch area) |
154 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT | 151 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT |
155 | mov out4=in2 // parent_tidptr: valid only w/CLONE_PARENT_SETTID | 152 | mov out3=in2 // parent_tidptr: valid only w/CLONE_PARENT_SETTID |
156 | ;; | 153 | ;; |
157 | (p6) st8 [r2]=in4 // store TLS in r13 (tp) | 154 | (p6) st8 [r2]=in4 // store TLS in r13 (tp) |
158 | mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID | 155 | mov out4=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID |
159 | adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s | ||
160 | mov out0=in0 // out0 = clone_flags | 156 | mov out0=in0 // out0 = clone_flags |
161 | br.call.sptk.many rp=do_fork | 157 | br.call.sptk.many rp=do_fork |
162 | .ret2: .restore sp | 158 | .ret2: .restore sp |
@@ -484,19 +480,6 @@ GLOBAL_ENTRY(prefetch_stack) | |||
484 | br.ret.sptk.many rp | 480 | br.ret.sptk.many rp |
485 | END(prefetch_stack) | 481 | END(prefetch_stack) |
486 | 482 | ||
487 | GLOBAL_ENTRY(kernel_execve) | ||
488 | rum psr.ac | ||
489 | mov r15=__NR_execve // put syscall number in place | ||
490 | break __BREAK_SYSCALL | ||
491 | br.ret.sptk.many rp | ||
492 | END(kernel_execve) | ||
493 | |||
494 | GLOBAL_ENTRY(clone) | ||
495 | mov r15=__NR_clone // put syscall number in place | ||
496 | break __BREAK_SYSCALL | ||
497 | br.ret.sptk.many rp | ||
498 | END(clone) | ||
499 | |||
500 | /* | 483 | /* |
501 | * Invoke a system call, but do some tracing before and after the call. | 484 | * Invoke a system call, but do some tracing before and after the call. |
502 | * We MUST preserve the current register frame throughout this routine | 485 | * We MUST preserve the current register frame throughout this routine |
@@ -600,6 +583,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel) | |||
600 | .ret4: br.cond.sptk ia64_leave_kernel | 583 | .ret4: br.cond.sptk ia64_leave_kernel |
601 | END(ia64_strace_leave_kernel) | 584 | END(ia64_strace_leave_kernel) |
602 | 585 | ||
586 | ENTRY(call_payload) | ||
587 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0) | ||
588 | /* call the kernel_thread payload; fn is in r4, arg - in r5 */ | ||
589 | alloc loc1=ar.pfs,0,3,1,0 | ||
590 | mov loc0=rp | ||
591 | mov loc2=gp | ||
592 | mov out0=r5 // arg | ||
593 | ld8 r14 = [r4], 8 // fn.address | ||
594 | ;; | ||
595 | mov b6 = r14 | ||
596 | ld8 gp = [r4] // fn.gp | ||
597 | ;; | ||
598 | br.call.sptk.many rp=b6 // fn(arg) | ||
599 | .ret12: mov gp=loc2 | ||
600 | mov rp=loc0 | ||
601 | mov ar.pfs=loc1 | ||
602 | /* ... and if it has returned, we are going to userland */ | ||
603 | cmp.ne pKStk,pUStk=r0,r0 | ||
604 | br.ret.sptk.many rp | ||
605 | END(call_payload) | ||
606 | |||
603 | GLOBAL_ENTRY(ia64_ret_from_clone) | 607 | GLOBAL_ENTRY(ia64_ret_from_clone) |
604 | PT_REGS_UNWIND_INFO(0) | 608 | PT_REGS_UNWIND_INFO(0) |
605 | { /* | 609 | { /* |
@@ -616,6 +620,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone) | |||
616 | br.call.sptk.many rp=ia64_invoke_schedule_tail | 620 | br.call.sptk.many rp=ia64_invoke_schedule_tail |
617 | } | 621 | } |
618 | .ret8: | 622 | .ret8: |
623 | (pKStk) br.call.sptk.many rp=call_payload | ||
619 | adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 | 624 | adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 |
620 | ;; | 625 | ;; |
621 | ld4 r2=[r2] | 626 | ld4 r2=[r2] |
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 629a250f7c19..4738ff7bd66a 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S | |||
@@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime) | |||
1093 | END(cycle_to_cputime) | 1093 | END(cycle_to_cputime) |
1094 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | 1094 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ |
1095 | 1095 | ||
1096 | GLOBAL_ENTRY(start_kernel_thread) | ||
1097 | .prologue | ||
1098 | .save rp, r0 // this is the end of the call-chain | ||
1099 | .body | ||
1100 | alloc r2 = ar.pfs, 0, 0, 2, 0 | ||
1101 | mov out0 = r9 | ||
1102 | mov out1 = r11;; | ||
1103 | br.call.sptk.many rp = kernel_thread_helper;; | ||
1104 | mov out0 = r8 | ||
1105 | br.call.sptk.many rp = sys_exit;; | ||
1106 | 1: br.sptk.few 1b // not reached | ||
1107 | END(start_kernel_thread) | ||
1108 | |||
1109 | #ifdef CONFIG_IA64_BRL_EMU | 1096 | #ifdef CONFIG_IA64_BRL_EMU |
1110 | 1097 | ||
1111 | /* | 1098 | /* |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 35e106f2ed13..31360cbbd5f8 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -393,72 +393,24 @@ ia64_load_extra (struct task_struct *task) | |||
393 | int | 393 | int |
394 | copy_thread(unsigned long clone_flags, | 394 | copy_thread(unsigned long clone_flags, |
395 | unsigned long user_stack_base, unsigned long user_stack_size, | 395 | unsigned long user_stack_base, unsigned long user_stack_size, |
396 | struct task_struct *p, struct pt_regs *regs) | 396 | struct task_struct *p) |
397 | { | 397 | { |
398 | extern char ia64_ret_from_clone; | 398 | extern char ia64_ret_from_clone; |
399 | struct switch_stack *child_stack, *stack; | 399 | struct switch_stack *child_stack, *stack; |
400 | unsigned long rbs, child_rbs, rbs_size; | 400 | unsigned long rbs, child_rbs, rbs_size; |
401 | struct pt_regs *child_ptregs; | 401 | struct pt_regs *child_ptregs; |
402 | struct pt_regs *regs = current_pt_regs(); | ||
402 | int retval = 0; | 403 | int retval = 0; |
403 | 404 | ||
404 | #ifdef CONFIG_SMP | ||
405 | /* | ||
406 | * For SMP idle threads, fork_by_hand() calls do_fork with | ||
407 | * NULL regs. | ||
408 | */ | ||
409 | if (!regs) | ||
410 | return 0; | ||
411 | #endif | ||
412 | |||
413 | stack = ((struct switch_stack *) regs) - 1; | ||
414 | |||
415 | child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; | 405 | child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; |
416 | child_stack = (struct switch_stack *) child_ptregs - 1; | 406 | child_stack = (struct switch_stack *) child_ptregs - 1; |
417 | 407 | ||
418 | /* copy parent's switch_stack & pt_regs to child: */ | ||
419 | memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
420 | |||
421 | rbs = (unsigned long) current + IA64_RBS_OFFSET; | 408 | rbs = (unsigned long) current + IA64_RBS_OFFSET; |
422 | child_rbs = (unsigned long) p + IA64_RBS_OFFSET; | 409 | child_rbs = (unsigned long) p + IA64_RBS_OFFSET; |
423 | rbs_size = stack->ar_bspstore - rbs; | ||
424 | |||
425 | /* copy the parent's register backing store to the child: */ | ||
426 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); | ||
427 | |||
428 | if (likely(user_mode(child_ptregs))) { | ||
429 | if (clone_flags & CLONE_SETTLS) | ||
430 | child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ | ||
431 | if (user_stack_base) { | ||
432 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; | ||
433 | child_ptregs->ar_bspstore = user_stack_base; | ||
434 | child_ptregs->ar_rnat = 0; | ||
435 | child_ptregs->loadrs = 0; | ||
436 | } | ||
437 | } else { | ||
438 | /* | ||
439 | * Note: we simply preserve the relative position of | ||
440 | * the stack pointer here. There is no need to | ||
441 | * allocate a scratch area here, since that will have | ||
442 | * been taken care of by the caller of sys_clone() | ||
443 | * already. | ||
444 | */ | ||
445 | child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ | ||
446 | child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ | ||
447 | } | ||
448 | child_stack->ar_bspstore = child_rbs + rbs_size; | ||
449 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
450 | 410 | ||
451 | /* copy parts of thread_struct: */ | 411 | /* copy parts of thread_struct: */ |
452 | p->thread.ksp = (unsigned long) child_stack - 16; | 412 | p->thread.ksp = (unsigned long) child_stack - 16; |
453 | 413 | ||
454 | /* stop some PSR bits from being inherited. | ||
455 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
456 | * therefore we must specify them explicitly here and not include them in | ||
457 | * IA64_PSR_BITS_TO_CLEAR. | ||
458 | */ | ||
459 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
460 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
461 | |||
462 | /* | 414 | /* |
463 | * NOTE: The calling convention considers all floating point | 415 | * NOTE: The calling convention considers all floating point |
464 | * registers in the high partition (fph) to be scratch. Since | 416 | * registers in the high partition (fph) to be scratch. Since |
@@ -480,8 +432,66 @@ copy_thread(unsigned long clone_flags, | |||
480 | # define THREAD_FLAGS_TO_SET 0 | 432 | # define THREAD_FLAGS_TO_SET 0 |
481 | p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | 433 | p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) |
482 | | THREAD_FLAGS_TO_SET); | 434 | | THREAD_FLAGS_TO_SET); |
435 | |||
483 | ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ | 436 | ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ |
484 | 437 | ||
438 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
439 | if (unlikely(!user_stack_base)) { | ||
440 | /* fork_idle() called us */ | ||
441 | return 0; | ||
442 | } | ||
443 | memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
444 | child_stack->r4 = user_stack_base; /* payload */ | ||
445 | child_stack->r5 = user_stack_size; /* argument */ | ||
446 | /* | ||
447 | * Preserve PSR bits, except for bits 32-34 and 37-45, | ||
448 | * which we can't read. | ||
449 | */ | ||
450 | child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; | ||
451 | /* mark as valid, empty frame */ | ||
452 | child_ptregs->cr_ifs = 1UL << 63; | ||
453 | child_stack->ar_fpsr = child_ptregs->ar_fpsr | ||
454 | = ia64_getreg(_IA64_REG_AR_FPSR); | ||
455 | child_stack->pr = (1 << PRED_KERNEL_STACK); | ||
456 | child_stack->ar_bspstore = child_rbs; | ||
457 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
458 | |||
459 | /* stop some PSR bits from being inherited. | ||
460 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
461 | * therefore we must specify them explicitly here and not include them in | ||
462 | * IA64_PSR_BITS_TO_CLEAR. | ||
463 | */ | ||
464 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
465 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | stack = ((struct switch_stack *) regs) - 1; | ||
470 | /* copy parent's switch_stack & pt_regs to child: */ | ||
471 | memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); | ||
472 | |||
473 | /* copy the parent's register backing store to the child: */ | ||
474 | rbs_size = stack->ar_bspstore - rbs; | ||
475 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); | ||
476 | if (clone_flags & CLONE_SETTLS) | ||
477 | child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ | ||
478 | if (user_stack_base) { | ||
479 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; | ||
480 | child_ptregs->ar_bspstore = user_stack_base; | ||
481 | child_ptregs->ar_rnat = 0; | ||
482 | child_ptregs->loadrs = 0; | ||
483 | } | ||
484 | child_stack->ar_bspstore = child_rbs + rbs_size; | ||
485 | child_stack->b0 = (unsigned long) &ia64_ret_from_clone; | ||
486 | |||
487 | /* stop some PSR bits from being inherited. | ||
488 | * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() | ||
489 | * therefore we must specify them explicitly here and not include them in | ||
490 | * IA64_PSR_BITS_TO_CLEAR. | ||
491 | */ | ||
492 | child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) | ||
493 | & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); | ||
494 | |||
485 | #ifdef CONFIG_PERFMON | 495 | #ifdef CONFIG_PERFMON |
486 | if (current->thread.pfm_context) | 496 | if (current->thread.pfm_context) |
487 | pfm_inherit(p, child_ptregs); | 497 | pfm_inherit(p, child_ptregs); |
@@ -608,57 +618,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) | |||
608 | return 1; /* f0-f31 are always valid so we always return 1 */ | 618 | return 1; /* f0-f31 are always valid so we always return 1 */ |
609 | } | 619 | } |
610 | 620 | ||
611 | long | ||
612 | sys_execve (const char __user *filename, | ||
613 | const char __user *const __user *argv, | ||
614 | const char __user *const __user *envp, | ||
615 | struct pt_regs *regs) | ||
616 | { | ||
617 | struct filename *fname; | ||
618 | int error; | ||
619 | |||
620 | fname = getname(filename); | ||
621 | error = PTR_ERR(fname); | ||
622 | if (IS_ERR(fname)) | ||
623 | goto out; | ||
624 | error = do_execve(fname->name, argv, envp, regs); | ||
625 | putname(fname); | ||
626 | out: | ||
627 | return error; | ||
628 | } | ||
629 | |||
630 | pid_t | ||
631 | kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) | ||
632 | { | ||
633 | extern void start_kernel_thread (void); | ||
634 | unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread; | ||
635 | struct { | ||
636 | struct switch_stack sw; | ||
637 | struct pt_regs pt; | ||
638 | } regs; | ||
639 | |||
640 | memset(®s, 0, sizeof(regs)); | ||
641 | regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ | ||
642 | regs.pt.r1 = helper_fptr[1]; /* set GP */ | ||
643 | regs.pt.r9 = (unsigned long) fn; /* 1st argument */ | ||
644 | regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ | ||
645 | /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ | ||
646 | regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; | ||
647 | regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ | ||
648 | regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); | ||
649 | regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; | ||
650 | regs.sw.pr = (1 << PRED_KERNEL_STACK); | ||
651 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); | ||
652 | } | ||
653 | EXPORT_SYMBOL(kernel_thread); | ||
654 | |||
655 | /* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ | ||
656 | int | ||
657 | kernel_thread_helper (int (*fn)(void *), void *arg) | ||
658 | { | ||
659 | return (*fn)(arg); | ||
660 | } | ||
661 | |||
662 | /* | 621 | /* |
663 | * Flush thread state. This is called when a thread does an execve(). | 622 | * Flush thread state. This is called when a thread does an execve(). |
664 | */ | 623 | */ |
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 963d2db53bfa..6a368cb2043e 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -460,11 +460,6 @@ start_secondary (void *unused) | |||
460 | return 0; | 460 | return 0; |
461 | } | 461 | } |
462 | 462 | ||
463 | struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) | ||
464 | { | ||
465 | return NULL; | ||
466 | } | ||
467 | |||
468 | static int __cpuinit | 463 | static int __cpuinit |
469 | do_boot_cpu (int sapicid, int cpu, struct task_struct *idle) | 464 | do_boot_cpu (int sapicid, int cpu, struct task_struct *idle) |
470 | { | 465 | { |
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index f807721e19a5..5183f43a2cf7 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig | |||
@@ -15,6 +15,8 @@ config M32R | |||
15 | select GENERIC_ATOMIC64 | 15 | select GENERIC_ATOMIC64 |
16 | select ARCH_USES_GETTIMEOFFSET | 16 | select ARCH_USES_GETTIMEOFFSET |
17 | select MODULES_USE_ELF_RELA | 17 | select MODULES_USE_ELF_RELA |
18 | select GENERIC_KERNEL_THREAD | ||
19 | select GENERIC_KERNEL_EXECVE | ||
18 | 20 | ||
19 | config SBUS | 21 | config SBUS |
20 | bool | 22 | bool |
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h index da17253b5735..5767367550c6 100644 --- a/arch/m32r/include/asm/processor.h +++ b/arch/m32r/include/asm/processor.h | |||
@@ -118,11 +118,6 @@ struct mm_struct; | |||
118 | /* Free all resources held by a thread. */ | 118 | /* Free all resources held by a thread. */ |
119 | extern void release_thread(struct task_struct *); | 119 | extern void release_thread(struct task_struct *); |
120 | 120 | ||
121 | /* | ||
122 | * create a kernel thread without removing it from tasklists | ||
123 | */ | ||
124 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
125 | |||
126 | /* Copy and release all segment info associated with a VM */ | 121 | /* Copy and release all segment info associated with a VM */ |
127 | extern void copy_segments(struct task_struct *p, struct mm_struct * mm); | 122 | extern void copy_segments(struct task_struct *p, struct mm_struct * mm); |
128 | extern void release_segments(struct mm_struct * mm); | 123 | extern void release_segments(struct mm_struct * mm); |
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h index 4313aa62b51b..c4432f1fb2cf 100644 --- a/arch/m32r/include/asm/ptrace.h +++ b/arch/m32r/include/asm/ptrace.h | |||
@@ -139,6 +139,8 @@ extern void withdraw_debug_trap(struct pt_regs *regs); | |||
139 | 139 | ||
140 | #define task_pt_regs(task) \ | 140 | #define task_pt_regs(task) \ |
141 | ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) | 141 | ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) |
142 | #define current_pt_regs() ((struct pt_regs *) \ | ||
143 | ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | ||
142 | 144 | ||
143 | #endif /* __KERNEL */ | 145 | #endif /* __KERNEL */ |
144 | 146 | ||
diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index ea5f95e4079e..e4d2e2ad5f1e 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h | |||
@@ -149,10 +149,6 @@ typedef struct sigaltstack { | |||
149 | 149 | ||
150 | #undef __HAVE_ARCH_SIG_BITOPS | 150 | #undef __HAVE_ARCH_SIG_BITOPS |
151 | 151 | ||
152 | struct pt_regs; | ||
153 | |||
154 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
155 | |||
156 | #endif /* __KERNEL__ */ | 152 | #endif /* __KERNEL__ */ |
157 | 153 | ||
158 | #endif /* _ASM_M32R_SIGNAL_H */ | 154 | #endif /* _ASM_M32R_SIGNAL_H */ |
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index d5e66a480782..d9e7351af2a4 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h | |||
@@ -352,6 +352,10 @@ | |||
352 | #define __ARCH_WANT_SYS_OLDUMOUNT | 352 | #define __ARCH_WANT_SYS_OLDUMOUNT |
353 | #define __ARCH_WANT_SYS_RT_SIGACTION | 353 | #define __ARCH_WANT_SYS_RT_SIGACTION |
354 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 354 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
355 | #define __ARCH_WANT_SYS_EXECVE | ||
356 | #define __ARCH_WANT_SYS_CLONE | ||
357 | #define __ARCH_WANT_SYS_FORK | ||
358 | #define __ARCH_WANT_SYS_VFORK | ||
355 | 359 | ||
356 | #define __IGNORE_lchown | 360 | #define __IGNORE_lchown |
357 | #define __IGNORE_setuid | 361 | #define __IGNORE_setuid |
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 225412bc227e..0c01543f10cd 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S | |||
@@ -125,6 +125,15 @@ | |||
125 | and \reg, sp | 125 | and \reg, sp |
126 | .endm | 126 | .endm |
127 | 127 | ||
128 | ENTRY(ret_from_kernel_thread) | ||
129 | pop r0 | ||
130 | bl schedule_tail | ||
131 | GET_THREAD_INFO(r8) | ||
132 | ld r0, R0(r8) | ||
133 | ld r1, R1(r8) | ||
134 | jl r1 | ||
135 | bra syscall_exit | ||
136 | |||
128 | ENTRY(ret_from_fork) | 137 | ENTRY(ret_from_fork) |
129 | pop r0 | 138 | pop r0 |
130 | bl schedule_tail | 139 | bl schedule_tail |
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index 700570747a90..b727e693c805 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c | |||
@@ -21,7 +21,6 @@ EXPORT_SYMBOL(boot_cpu_data); | |||
21 | EXPORT_SYMBOL(dump_fpu); | 21 | EXPORT_SYMBOL(dump_fpu); |
22 | EXPORT_SYMBOL(__ioremap); | 22 | EXPORT_SYMBOL(__ioremap); |
23 | EXPORT_SYMBOL(iounmap); | 23 | EXPORT_SYMBOL(iounmap); |
24 | EXPORT_SYMBOL(kernel_thread); | ||
25 | 24 | ||
26 | EXPORT_SYMBOL(strncpy_from_user); | 25 | EXPORT_SYMBOL(strncpy_from_user); |
27 | EXPORT_SYMBOL(__strncpy_from_user); | 26 | EXPORT_SYMBOL(__strncpy_from_user); |
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index e7366276ef30..765d0f57c787 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c | |||
@@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs) | |||
165 | } | 165 | } |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * Create a kernel thread | ||
169 | */ | ||
170 | |||
171 | /* | ||
172 | * This is the mechanism for creating a new kernel thread. | ||
173 | * | ||
174 | * NOTE! Only a kernel-only process(ie the swapper or direct descendants | ||
175 | * who haven't done an "execve()") should use this: it will work within | ||
176 | * a system call from a "real" process, but the process memory space will | ||
177 | * not be free'd until both the parent and the child have exited. | ||
178 | */ | ||
179 | static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg) | ||
180 | { | ||
181 | fn(arg); | ||
182 | do_exit(-1); | ||
183 | } | ||
184 | |||
185 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
186 | { | ||
187 | struct pt_regs regs; | ||
188 | |||
189 | memset(®s, 0, sizeof (regs)); | ||
190 | regs.r1 = (unsigned long)fn; | ||
191 | regs.r2 = (unsigned long)arg; | ||
192 | |||
193 | regs.bpc = (unsigned long)kernel_thread_helper; | ||
194 | |||
195 | regs.psw = M32R_PSW_BIE; | ||
196 | |||
197 | /* Ok, create the new process. */ | ||
198 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, | ||
199 | NULL); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Free current thread data structures etc.. | 168 | * Free current thread data structures etc.. |
204 | */ | 169 | */ |
205 | void exit_thread(void) | 170 | void exit_thread(void) |
@@ -227,88 +192,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
227 | } | 192 | } |
228 | 193 | ||
229 | int copy_thread(unsigned long clone_flags, unsigned long spu, | 194 | int copy_thread(unsigned long clone_flags, unsigned long spu, |
230 | unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) | 195 | unsigned long arg, struct task_struct *tsk) |
231 | { | 196 | { |
232 | struct pt_regs *childregs = task_pt_regs(tsk); | 197 | struct pt_regs *childregs = task_pt_regs(tsk); |
233 | extern void ret_from_fork(void); | 198 | extern void ret_from_fork(void); |
234 | 199 | extern void ret_from_kernel_thread(void); | |
235 | /* Copy registers */ | 200 | |
236 | *childregs = *regs; | 201 | if (unlikely(tsk->flags & PF_KTHREAD)) { |
237 | 202 | memset(childregs, 0, sizeof(struct pt_regs)); | |
238 | childregs->spu = spu; | 203 | childregs->psw = M32R_PSW_BIE; |
239 | childregs->r0 = 0; /* Child gets zero as return value */ | 204 | childregs->r1 = spu; /* fn */ |
240 | regs->r0 = tsk->pid; | 205 | childregs->r0 = arg; |
206 | tsk->thread.lr = (unsigned long)ret_from_kernel_thread; | ||
207 | } else { | ||
208 | /* Copy registers */ | ||
209 | *childregs = *current_pt_regs(); | ||
210 | if (spu) | ||
211 | childregs->spu = spu; | ||
212 | childregs->r0 = 0; /* Child gets zero as return value */ | ||
213 | tsk->thread.lr = (unsigned long)ret_from_fork; | ||
214 | } | ||
241 | tsk->thread.sp = (unsigned long)childregs; | 215 | tsk->thread.sp = (unsigned long)childregs; |
242 | tsk->thread.lr = (unsigned long)ret_from_fork; | ||
243 | 216 | ||
244 | return 0; | 217 | return 0; |
245 | } | 218 | } |
246 | 219 | ||
247 | asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, | ||
248 | unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, | ||
249 | struct pt_regs regs) | ||
250 | { | ||
251 | #ifdef CONFIG_MMU | ||
252 | return do_fork(SIGCHLD, regs.spu, ®s, 0, NULL, NULL); | ||
253 | #else | ||
254 | return -EINVAL; | ||
255 | #endif /* CONFIG_MMU */ | ||
256 | } | ||
257 | |||
258 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
259 | unsigned long parent_tidptr, | ||
260 | unsigned long child_tidptr, | ||
261 | unsigned long r4, unsigned long r5, unsigned long r6, | ||
262 | struct pt_regs regs) | ||
263 | { | ||
264 | if (!newsp) | ||
265 | newsp = regs.spu; | ||
266 | |||
267 | return do_fork(clone_flags, newsp, ®s, 0, | ||
268 | (int __user *)parent_tidptr, (int __user *)child_tidptr); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * This is trivial, and on the face of it looks like it | ||
273 | * could equally well be done in user mode. | ||
274 | * | ||
275 | * Not so, for quite unobvious reasons - register pressure. | ||
276 | * In user mode vfork() cannot have a stack frame, and if | ||
277 | * done by calling the "clone()" system call directly, you | ||
278 | * do not have enough call-clobbered registers to hold all | ||
279 | * the information you need. | ||
280 | */ | ||
281 | asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2, | ||
282 | unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, | ||
283 | struct pt_regs regs) | ||
284 | { | ||
285 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, ®s, 0, | ||
286 | NULL, NULL); | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * sys_execve() executes a new program. | ||
291 | */ | ||
292 | asmlinkage int sys_execve(const char __user *ufilename, | ||
293 | const char __user *const __user *uargv, | ||
294 | const char __user *const __user *uenvp, | ||
295 | unsigned long r3, unsigned long r4, unsigned long r5, | ||
296 | unsigned long r6, struct pt_regs regs) | ||
297 | { | ||
298 | int error; | ||
299 | struct filename *filename; | ||
300 | |||
301 | filename = getname(ufilename); | ||
302 | error = PTR_ERR(filename); | ||
303 | if (IS_ERR(filename)) | ||
304 | goto out; | ||
305 | |||
306 | error = do_execve(filename->name, uargv, uenvp, ®s); | ||
307 | putname(filename); | ||
308 | out: | ||
309 | return error; | ||
310 | } | ||
311 | |||
312 | /* | 220 | /* |
313 | * These bracket the sleeping functions.. | 221 | * These bracket the sleeping functions.. |
314 | */ | 222 | */ |
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index d841fb6cc703..c3fdd632fba7 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c | |||
@@ -88,24 +88,3 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op) | |||
88 | /* Not implemented yet. */ | 88 | /* Not implemented yet. */ |
89 | return -ENOSYS; | 89 | return -ENOSYS; |
90 | } | 90 | } |
91 | |||
92 | /* | ||
93 | * Do a system call from kernel instead of calling sys_execve so we | ||
94 | * end up with proper pt_regs. | ||
95 | */ | ||
96 | int kernel_execve(const char *filename, | ||
97 | const char *const argv[], | ||
98 | const char *const envp[]) | ||
99 | { | ||
100 | register long __scno __asm__ ("r7") = __NR_execve; | ||
101 | register long __arg3 __asm__ ("r2") = (long)(envp); | ||
102 | register long __arg2 __asm__ ("r1") = (long)(argv); | ||
103 | register long __res __asm__ ("r0") = (long)(filename); | ||
104 | __asm__ __volatile__ ( | ||
105 | "trap #" SYSCALL_VECTOR "|| nop" | ||
106 | : "=r" (__res) | ||
107 | : "r" (__scno), "0" (__res), "r" (__arg2), | ||
108 | "r" (__arg3) | ||
109 | : "memory"); | ||
110 | return __res; | ||
111 | } | ||
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index e7c161433eae..953a7ba5d050 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -16,6 +16,7 @@ config M68K | |||
16 | select ARCH_WANT_IPC_PARSE_VERSION | 16 | select ARCH_WANT_IPC_PARSE_VERSION |
17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE | 17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE |
18 | select GENERIC_KERNEL_THREAD | 18 | select GENERIC_KERNEL_THREAD |
19 | select GENERIC_KERNEL_EXECVE | ||
19 | select HAVE_MOD_ARCH_SPECIFIC | 20 | select HAVE_MOD_ARCH_SPECIFIC |
20 | select MODULES_USE_ELF_REL | 21 | select MODULES_USE_ELF_REL |
21 | select MODULES_USE_ELF_RELA | 22 | select MODULES_USE_ELF_RELA |
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 2df26b57c26a..9c8c46b06b0c 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h | |||
@@ -86,11 +86,9 @@ static inline int sigfindinword(unsigned long word) | |||
86 | 86 | ||
87 | #endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */ | 87 | #endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */ |
88 | 88 | ||
89 | #ifdef __uClinux__ | 89 | #ifndef __uClinux__ |
90 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | 90 | extern void ptrace_signal_deliver(void); |
91 | #else | 91 | #define ptrace_signal_deliver ptrace_signal_deliver |
92 | struct pt_regs; | ||
93 | extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); | ||
94 | #endif /* __uClinux__ */ | 92 | #endif /* __uClinux__ */ |
95 | 93 | ||
96 | #endif /* _M68K_SIGNAL_H */ | 94 | #endif /* _M68K_SIGNAL_H */ |
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 5fc7f7bec1c8..a021d67cdd72 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
@@ -32,7 +32,8 @@ | |||
32 | #define __ARCH_WANT_SYS_RT_SIGACTION | 32 | #define __ARCH_WANT_SYS_RT_SIGACTION |
33 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 33 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
34 | #define __ARCH_WANT_SYS_EXECVE | 34 | #define __ARCH_WANT_SYS_EXECVE |
35 | #define __ARCH_WANT_KERNEL_EXECVE | 35 | #define __ARCH_WANT_SYS_FORK |
36 | #define __ARCH_WANT_SYS_VFORK | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * "Conditional" syscalls | 39 | * "Conditional" syscalls |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 946cb0187751..a78f5649e8de 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -44,34 +44,29 @@ | |||
44 | 44 | ||
45 | .globl system_call, buserr, trap, resume | 45 | .globl system_call, buserr, trap, resume |
46 | .globl sys_call_table | 46 | .globl sys_call_table |
47 | .globl sys_fork, sys_clone, sys_vfork | 47 | .globl __sys_fork, __sys_clone, __sys_vfork |
48 | .globl ret_from_interrupt, bad_interrupt | 48 | .globl ret_from_interrupt, bad_interrupt |
49 | .globl auto_irqhandler_fixup | 49 | .globl auto_irqhandler_fixup |
50 | .globl user_irqvec_fixup | 50 | .globl user_irqvec_fixup |
51 | 51 | ||
52 | .text | 52 | .text |
53 | ENTRY(sys_fork) | 53 | ENTRY(__sys_fork) |
54 | SAVE_SWITCH_STACK | 54 | SAVE_SWITCH_STACK |
55 | pea %sp@(SWITCH_STACK_SIZE) | 55 | jbsr sys_fork |
56 | jbsr m68k_fork | 56 | lea %sp@(24),%sp |
57 | addql #4,%sp | ||
58 | RESTORE_SWITCH_STACK | ||
59 | rts | 57 | rts |
60 | 58 | ||
61 | ENTRY(sys_clone) | 59 | ENTRY(__sys_clone) |
62 | SAVE_SWITCH_STACK | 60 | SAVE_SWITCH_STACK |
63 | pea %sp@(SWITCH_STACK_SIZE) | 61 | pea %sp@(SWITCH_STACK_SIZE) |
64 | jbsr m68k_clone | 62 | jbsr m68k_clone |
65 | addql #4,%sp | 63 | lea %sp@(28),%sp |
66 | RESTORE_SWITCH_STACK | ||
67 | rts | 64 | rts |
68 | 65 | ||
69 | ENTRY(sys_vfork) | 66 | ENTRY(__sys_vfork) |
70 | SAVE_SWITCH_STACK | 67 | SAVE_SWITCH_STACK |
71 | pea %sp@(SWITCH_STACK_SIZE) | 68 | jbsr sys_vfork |
72 | jbsr m68k_vfork | 69 | lea %sp@(24),%sp |
73 | addql #4,%sp | ||
74 | RESTORE_SWITCH_STACK | ||
75 | rts | 70 | rts |
76 | 71 | ||
77 | ENTRY(sys_sigreturn) | 72 | ENTRY(sys_sigreturn) |
@@ -115,16 +110,9 @@ ENTRY(ret_from_kernel_thread) | |||
115 | | a3 contains the kernel thread payload, d7 - its argument | 110 | | a3 contains the kernel thread payload, d7 - its argument |
116 | movel %d1,%sp@- | 111 | movel %d1,%sp@- |
117 | jsr schedule_tail | 112 | jsr schedule_tail |
118 | GET_CURRENT(%d0) | ||
119 | movel %d7,(%sp) | 113 | movel %d7,(%sp) |
120 | jsr %a3@ | 114 | jsr %a3@ |
121 | addql #4,%sp | 115 | addql #4,%sp |
122 | movel %d0,(%sp) | ||
123 | jra sys_exit | ||
124 | |||
125 | ENTRY(ret_from_kernel_execve) | ||
126 | movel 4(%sp), %sp | ||
127 | GET_CURRENT(%d0) | ||
128 | jra ret_from_exception | 116 | jra ret_from_exception |
129 | 117 | ||
130 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) | 118 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c51bb172e14d..d538694ad208 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -136,57 +136,35 @@ void flush_thread(void) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | /* | 138 | /* |
139 | * "m68k_fork()".. By the time we get here, the | 139 | * Why not generic sys_clone, you ask? m68k passes all arguments on stack. |
140 | * non-volatile registers have also been saved on the | 140 | * And we need all registers saved, which means a bunch of stuff pushed |
141 | * stack. We do some ugly pointer stuff here.. (see | 141 | * on top of pt_regs, which means that sys_clone() arguments would be |
142 | * also copy_thread) | 142 | * buried. We could, of course, copy them, but it's too costly for no |
143 | * good reason - generic clone() would have to copy them *again* for | ||
144 | * do_fork() anyway. So in this case it's actually better to pass pt_regs * | ||
145 | * and extract arguments for do_fork() from there. Eventually we might | ||
146 | * go for calling do_fork() directly from the wrapper, but only after we | ||
147 | * are finished with do_fork() prototype conversion. | ||
143 | */ | 148 | */ |
144 | |||
145 | asmlinkage int m68k_fork(struct pt_regs *regs) | ||
146 | { | ||
147 | #ifdef CONFIG_MMU | ||
148 | return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); | ||
149 | #else | ||
150 | return -EINVAL; | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | asmlinkage int m68k_vfork(struct pt_regs *regs) | ||
155 | { | ||
156 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, | ||
157 | NULL, NULL); | ||
158 | } | ||
159 | |||
160 | asmlinkage int m68k_clone(struct pt_regs *regs) | 149 | asmlinkage int m68k_clone(struct pt_regs *regs) |
161 | { | 150 | { |
162 | unsigned long clone_flags; | 151 | /* regs will be equal to current_pt_regs() */ |
163 | unsigned long newsp; | 152 | return do_fork(regs->d1, regs->d2, 0, |
164 | int __user *parent_tidptr, *child_tidptr; | 153 | (int __user *)regs->d3, (int __user *)regs->d4); |
165 | |||
166 | /* syscall2 puts clone_flags in d1 and usp in d2 */ | ||
167 | clone_flags = regs->d1; | ||
168 | newsp = regs->d2; | ||
169 | parent_tidptr = (int __user *)regs->d3; | ||
170 | child_tidptr = (int __user *)regs->d4; | ||
171 | if (!newsp) | ||
172 | newsp = rdusp(); | ||
173 | return do_fork(clone_flags, newsp, regs, 0, | ||
174 | parent_tidptr, child_tidptr); | ||
175 | } | 154 | } |
176 | 155 | ||
177 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 156 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
178 | unsigned long arg, | 157 | unsigned long arg, struct task_struct *p) |
179 | struct task_struct * p, struct pt_regs * regs) | ||
180 | { | 158 | { |
181 | struct pt_regs * childregs; | 159 | struct fork_frame { |
182 | struct switch_stack *childstack; | 160 | struct switch_stack sw; |
161 | struct pt_regs regs; | ||
162 | } *frame; | ||
183 | 163 | ||
184 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 164 | frame = (struct fork_frame *) (task_stack_page(p) + THREAD_SIZE) - 1; |
185 | childstack = ((struct switch_stack *) childregs) - 1; | ||
186 | 165 | ||
187 | p->thread.usp = usp; | 166 | p->thread.ksp = (unsigned long)frame; |
188 | p->thread.ksp = (unsigned long)childstack; | 167 | p->thread.esp0 = (unsigned long)&frame->regs; |
189 | p->thread.esp0 = (unsigned long)childregs; | ||
190 | 168 | ||
191 | /* | 169 | /* |
192 | * Must save the current SFC/DFC value, NOT the value when | 170 | * Must save the current SFC/DFC value, NOT the value when |
@@ -194,25 +172,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
194 | */ | 172 | */ |
195 | p->thread.fs = get_fs().seg; | 173 | p->thread.fs = get_fs().seg; |
196 | 174 | ||
197 | if (unlikely(!regs)) { | 175 | if (unlikely(p->flags & PF_KTHREAD)) { |
198 | /* kernel thread */ | 176 | /* kernel thread */ |
199 | memset(childstack, 0, | 177 | memset(frame, 0, sizeof(struct fork_frame)); |
200 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | 178 | frame->regs.sr = PS_S; |
201 | childregs->sr = PS_S; | 179 | frame->sw.a3 = usp; /* function */ |
202 | childstack->a3 = usp; /* function */ | 180 | frame->sw.d7 = arg; |
203 | childstack->d7 = arg; | 181 | frame->sw.retpc = (unsigned long)ret_from_kernel_thread; |
204 | childstack->retpc = (unsigned long)ret_from_kernel_thread; | ||
205 | p->thread.usp = 0; | 182 | p->thread.usp = 0; |
206 | return 0; | 183 | return 0; |
207 | } | 184 | } |
208 | *childregs = *regs; | 185 | memcpy(frame, container_of(current_pt_regs(), struct fork_frame, regs), |
209 | childregs->d0 = 0; | 186 | sizeof(struct fork_frame)); |
210 | 187 | frame->regs.d0 = 0; | |
211 | *childstack = ((struct switch_stack *) regs)[-1]; | 188 | frame->sw.retpc = (unsigned long)ret_from_fork; |
212 | childstack->retpc = (unsigned long)ret_from_fork; | 189 | p->thread.usp = usp ?: rdusp(); |
213 | 190 | ||
214 | if (clone_flags & CLONE_SETTLS) | 191 | if (clone_flags & CLONE_SETTLS) |
215 | task_thread_info(p)->tp_value = regs->d5; | 192 | task_thread_info(p)->tp_value = frame->regs.d5; |
216 | 193 | ||
217 | #ifdef CONFIG_FPU | 194 | #ifdef CONFIG_FPU |
218 | if (!FPU_IS_EMU) { | 195 | if (!FPU_IS_EMU) { |
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 710a528b928b..9a396cda3147 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c | |||
@@ -108,8 +108,9 @@ int handle_kernel_fault(struct pt_regs *regs) | |||
108 | return 1; | 108 | return 1; |
109 | } | 109 | } |
110 | 110 | ||
111 | void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) | 111 | void ptrace_signal_deliver(void) |
112 | { | 112 | { |
113 | struct pt_regs *regs = signal_pt_regs(); | ||
113 | if (regs->orig_d0 < 0) | 114 | if (regs->orig_d0 < 0) |
114 | return; | 115 | return; |
115 | switch (regs->d0) { | 116 | switch (regs->d0) { |
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index 4fc2e29b771b..c30da5b3f2db 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S | |||
@@ -22,7 +22,7 @@ ALIGN | |||
22 | ENTRY(sys_call_table) | 22 | ENTRY(sys_call_table) |
23 | .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ | 23 | .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ |
24 | .long sys_exit | 24 | .long sys_exit |
25 | .long sys_fork | 25 | .long __sys_fork |
26 | .long sys_read | 26 | .long sys_read |
27 | .long sys_write | 27 | .long sys_write |
28 | .long sys_open /* 5 */ | 28 | .long sys_open /* 5 */ |
@@ -140,7 +140,7 @@ ENTRY(sys_call_table) | |||
140 | .long sys_ipc | 140 | .long sys_ipc |
141 | .long sys_fsync | 141 | .long sys_fsync |
142 | .long sys_sigreturn | 142 | .long sys_sigreturn |
143 | .long sys_clone /* 120 */ | 143 | .long __sys_clone /* 120 */ |
144 | .long sys_setdomainname | 144 | .long sys_setdomainname |
145 | .long sys_newuname | 145 | .long sys_newuname |
146 | .long sys_cacheflush /* modify_ldt for i386 */ | 146 | .long sys_cacheflush /* modify_ldt for i386 */ |
@@ -210,7 +210,7 @@ ENTRY(sys_call_table) | |||
210 | .long sys_sendfile | 210 | .long sys_sendfile |
211 | .long sys_ni_syscall /* streams1 */ | 211 | .long sys_ni_syscall /* streams1 */ |
212 | .long sys_ni_syscall /* streams2 */ | 212 | .long sys_ni_syscall /* streams2 */ |
213 | .long sys_vfork /* 190 */ | 213 | .long __sys_vfork /* 190 */ |
214 | .long sys_getrlimit | 214 | .long sys_getrlimit |
215 | .long sys_mmap2 | 215 | .long sys_mmap2 |
216 | .long sys_truncate64 | 216 | .long sys_truncate64 |
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 4cba7439f9de..4bcf89148f3c 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -26,6 +26,9 @@ config MICROBLAZE | |||
26 | select GENERIC_ATOMIC64 | 26 | select GENERIC_ATOMIC64 |
27 | select GENERIC_CLOCKEVENTS | 27 | select GENERIC_CLOCKEVENTS |
28 | select MODULES_USE_ELF_RELA | 28 | select MODULES_USE_ELF_RELA |
29 | select GENERIC_KERNEL_THREAD | ||
30 | select GENERIC_KERNEL_EXECVE | ||
31 | select CLONE_BACKWARDS | ||
29 | 32 | ||
30 | config SWAP | 33 | config SWAP |
31 | def_bool n | 34 | def_bool n |
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 2957fcc71764..eb3a46c096fe 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
@@ -4,3 +4,4 @@ header-y += elf.h | |||
4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
5 | generic-y += exec.h | 5 | generic-y += exec.h |
6 | generic-y += trace_clock.h | 6 | generic-y += trace_clock.h |
7 | generic-y += syscalls.h | ||
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index af2bb9652392..0759153e8117 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h | |||
@@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op; | |||
31 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); | 31 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); |
32 | 32 | ||
33 | extern void ret_from_fork(void); | 33 | extern void ret_from_fork(void); |
34 | extern void ret_from_kernel_thread(void); | ||
34 | 35 | ||
35 | # endif /* __ASSEMBLY__ */ | 36 | # endif /* __ASSEMBLY__ */ |
36 | 37 | ||
@@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t); | |||
78 | 79 | ||
79 | extern unsigned long get_wchan(struct task_struct *p); | 80 | extern unsigned long get_wchan(struct task_struct *p); |
80 | 81 | ||
81 | /* | ||
82 | * create a kernel thread without removing it from tasklists | ||
83 | */ | ||
84 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
85 | |||
86 | # define KSTK_EIP(tsk) (0) | 82 | # define KSTK_EIP(tsk) (0) |
87 | # define KSTK_ESP(tsk) (0) | 83 | # define KSTK_ESP(tsk) (0) |
88 | 84 | ||
@@ -131,8 +127,6 @@ extern inline void release_thread(struct task_struct *dead_task) | |||
131 | { | 127 | { |
132 | } | 128 | } |
133 | 129 | ||
134 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
135 | |||
136 | /* Free current thread data structures etc. */ | 130 | /* Free current thread data structures etc. */ |
137 | static inline void exit_thread(void) | 131 | static inline void exit_thread(void) |
138 | { | 132 | { |
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h deleted file mode 100644 index 27f2f4c0f39f..000000000000 --- a/arch/microblaze/include/asm/syscalls.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef __ASM_MICROBLAZE_SYSCALLS_H | ||
2 | |||
3 | asmlinkage long microblaze_vfork(struct pt_regs *regs); | ||
4 | asmlinkage long microblaze_clone(int flags, unsigned long stack, | ||
5 | struct pt_regs *regs); | ||
6 | asmlinkage long microblaze_execve(const char __user *filenamei, | ||
7 | const char __user *const __user *argv, | ||
8 | const char __user *const __user *envp, | ||
9 | struct pt_regs *regs); | ||
10 | |||
11 | asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs); | ||
12 | #define sys_clone sys_clone | ||
13 | |||
14 | #include <asm-generic/syscalls.h> | ||
15 | |||
16 | #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ | ||
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6985e6e9d826..94d978986b75 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h | |||
@@ -422,6 +422,12 @@ | |||
422 | #define __ARCH_WANT_SYS_SIGPROCMASK | 422 | #define __ARCH_WANT_SYS_SIGPROCMASK |
423 | #define __ARCH_WANT_SYS_RT_SIGACTION | 423 | #define __ARCH_WANT_SYS_RT_SIGACTION |
424 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 424 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
425 | #define __ARCH_WANT_SYS_EXECVE | ||
426 | #define __ARCH_WANT_SYS_CLONE | ||
427 | #define __ARCH_WANT_SYS_VFORK | ||
428 | #ifdef CONFIG_MMU | ||
429 | #define __ARCH_WANT_SYS_FORK | ||
430 | #endif | ||
425 | 431 | ||
426 | /* | 432 | /* |
427 | * "Conditional" syscalls | 433 | * "Conditional" syscalls |
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 75c3ea1f48a1..cb0327f204ab 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S | |||
@@ -474,6 +474,14 @@ ENTRY(ret_from_fork) | |||
474 | brid ret_to_user | 474 | brid ret_to_user |
475 | nop | 475 | nop |
476 | 476 | ||
477 | ENTRY(ret_from_kernel_thread) | ||
478 | brlid r15, schedule_tail | ||
479 | addk r5, r0, r3 | ||
480 | brald r15, r20 | ||
481 | addk r5, r0, r19 | ||
482 | brid ret_to_user | ||
483 | addk r3, r0, r0 | ||
484 | |||
477 | work_pending: | 485 | work_pending: |
478 | enable_irq | 486 | enable_irq |
479 | 487 | ||
@@ -551,18 +559,6 @@ no_work_pending: | |||
551 | rtid r14, 0 | 559 | rtid r14, 0 |
552 | nop | 560 | nop |
553 | 561 | ||
554 | sys_vfork: | ||
555 | brid microblaze_vfork | ||
556 | addk r5, r1, r0 | ||
557 | |||
558 | sys_clone: | ||
559 | brid microblaze_clone | ||
560 | addk r7, r1, r0 | ||
561 | |||
562 | sys_execve: | ||
563 | brid microblaze_execve | ||
564 | addk r8, r1, r0 | ||
565 | |||
566 | sys_rt_sigreturn_wrapper: | 562 | sys_rt_sigreturn_wrapper: |
567 | brid sys_rt_sigreturn | 563 | brid sys_rt_sigreturn |
568 | addk r5, r1, r0 | 564 | addk r5, r1, r0 |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 03f7b8ce6b6b..c217367dfc7b 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
@@ -293,24 +293,6 @@ C_ENTRY(_user_exception): | |||
293 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ | 293 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ |
294 | addi r14, r14, 4 /* return address is 4 byte after call */ | 294 | addi r14, r14, 4 /* return address is 4 byte after call */ |
295 | 295 | ||
296 | mfs r1, rmsr | ||
297 | nop | ||
298 | andi r1, r1, MSR_UMS | ||
299 | bnei r1, 1f | ||
300 | |||
301 | /* Kernel-mode state save - kernel execve */ | ||
302 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ | ||
303 | tophys(r1,r1); | ||
304 | |||
305 | addik r1, r1, -PT_SIZE; /* Make room on the stack. */ | ||
306 | SAVE_REGS | ||
307 | |||
308 | swi r1, r1, PT_MODE; /* pt_regs -> kernel mode */ | ||
309 | brid 2f; | ||
310 | nop; /* Fill delay slot */ | ||
311 | |||
312 | /* User-mode state save. */ | ||
313 | 1: | ||
314 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ | 296 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ |
315 | tophys(r1,r1); | 297 | tophys(r1,r1); |
316 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ | 298 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ |
@@ -460,18 +442,6 @@ TRAP_return: /* Make global symbol for debugging */ | |||
460 | nop; | 442 | nop; |
461 | 443 | ||
462 | 444 | ||
463 | /* These syscalls need access to the struct pt_regs on the stack, so we | ||
464 | implement them in assembly (they're basically all wrappers anyway). */ | ||
465 | |||
466 | C_ENTRY(sys_fork_wrapper): | ||
467 | addi r5, r0, SIGCHLD /* Arg 0: flags */ | ||
468 | lwi r6, r1, PT_R1 /* Arg 1: child SP (use parent's) */ | ||
469 | addik r7, r1, 0 /* Arg 2: parent context */ | ||
470 | add r8, r0, r0 /* Arg 3: (unused) */ | ||
471 | add r9, r0, r0; /* Arg 4: (unused) */ | ||
472 | brid do_fork /* Do real work (tail-call) */ | ||
473 | add r10, r0, r0; /* Arg 5: (unused) */ | ||
474 | |||
475 | /* This the initial entry point for a new child thread, with an appropriate | 445 | /* This the initial entry point for a new child thread, with an appropriate |
476 | stack in place that makes it look the the child is in the middle of an | 446 | stack in place that makes it look the the child is in the middle of an |
477 | syscall. This function is actually `returned to' from switch_thread | 447 | syscall. This function is actually `returned to' from switch_thread |
@@ -479,28 +449,19 @@ C_ENTRY(sys_fork_wrapper): | |||
479 | saved context). */ | 449 | saved context). */ |
480 | C_ENTRY(ret_from_fork): | 450 | C_ENTRY(ret_from_fork): |
481 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ | 451 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ |
482 | add r3, r5, r0; /* switch_thread returns the prev task */ | 452 | add r5, r3, r0; /* switch_thread returns the prev task */ |
483 | /* ( in the delay slot ) */ | 453 | /* ( in the delay slot ) */ |
484 | brid ret_from_trap; /* Do normal trap return */ | 454 | brid ret_from_trap; /* Do normal trap return */ |
485 | add r3, r0, r0; /* Child's fork call should return 0. */ | 455 | add r3, r0, r0; /* Child's fork call should return 0. */ |
486 | 456 | ||
487 | C_ENTRY(sys_vfork): | 457 | C_ENTRY(ret_from_kernel_thread): |
488 | brid microblaze_vfork /* Do real work (tail-call) */ | 458 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ |
489 | addik r5, r1, 0 | 459 | add r5, r3, r0; /* switch_thread returns the prev task */ |
490 | 460 | /* ( in the delay slot ) */ | |
491 | C_ENTRY(sys_clone): | 461 | brald r15, r20 /* fn was left in r20 */ |
492 | bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ | 462 | addk r5, r0, r19 /* ... and argument - in r19 */ |
493 | lwi r6, r1, PT_R1; /* If so, use paret's stack ptr */ | 463 | brid ret_from_trap |
494 | 1: addik r7, r1, 0; /* Arg 2: parent context */ | 464 | add r3, r0, r0 |
495 | lwi r9, r1, PT_R8; /* parent tid. */ | ||
496 | lwi r10, r1, PT_R9; /* child tid. */ | ||
497 | /* do_fork will pick up TLS from regs->r10. */ | ||
498 | brid do_fork /* Do real work (tail-call) */ | ||
499 | add r8, r0, r0; /* Arg 3: (unused) */ | ||
500 | |||
501 | C_ENTRY(sys_execve): | ||
502 | brid microblaze_execve; /* Do real work (tail-call).*/ | ||
503 | addik r8, r1, 0; /* add user context as 4th arg */ | ||
504 | 465 | ||
505 | C_ENTRY(sys_rt_sigreturn_wrapper): | 466 | C_ENTRY(sys_rt_sigreturn_wrapper): |
506 | brid sys_rt_sigreturn /* Do real work */ | 467 | brid sys_rt_sigreturn /* Do real work */ |
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 1944e00f07e1..40823fd1db0b 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/pm.h> | 13 | #include <linux/pm.h> |
14 | #include <linux/tick.h> | 14 | #include <linux/tick.h> |
15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
16 | #include <linux/ptrace.h> | ||
16 | #include <asm/pgalloc.h> | 17 | #include <asm/pgalloc.h> |
17 | #include <asm/uaccess.h> /* for USER_DS macros */ | 18 | #include <asm/uaccess.h> /* for USER_DS macros */ |
18 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
@@ -119,46 +120,38 @@ void flush_thread(void) | |||
119 | } | 120 | } |
120 | 121 | ||
121 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 122 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
122 | unsigned long unused, | 123 | unsigned long arg, struct task_struct *p) |
123 | struct task_struct *p, struct pt_regs *regs) | ||
124 | { | 124 | { |
125 | struct pt_regs *childregs = task_pt_regs(p); | 125 | struct pt_regs *childregs = task_pt_regs(p); |
126 | struct thread_info *ti = task_thread_info(p); | 126 | struct thread_info *ti = task_thread_info(p); |
127 | 127 | ||
128 | *childregs = *regs; | 128 | if (unlikely(p->flags & PF_KTHREAD)) { |
129 | if (user_mode(regs)) | 129 | /* if we're creating a new kernel thread then just zeroing all |
130 | * the registers. That's OK for a brand new thread.*/ | ||
131 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
132 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | ||
133 | ti->cpu_context.r1 = (unsigned long)childregs; | ||
134 | ti->cpu_context.r20 = (unsigned long)usp; /* fn */ | ||
135 | ti->cpu_context.r19 = (unsigned long)arg; | ||
136 | childregs->pt_mode = 1; | ||
137 | local_save_flags(childregs->msr); | ||
138 | #ifdef CONFIG_MMU | ||
139 | ti->cpu_context.msr = childregs->msr & ~MSR_IE; | ||
140 | #endif | ||
141 | ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; | ||
142 | return 0; | ||
143 | } | ||
144 | *childregs = *current_pt_regs(); | ||
145 | if (usp) | ||
130 | childregs->r1 = usp; | 146 | childregs->r1 = usp; |
131 | else | ||
132 | childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; | ||
133 | 147 | ||
134 | #ifndef CONFIG_MMU | ||
135 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | 148 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); |
136 | ti->cpu_context.r1 = (unsigned long)childregs; | 149 | ti->cpu_context.r1 = (unsigned long)childregs; |
150 | #ifndef CONFIG_MMU | ||
137 | ti->cpu_context.msr = (unsigned long)childregs->msr; | 151 | ti->cpu_context.msr = (unsigned long)childregs->msr; |
138 | #else | 152 | #else |
153 | childregs->msr |= MSR_UMS; | ||
139 | 154 | ||
140 | /* if creating a kernel thread then update the current reg (we don't | ||
141 | * want to use the parent's value when restoring by POP_STATE) */ | ||
142 | if (kernel_mode(regs)) | ||
143 | /* save new current on stack to use POP_STATE */ | ||
144 | childregs->CURRENT_TASK = (unsigned long)p; | ||
145 | /* if returning to user then use the parent's value of this register */ | ||
146 | |||
147 | /* if we're creating a new kernel thread then just zeroing all | ||
148 | * the registers. That's OK for a brand new thread.*/ | ||
149 | /* Pls. note that some of them will be restored in POP_STATE */ | ||
150 | if (kernel_mode(regs)) | ||
151 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | ||
152 | /* if this thread is created for fork/vfork/clone, then we want to | ||
153 | * restore all the parent's context */ | ||
154 | /* in addition to the registers which will be restored by POP_STATE */ | ||
155 | else { | ||
156 | ti->cpu_context = *(struct cpu_context *)regs; | ||
157 | childregs->msr |= MSR_UMS; | ||
158 | } | ||
159 | |||
160 | /* FIXME STATE_SAVE_PT_OFFSET; */ | ||
161 | ti->cpu_context.r1 = (unsigned long)childregs; | ||
162 | /* we should consider the fact that childregs is a copy of the parent | 155 | /* we should consider the fact that childregs is a copy of the parent |
163 | * regs which were saved immediately after entering the kernel state | 156 | * regs which were saved immediately after entering the kernel state |
164 | * before enabling VM. This MSR will be restored in switch_to and | 157 | * before enabling VM. This MSR will be restored in switch_to and |
@@ -209,29 +202,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
209 | } | 202 | } |
210 | #endif | 203 | #endif |
211 | 204 | ||
212 | static void kernel_thread_helper(int (*fn)(void *), void *arg) | ||
213 | { | ||
214 | fn(arg); | ||
215 | do_exit(-1); | ||
216 | } | ||
217 | |||
218 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
219 | { | ||
220 | struct pt_regs regs; | ||
221 | |||
222 | memset(®s, 0, sizeof(regs)); | ||
223 | /* store them in non-volatile registers */ | ||
224 | regs.r5 = (unsigned long)fn; | ||
225 | regs.r6 = (unsigned long)arg; | ||
226 | local_save_flags(regs.msr); | ||
227 | regs.pc = (unsigned long)kernel_thread_helper; | ||
228 | regs.pt_mode = 1; | ||
229 | |||
230 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | ||
231 | ®s, 0, NULL, NULL); | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(kernel_thread); | ||
234 | |||
235 | unsigned long get_wchan(struct task_struct *p) | 205 | unsigned long get_wchan(struct task_struct *p) |
236 | { | 206 | { |
237 | /* TBD (used by procfs) */ | 207 | /* TBD (used by procfs) */ |
@@ -246,6 +216,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) | |||
246 | regs->pt_mode = 0; | 216 | regs->pt_mode = 0; |
247 | #ifdef CONFIG_MMU | 217 | #ifdef CONFIG_MMU |
248 | regs->msr |= MSR_UMS; | 218 | regs->msr |= MSR_UMS; |
219 | regs->msr &= ~MSR_VM; | ||
249 | #endif | 220 | #endif |
250 | } | 221 | } |
251 | 222 | ||
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 404c0f24bd41..63647c586b43 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c | |||
@@ -34,38 +34,6 @@ | |||
34 | 34 | ||
35 | #include <asm/syscalls.h> | 35 | #include <asm/syscalls.h> |
36 | 36 | ||
37 | asmlinkage long microblaze_vfork(struct pt_regs *regs) | ||
38 | { | ||
39 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, | ||
40 | regs, 0, NULL, NULL); | ||
41 | } | ||
42 | |||
43 | asmlinkage long microblaze_clone(int flags, unsigned long stack, | ||
44 | struct pt_regs *regs) | ||
45 | { | ||
46 | if (!stack) | ||
47 | stack = regs->r1; | ||
48 | return do_fork(flags, stack, regs, 0, NULL, NULL); | ||
49 | } | ||
50 | |||
51 | asmlinkage long microblaze_execve(const char __user *filenamei, | ||
52 | const char __user *const __user *argv, | ||
53 | const char __user *const __user *envp, | ||
54 | struct pt_regs *regs) | ||
55 | { | ||
56 | int error; | ||
57 | struct filename *filename; | ||
58 | |||
59 | filename = getname(filenamei); | ||
60 | error = PTR_ERR(filename); | ||
61 | if (IS_ERR(filename)) | ||
62 | goto out; | ||
63 | error = do_execve(filename->name, argv, envp, regs); | ||
64 | putname(filename); | ||
65 | out: | ||
66 | return error; | ||
67 | } | ||
68 | |||
69 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | 37 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, |
70 | unsigned long prot, unsigned long flags, | 38 | unsigned long prot, unsigned long flags, |
71 | unsigned long fd, off_t pgoff) | 39 | unsigned long fd, off_t pgoff) |
@@ -75,24 +43,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | |||
75 | 43 | ||
76 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); | 44 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); |
77 | } | 45 | } |
78 | |||
79 | /* | ||
80 | * Do a system call from kernel instead of calling sys_execve so we | ||
81 | * end up with proper pt_regs. | ||
82 | */ | ||
83 | int kernel_execve(const char *filename, | ||
84 | const char *const argv[], | ||
85 | const char *const envp[]) | ||
86 | { | ||
87 | register const char *__a __asm__("r5") = filename; | ||
88 | register const void *__b __asm__("r6") = argv; | ||
89 | register const void *__c __asm__("r7") = envp; | ||
90 | register unsigned long __syscall __asm__("r12") = __NR_execve; | ||
91 | register unsigned long __ret __asm__("r3"); | ||
92 | __asm__ __volatile__ ("brki r14, 0x8" | ||
93 | : "=r" (__ret), "=r" (__syscall) | ||
94 | : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) | ||
95 | : "r4", "r8", "r9", | ||
96 | "r10", "r11", "r14", "cc", "memory"); | ||
97 | return __ret; | ||
98 | } | ||
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 6a2b294ef6dc..ff6431e54680 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S | |||
@@ -2,11 +2,7 @@ ENTRY(sys_call_table) | |||
2 | .long sys_restart_syscall /* 0 - old "setup()" system call, | 2 | .long sys_restart_syscall /* 0 - old "setup()" system call, |
3 | * used for restarting */ | 3 | * used for restarting */ |
4 | .long sys_exit | 4 | .long sys_exit |
5 | #ifdef CONFIG_MMU | 5 | .long sys_fork |
6 | .long sys_fork_wrapper | ||
7 | #else | ||
8 | .long sys_ni_syscall | ||
9 | #endif | ||
10 | .long sys_read | 6 | .long sys_read |
11 | .long sys_write | 7 | .long sys_write |
12 | .long sys_open /* 5 */ | 8 | .long sys_open /* 5 */ |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index dba9390d37cf..4183e62f178c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -40,6 +40,8 @@ config MIPS | |||
40 | select HAVE_MOD_ARCH_SPECIFIC | 40 | select HAVE_MOD_ARCH_SPECIFIC |
41 | select MODULES_USE_ELF_REL | 41 | select MODULES_USE_ELF_REL |
42 | select MODULES_USE_ELF_RELA if 64BIT | 42 | select MODULES_USE_ELF_RELA if 64BIT |
43 | select GENERIC_KERNEL_THREAD | ||
44 | select GENERIC_KERNEL_EXECVE | ||
43 | 45 | ||
44 | menu "Machine selection" | 46 | menu "Machine selection" |
45 | 47 | ||
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 5e33fabe354d..d28c41e0887c 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h | |||
@@ -310,8 +310,6 @@ struct task_struct; | |||
310 | /* Free all resources held by a thread. */ | 310 | /* Free all resources held by a thread. */ |
311 | #define release_thread(thread) do { } while(0) | 311 | #define release_thread(thread) do { } while(0) |
312 | 312 | ||
313 | extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
314 | |||
315 | extern unsigned long thread_saved_pc(struct task_struct *tsk); | 313 | extern unsigned long thread_saved_pc(struct task_struct *tsk); |
316 | 314 | ||
317 | /* | 315 | /* |
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index 4f5da948a777..cec5e125f7e4 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h | |||
@@ -61,4 +61,10 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs) | |||
61 | die(str, regs); | 61 | die(str, regs); |
62 | } | 62 | } |
63 | 63 | ||
64 | #define current_pt_regs() \ | ||
65 | ({ \ | ||
66 | unsigned long sp = (unsigned long)__builtin_frame_address(0); \ | ||
67 | (struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \ | ||
68 | }) | ||
69 | |||
64 | #endif /* _ASM_PTRACE_H */ | 70 | #endif /* _ASM_PTRACE_H */ |
diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h index 880240dff8b7..cf4a08062d1d 100644 --- a/arch/mips/include/asm/signal.h +++ b/arch/mips/include/asm/signal.h | |||
@@ -21,6 +21,4 @@ | |||
21 | #include <asm/sigcontext.h> | 21 | #include <asm/sigcontext.h> |
22 | #include <asm/siginfo.h> | 22 | #include <asm/siginfo.h> |
23 | 23 | ||
24 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
25 | |||
26 | #endif /* _ASM_SIGNAL_H */ | 24 | #endif /* _ASM_SIGNAL_H */ |
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 9e47cc11aa26..b306e2081cad 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 | 20 | #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 |
21 | #define __ARCH_WANT_OLD_READDIR | 21 | #define __ARCH_WANT_OLD_READDIR |
22 | #define __ARCH_WANT_SYS_ALARM | 22 | #define __ARCH_WANT_SYS_ALARM |
23 | #define __ARCH_WANT_SYS_EXECVE | ||
23 | #define __ARCH_WANT_SYS_GETHOSTNAME | 24 | #define __ARCH_WANT_SYS_GETHOSTNAME |
24 | #define __ARCH_WANT_SYS_IPC | 25 | #define __ARCH_WANT_SYS_IPC |
25 | #define __ARCH_WANT_SYS_PAUSE | 26 | #define __ARCH_WANT_SYS_PAUSE |
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 9b00362f32f6..e5786858cdb6 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S | |||
@@ -70,6 +70,12 @@ need_resched: | |||
70 | b need_resched | 70 | b need_resched |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | FEXPORT(ret_from_kernel_thread) | ||
74 | jal schedule_tail # a0 = struct task_struct *prev | ||
75 | move a0, s1 | ||
76 | jal s0 | ||
77 | j syscall_exit | ||
78 | |||
73 | FEXPORT(ret_from_fork) | 79 | FEXPORT(ret_from_fork) |
74 | jal schedule_tail # a0 = struct task_struct *prev | 80 | jal schedule_tail # a0 = struct task_struct *prev |
75 | 81 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 3a21acedf882..7adab86c632c 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -3,7 +3,6 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2000 Silicon Graphics, Inc. | 4 | * Copyright (C) 2000 Silicon Graphics, Inc. |
5 | * Written by Ulf Carlsson (ulfc@engr.sgi.com) | 5 | * Written by Ulf Carlsson (ulfc@engr.sgi.com) |
6 | * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) | ||
7 | */ | 6 | */ |
8 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
9 | #include <linux/mm.h> | 8 | #include <linux/mm.h> |
@@ -77,26 +76,6 @@ out: | |||
77 | return error; | 76 | return error; |
78 | } | 77 | } |
79 | 78 | ||
80 | /* | ||
81 | * sys_execve() executes a new program. | ||
82 | */ | ||
83 | asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) | ||
84 | { | ||
85 | int error; | ||
86 | struct filename *filename; | ||
87 | |||
88 | filename = getname(compat_ptr(regs.regs[4])); | ||
89 | error = PTR_ERR(filename); | ||
90 | if (IS_ERR(filename)) | ||
91 | goto out; | ||
92 | error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]), | ||
93 | compat_ptr(regs.regs[6]), ®s); | ||
94 | putname(filename); | ||
95 | |||
96 | out: | ||
97 | return error; | ||
98 | } | ||
99 | |||
100 | #define RLIM_INFINITY32 0x7fffffff | 79 | #define RLIM_INFINITY32 0x7fffffff |
101 | #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) | 80 | #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) |
102 | 81 | ||
@@ -333,7 +312,7 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs) | |||
333 | /* Use __dummy4 instead of getting it off the stack, so that | 312 | /* Use __dummy4 instead of getting it off the stack, so that |
334 | syscall() works. */ | 313 | syscall() works. */ |
335 | child_tidptr = (int __user *) __dummy4; | 314 | child_tidptr = (int __user *) __dummy4; |
336 | return do_fork(clone_flags, newsp, ®s, 0, | 315 | return do_fork(clone_flags, newsp, 0, |
337 | parent_tidptr, child_tidptr); | 316 | parent_tidptr, child_tidptr); |
338 | } | 317 | } |
339 | 318 | ||
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 3fc1691110dc..2d9304c2b54c 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c | |||
@@ -32,8 +32,6 @@ EXPORT_SYMBOL(memset); | |||
32 | EXPORT_SYMBOL(memcpy); | 32 | EXPORT_SYMBOL(memcpy); |
33 | EXPORT_SYMBOL(memmove); | 33 | EXPORT_SYMBOL(memmove); |
34 | 34 | ||
35 | EXPORT_SYMBOL(kernel_thread); | ||
36 | |||
37 | /* | 35 | /* |
38 | * Functions that operate on entire pages. Mostly used by memory management. | 36 | * Functions that operate on entire pages. Mostly used by memory management. |
39 | */ | 37 | */ |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index e9a5fd7277f4..38097652d62d 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -84,6 +84,7 @@ void __noreturn cpu_idle(void) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | asmlinkage void ret_from_fork(void); | 86 | asmlinkage void ret_from_fork(void); |
87 | asmlinkage void ret_from_kernel_thread(void); | ||
87 | 88 | ||
88 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) | 89 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) |
89 | { | 90 | { |
@@ -113,10 +114,10 @@ void flush_thread(void) | |||
113 | } | 114 | } |
114 | 115 | ||
115 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 116 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
116 | unsigned long unused, struct task_struct *p, struct pt_regs *regs) | 117 | unsigned long arg, struct task_struct *p) |
117 | { | 118 | { |
118 | struct thread_info *ti = task_thread_info(p); | 119 | struct thread_info *ti = task_thread_info(p); |
119 | struct pt_regs *childregs; | 120 | struct pt_regs *childregs, *regs = current_pt_regs(); |
120 | unsigned long childksp; | 121 | unsigned long childksp; |
121 | p->set_child_tid = p->clear_child_tid = NULL; | 122 | p->set_child_tid = p->clear_child_tid = NULL; |
122 | 123 | ||
@@ -136,19 +137,30 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
136 | childregs = (struct pt_regs *) childksp - 1; | 137 | childregs = (struct pt_regs *) childksp - 1; |
137 | /* Put the stack after the struct pt_regs. */ | 138 | /* Put the stack after the struct pt_regs. */ |
138 | childksp = (unsigned long) childregs; | 139 | childksp = (unsigned long) childregs; |
140 | p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); | ||
141 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
142 | unsigned long status = p->thread.cp0_status; | ||
143 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
144 | ti->addr_limit = KERNEL_DS; | ||
145 | p->thread.reg16 = usp; /* fn */ | ||
146 | p->thread.reg17 = arg; | ||
147 | p->thread.reg29 = childksp; | ||
148 | p->thread.reg31 = (unsigned long) ret_from_kernel_thread; | ||
149 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
150 | status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | | ||
151 | ((status & (ST0_KUC | ST0_IEC)) << 2); | ||
152 | #else | ||
153 | status |= ST0_EXL; | ||
154 | #endif | ||
155 | childregs->cp0_status = status; | ||
156 | return 0; | ||
157 | } | ||
139 | *childregs = *regs; | 158 | *childregs = *regs; |
140 | childregs->regs[7] = 0; /* Clear error flag */ | 159 | childregs->regs[7] = 0; /* Clear error flag */ |
141 | |||
142 | childregs->regs[2] = 0; /* Child gets zero as return value */ | 160 | childregs->regs[2] = 0; /* Child gets zero as return value */ |
161 | childregs->regs[29] = usp; | ||
162 | ti->addr_limit = USER_DS; | ||
143 | 163 | ||
144 | if (childregs->cp0_status & ST0_CU0) { | ||
145 | childregs->regs[28] = (unsigned long) ti; | ||
146 | childregs->regs[29] = childksp; | ||
147 | ti->addr_limit = KERNEL_DS; | ||
148 | } else { | ||
149 | childregs->regs[29] = usp; | ||
150 | ti->addr_limit = USER_DS; | ||
151 | } | ||
152 | p->thread.reg29 = (unsigned long) childregs; | 164 | p->thread.reg29 = (unsigned long) childregs; |
153 | p->thread.reg31 = (unsigned long) ret_from_fork; | 165 | p->thread.reg31 = (unsigned long) ret_from_fork; |
154 | 166 | ||
@@ -156,7 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
156 | * New tasks lose permission to use the fpu. This accelerates context | 168 | * New tasks lose permission to use the fpu. This accelerates context |
157 | * switching for most programs since they don't use the fpu. | 169 | * switching for most programs since they don't use the fpu. |
158 | */ | 170 | */ |
159 | p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); | ||
160 | childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); | 171 | childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); |
161 | 172 | ||
162 | #ifdef CONFIG_MIPS_MT_SMTC | 173 | #ifdef CONFIG_MIPS_MT_SMTC |
@@ -222,35 +233,6 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) | |||
222 | } | 233 | } |
223 | 234 | ||
224 | /* | 235 | /* |
225 | * Create a kernel thread | ||
226 | */ | ||
227 | static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
228 | { | ||
229 | do_exit(fn(arg)); | ||
230 | } | ||
231 | |||
232 | long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
233 | { | ||
234 | struct pt_regs regs; | ||
235 | |||
236 | memset(®s, 0, sizeof(regs)); | ||
237 | |||
238 | regs.regs[4] = (unsigned long) arg; | ||
239 | regs.regs[5] = (unsigned long) fn; | ||
240 | regs.cp0_epc = (unsigned long) kernel_thread_helper; | ||
241 | regs.cp0_status = read_c0_status(); | ||
242 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | ||
243 | regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | | ||
244 | ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2); | ||
245 | #else | ||
246 | regs.cp0_status |= ST0_EXL; | ||
247 | #endif | ||
248 | |||
249 | /* Ok, create the new process.. */ | ||
250 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * | 236 | * |
255 | */ | 237 | */ |
256 | struct mips_frame_info { | 238 | struct mips_frame_info { |
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 86ec03f0e00c..629719143763 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S | |||
@@ -167,7 +167,7 @@ EXPORT(sysn32_call_table) | |||
167 | PTR sys_getsockopt | 167 | PTR sys_getsockopt |
168 | PTR sys_clone /* 6055 */ | 168 | PTR sys_clone /* 6055 */ |
169 | PTR sys_fork | 169 | PTR sys_fork |
170 | PTR sys32_execve | 170 | PTR compat_sys_execve |
171 | PTR sys_exit | 171 | PTR sys_exit |
172 | PTR compat_sys_wait4 | 172 | PTR compat_sys_wait4 |
173 | PTR sys_kill /* 6060 */ | 173 | PTR sys_kill /* 6060 */ |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 53c2d7245764..9601be6afa3d 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
@@ -203,7 +203,7 @@ sys_call_table: | |||
203 | PTR sys_creat | 203 | PTR sys_creat |
204 | PTR sys_link | 204 | PTR sys_link |
205 | PTR sys_unlink /* 4010 */ | 205 | PTR sys_unlink /* 4010 */ |
206 | PTR sys32_execve | 206 | PTR compat_sys_execve |
207 | PTR sys_chdir | 207 | PTR sys_chdir |
208 | PTR compat_sys_time | 208 | PTR compat_sys_time |
209 | PTR sys_mknod | 209 | PTR sys_mknod |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 2bd561bc05ae..201cb76b4df9 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -92,7 +92,7 @@ save_static_function(sys_fork); | |||
92 | static int __used noinline | 92 | static int __used noinline |
93 | _sys_fork(nabi_no_regargs struct pt_regs regs) | 93 | _sys_fork(nabi_no_regargs struct pt_regs regs) |
94 | { | 94 | { |
95 | return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); | 95 | return do_fork(SIGCHLD, regs.regs[29], 0, NULL, NULL); |
96 | } | 96 | } |
97 | 97 | ||
98 | save_static_function(sys_clone); | 98 | save_static_function(sys_clone); |
@@ -123,32 +123,10 @@ _sys_clone(nabi_no_regargs struct pt_regs regs) | |||
123 | #else | 123 | #else |
124 | child_tidptr = (int __user *) regs.regs[8]; | 124 | child_tidptr = (int __user *) regs.regs[8]; |
125 | #endif | 125 | #endif |
126 | return do_fork(clone_flags, newsp, ®s, 0, | 126 | return do_fork(clone_flags, newsp, 0, |
127 | parent_tidptr, child_tidptr); | 127 | parent_tidptr, child_tidptr); |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | ||
131 | * sys_execve() executes a new program. | ||
132 | */ | ||
133 | asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) | ||
134 | { | ||
135 | int error; | ||
136 | struct filename *filename; | ||
137 | |||
138 | filename = getname((const char __user *) (long)regs.regs[4]); | ||
139 | error = PTR_ERR(filename); | ||
140 | if (IS_ERR(filename)) | ||
141 | goto out; | ||
142 | error = do_execve(filename->name, | ||
143 | (const char __user *const __user *) (long)regs.regs[5], | ||
144 | (const char __user *const __user *) (long)regs.regs[6], | ||
145 | ®s); | ||
146 | putname(filename); | ||
147 | |||
148 | out: | ||
149 | return error; | ||
150 | } | ||
151 | |||
152 | SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) | 130 | SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) |
153 | { | 131 | { |
154 | struct thread_info *ti = task_thread_info(current); | 132 | struct thread_info *ti = task_thread_info(current); |
@@ -313,34 +291,3 @@ asmlinkage void bad_stack(void) | |||
313 | { | 291 | { |
314 | do_exit(SIGSEGV); | 292 | do_exit(SIGSEGV); |
315 | } | 293 | } |
316 | |||
317 | /* | ||
318 | * Do a system call from kernel instead of calling sys_execve so we | ||
319 | * end up with proper pt_regs. | ||
320 | */ | ||
321 | int kernel_execve(const char *filename, | ||
322 | const char *const argv[], | ||
323 | const char *const envp[]) | ||
324 | { | ||
325 | register unsigned long __a0 asm("$4") = (unsigned long) filename; | ||
326 | register unsigned long __a1 asm("$5") = (unsigned long) argv; | ||
327 | register unsigned long __a2 asm("$6") = (unsigned long) envp; | ||
328 | register unsigned long __a3 asm("$7"); | ||
329 | unsigned long __v0; | ||
330 | |||
331 | __asm__ volatile (" \n" | ||
332 | " .set noreorder \n" | ||
333 | " li $2, %5 # __NR_execve \n" | ||
334 | " syscall \n" | ||
335 | " move %0, $2 \n" | ||
336 | " .set reorder \n" | ||
337 | : "=&r" (__v0), "=r" (__a3) | ||
338 | : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) | ||
339 | : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", | ||
340 | "memory"); | ||
341 | |||
342 | if (__a3 == 0) | ||
343 | return __v0; | ||
344 | |||
345 | return -__v0; | ||
346 | } | ||
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 04669fac117b..72471744a912 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -9,6 +9,7 @@ config MN10300 | |||
9 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER | 9 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER |
10 | select GENERIC_CLOCKEVENTS | 10 | select GENERIC_CLOCKEVENTS |
11 | select GENERIC_KERNEL_THREAD | 11 | select GENERIC_KERNEL_THREAD |
12 | select GENERIC_KERNEL_EXECVE | ||
12 | select MODULES_USE_ELF_RELA | 13 | select MODULES_USE_ELF_RELA |
13 | 14 | ||
14 | config AM33_2 | 15 | config AM33_2 |
diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h index f9668ec3040c..d280e9780793 100644 --- a/arch/mn10300/include/asm/signal.h +++ b/arch/mn10300/include/asm/signal.h | |||
@@ -45,8 +45,4 @@ struct k_sigaction { | |||
45 | }; | 45 | }; |
46 | #include <asm/sigcontext.h> | 46 | #include <asm/sigcontext.h> |
47 | 47 | ||
48 | |||
49 | struct pt_regs; | ||
50 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
51 | |||
52 | #endif /* _ASM_SIGNAL_H */ | 48 | #endif /* _ASM_SIGNAL_H */ |
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h index 55bbec1887e9..cabf8ba73b27 100644 --- a/arch/mn10300/include/asm/unistd.h +++ b/arch/mn10300/include/asm/unistd.h | |||
@@ -44,7 +44,9 @@ | |||
44 | #define __ARCH_WANT_SYS_RT_SIGACTION | 44 | #define __ARCH_WANT_SYS_RT_SIGACTION |
45 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 45 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
46 | #define __ARCH_WANT_SYS_EXECVE | 46 | #define __ARCH_WANT_SYS_EXECVE |
47 | #define __ARCH_WANT_KERNEL_EXECVE | 47 | #define __ARCH_WANT_SYS_FORK |
48 | #define __ARCH_WANT_SYS_VFORK | ||
49 | #define __ARCH_WANT_SYS_CLONE | ||
48 | 50 | ||
49 | /* | 51 | /* |
50 | * "Conditional" syscalls | 52 | * "Conditional" syscalls |
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 0c631d34c8d7..68fcab8f8f6f 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S | |||
@@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread) | |||
60 | mov (REG_D0,fp),d0 | 60 | mov (REG_D0,fp),d0 |
61 | mov (REG_A0,fp),a0 | 61 | mov (REG_A0,fp),a0 |
62 | calls (a0) | 62 | calls (a0) |
63 | jmp sys_exit | ||
64 | |||
65 | ENTRY(ret_from_kernel_execve) | ||
66 | add -12,d0 /* pt_regs -> frame */ | ||
67 | mov d0,sp | ||
68 | GET_THREAD_INFO a2 | ||
69 | clr d0 | 63 | clr d0 |
64 | mov d0,(REG_D0,fp) | ||
70 | jmp syscall_exit | 65 | jmp syscall_exit |
71 | 66 | ||
72 | ############################################################################### | 67 | ############################################################################### |
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index d0c671b6d9ff..eb09f5a552ff 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
@@ -206,7 +206,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
206 | */ | 206 | */ |
207 | int copy_thread(unsigned long clone_flags, | 207 | int copy_thread(unsigned long clone_flags, |
208 | unsigned long c_usp, unsigned long ustk_size, | 208 | unsigned long c_usp, unsigned long ustk_size, |
209 | struct task_struct *p, struct pt_regs *kregs) | 209 | struct task_struct *p) |
210 | { | 210 | { |
211 | struct thread_info *ti = task_thread_info(p); | 211 | struct thread_info *ti = task_thread_info(p); |
212 | struct pt_regs *c_regs; | 212 | struct pt_regs *c_regs; |
@@ -227,7 +227,7 @@ int copy_thread(unsigned long clone_flags, | |||
227 | p->thread.wchan = p->thread.pc; | 227 | p->thread.wchan = p->thread.pc; |
228 | p->thread.usp = c_usp; | 228 | p->thread.usp = c_usp; |
229 | 229 | ||
230 | if (unlikely(!kregs)) { | 230 | if (unlikely(p->flags & PF_KTHREAD)) { |
231 | memset(c_regs, 0, sizeof(struct pt_regs)); | 231 | memset(c_regs, 0, sizeof(struct pt_regs)); |
232 | c_regs->a0 = c_usp; /* function */ | 232 | c_regs->a0 = c_usp; /* function */ |
233 | c_regs->d0 = ustk_size; /* argument */ | 233 | c_regs->d0 = ustk_size; /* argument */ |
@@ -236,8 +236,9 @@ int copy_thread(unsigned long clone_flags, | |||
236 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | 236 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
237 | return 0; | 237 | return 0; |
238 | } | 238 | } |
239 | *c_regs = *kregs; | 239 | *c_regs = *current_pt_regs(); |
240 | c_regs->sp = c_usp; | 240 | if (c_usp) |
241 | c_regs->sp = c_usp; | ||
241 | c_regs->epsw &= ~EPSW_FE; /* my FPU */ | 242 | c_regs->epsw &= ~EPSW_FE; /* my FPU */ |
242 | 243 | ||
243 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ | 244 | /* the new TLS pointer is passed in as arg #5 to sys_clone() */ |
@@ -249,30 +250,6 @@ int copy_thread(unsigned long clone_flags, | |||
249 | return 0; | 250 | return 0; |
250 | } | 251 | } |
251 | 252 | ||
252 | /* | ||
253 | * clone a process | ||
254 | * - tlsptr is retrieved by copy_thread() from current_frame()->d3 | ||
255 | */ | ||
256 | asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
257 | int __user *parent_tidptr, int __user *child_tidptr, | ||
258 | int __user *tlsptr) | ||
259 | { | ||
260 | return do_fork(clone_flags, newsp ?: current_frame()->sp, | ||
261 | current_frame(), 0, parent_tidptr, child_tidptr); | ||
262 | } | ||
263 | |||
264 | asmlinkage long sys_fork(void) | ||
265 | { | ||
266 | return do_fork(SIGCHLD, current_frame()->sp, | ||
267 | current_frame(), 0, NULL, NULL); | ||
268 | } | ||
269 | |||
270 | asmlinkage long sys_vfork(void) | ||
271 | { | ||
272 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp, | ||
273 | current_frame(), 0, NULL, NULL); | ||
274 | } | ||
275 | |||
276 | unsigned long get_wchan(struct task_struct *p) | 253 | unsigned long get_wchan(struct task_struct *p) |
277 | { | 254 | { |
278 | return p->thread.wchan; | 255 | return p->thread.wchan; |
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 05f2ba41ff1a..e7f1a2993f78 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
@@ -22,6 +22,8 @@ config OPENRISC | |||
22 | select GENERIC_STRNCPY_FROM_USER | 22 | select GENERIC_STRNCPY_FROM_USER |
23 | select GENERIC_STRNLEN_USER | 23 | select GENERIC_STRNLEN_USER |
24 | select MODULES_USE_ELF_RELA | 24 | select MODULES_USE_ELF_RELA |
25 | select GENERIC_KERNEL_THREAD | ||
26 | select GENERIC_KERNEL_EXECVE | ||
25 | 27 | ||
26 | config MMU | 28 | config MMU |
27 | def_bool y | 29 | def_bool y |
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h index 43decdbdb2ed..33691380608e 100644 --- a/arch/openrisc/include/asm/processor.h +++ b/arch/openrisc/include/asm/processor.h | |||
@@ -81,8 +81,6 @@ struct thread_struct { | |||
81 | #define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp) | 81 | #define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp) |
82 | 82 | ||
83 | 83 | ||
84 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
85 | |||
86 | void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); | 84 | void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); |
87 | void release_thread(struct task_struct *); | 85 | void release_thread(struct task_struct *); |
88 | unsigned long get_wchan(struct task_struct *p); | 86 | unsigned long get_wchan(struct task_struct *p); |
diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h index 84a978af44d7..8ee816812a9e 100644 --- a/arch/openrisc/include/asm/syscalls.h +++ b/arch/openrisc/include/asm/syscalls.h | |||
@@ -24,4 +24,11 @@ asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1, | |||
24 | 24 | ||
25 | #include <asm-generic/syscalls.h> | 25 | #include <asm-generic/syscalls.h> |
26 | 26 | ||
27 | asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
28 | void __user *parent_tid, void __user *child_tid, int tls); | ||
29 | asmlinkage long __sys_fork(void); | ||
30 | |||
31 | #define sys_clone __sys_clone | ||
32 | #define sys_fork __sys_fork | ||
33 | |||
27 | #endif /* __ASM_OPENRISC_SYSCALLS_H */ | 34 | #endif /* __ASM_OPENRISC_SYSCALLS_H */ |
diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 437bdbb61b14..5082b8066325 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h | |||
@@ -20,6 +20,10 @@ | |||
20 | 20 | ||
21 | #define sys_mmap2 sys_mmap_pgoff | 21 | #define sys_mmap2 sys_mmap_pgoff |
22 | 22 | ||
23 | #define __ARCH_WANT_SYS_EXECVE | ||
24 | #define __ARCH_WANT_SYS_FORK | ||
25 | #define __ARCH_WANT_SYS_CLONE | ||
26 | |||
23 | #include <asm-generic/unistd.h> | 27 | #include <asm-generic/unistd.h> |
24 | 28 | ||
25 | #define __NR_or1k_atomic __NR_arch_specific_syscall | 29 | #define __NR_or1k_atomic __NR_arch_specific_syscall |
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile index e1ee0fa2bbda..35f92ce51c24 100644 --- a/arch/openrisc/kernel/Makefile +++ b/arch/openrisc/kernel/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | extra-y := head.o vmlinux.lds | 5 | extra-y := head.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \ | 7 | obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \ |
8 | traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \ | 8 | traps.o time.o irq.o entry.o ptrace.o signal.o \ |
9 | sys_call_table.o | 9 | sys_call_table.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODULES) += module.o | 11 | obj-$(CONFIG_MODULES) += module.o |
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index ddfcaa828b0e..5e5b30601bbf 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S | |||
@@ -894,6 +894,16 @@ ENTRY(ret_from_fork) | |||
894 | l.jal schedule_tail | 894 | l.jal schedule_tail |
895 | l.nop | 895 | l.nop |
896 | 896 | ||
897 | /* Check if we are a kernel thread */ | ||
898 | l.sfeqi r20,0 | ||
899 | l.bf 1f | ||
900 | l.nop | ||
901 | |||
902 | /* ...we are a kernel thread so invoke the requested callback */ | ||
903 | l.jalr r20 | ||
904 | l.or r3,r22,r0 | ||
905 | |||
906 | 1: | ||
897 | /* _syscall_returns expect r11 to contain return value */ | 907 | /* _syscall_returns expect r11 to contain return value */ |
898 | l.lwz r11,PT_GPR11(r1) | 908 | l.lwz r11,PT_GPR11(r1) |
899 | 909 | ||
@@ -915,26 +925,6 @@ ENTRY(ret_from_fork) | |||
915 | l.j _syscall_return | 925 | l.j _syscall_return |
916 | l.nop | 926 | l.nop |
917 | 927 | ||
918 | /* Since syscalls don't save call-clobbered registers, the args to | ||
919 | * kernel_thread_helper will need to be passed through callee-saved | ||
920 | * registers and copied to the parameter registers when the thread | ||
921 | * begins running. | ||
922 | * | ||
923 | * See arch/openrisc/kernel/process.c: | ||
924 | * The args are passed as follows: | ||
925 | * arg1 (r3) : passed in r20 | ||
926 | * arg2 (r4) : passed in r22 | ||
927 | */ | ||
928 | |||
929 | ENTRY(_kernel_thread_helper) | ||
930 | l.or r3,r20,r0 | ||
931 | l.or r4,r22,r0 | ||
932 | l.movhi r31,hi(kernel_thread_helper) | ||
933 | l.ori r31,r31,lo(kernel_thread_helper) | ||
934 | l.jr r31 | ||
935 | l.nop | ||
936 | |||
937 | |||
938 | /* ========================================================[ switch ] === */ | 928 | /* ========================================================[ switch ] === */ |
939 | 929 | ||
940 | /* | 930 | /* |
@@ -1044,8 +1034,13 @@ ENTRY(_switch) | |||
1044 | /* Unwind stack to pre-switch state */ | 1034 | /* Unwind stack to pre-switch state */ |
1045 | l.addi r1,r1,(INT_FRAME_SIZE) | 1035 | l.addi r1,r1,(INT_FRAME_SIZE) |
1046 | 1036 | ||
1047 | /* Return via the link-register back to where we 'came from', where that can be | 1037 | /* Return via the link-register back to where we 'came from', where |
1048 | * either schedule() or return_from_fork()... */ | 1038 | * that may be either schedule(), ret_from_fork(), or |
1039 | * ret_from_kernel_thread(). If we are returning to a new thread, | ||
1040 | * we are expected to have set up the arg to schedule_tail already, | ||
1041 | * hence we do so here unconditionally: | ||
1042 | */ | ||
1043 | l.lwz r3,TI_STACK(r3) /* Load 'prev' as schedule_tail arg */ | ||
1049 | l.jr r9 | 1044 | l.jr r9 |
1050 | l.nop | 1045 | l.nop |
1051 | 1046 | ||
@@ -1076,22 +1071,18 @@ _fork_save_extra_regs_and_call: | |||
1076 | l.jr r29 | 1071 | l.jr r29 |
1077 | l.sw PT_GPR28(r1),r28 | 1072 | l.sw PT_GPR28(r1),r28 |
1078 | 1073 | ||
1079 | ENTRY(sys_clone) | 1074 | ENTRY(__sys_clone) |
1080 | l.movhi r29,hi(_sys_clone) | 1075 | l.movhi r29,hi(sys_clone) |
1081 | l.ori r29,r29,lo(_sys_clone) | 1076 | l.ori r29,r29,lo(sys_clone) |
1082 | l.j _fork_save_extra_regs_and_call | 1077 | l.j _fork_save_extra_regs_and_call |
1083 | l.addi r7,r1,0 | 1078 | l.addi r7,r1,0 |
1084 | 1079 | ||
1085 | ENTRY(sys_fork) | 1080 | ENTRY(__sys_fork) |
1086 | l.movhi r29,hi(_sys_fork) | 1081 | l.movhi r29,hi(sys_fork) |
1087 | l.ori r29,r29,lo(_sys_fork) | 1082 | l.ori r29,r29,lo(sys_fork) |
1088 | l.j _fork_save_extra_regs_and_call | 1083 | l.j _fork_save_extra_regs_and_call |
1089 | l.addi r3,r1,0 | 1084 | l.addi r3,r1,0 |
1090 | 1085 | ||
1091 | ENTRY(sys_execve) | ||
1092 | l.j _sys_execve | ||
1093 | l.addi r6,r1,0 | ||
1094 | |||
1095 | ENTRY(sys_sigaltstack) | 1086 | ENTRY(sys_sigaltstack) |
1096 | l.j _sys_sigaltstack | 1087 | l.j _sys_sigaltstack |
1097 | l.addi r5,r1,0 | 1088 | l.addi r5,r1,0 |
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index c35f3ab1a8d3..00c233bf0d06 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c | |||
@@ -109,66 +109,83 @@ void release_thread(struct task_struct *dead_task) | |||
109 | */ | 109 | */ |
110 | extern asmlinkage void ret_from_fork(void); | 110 | extern asmlinkage void ret_from_fork(void); |
111 | 111 | ||
112 | /* | ||
113 | * copy_thread | ||
114 | * @clone_flags: flags | ||
115 | * @usp: user stack pointer or fn for kernel thread | ||
116 | * @arg: arg to fn for kernel thread; always NULL for userspace thread | ||
117 | * @p: the newly created task | ||
118 | * @regs: CPU context to copy for userspace thread; always NULL for kthread | ||
119 | * | ||
120 | * At the top of a newly initialized kernel stack are two stacked pt_reg | ||
121 | * structures. The first (topmost) is the userspace context of the thread. | ||
122 | * The second is the kernelspace context of the thread. | ||
123 | * | ||
124 | * A kernel thread will not be returning to userspace, so the topmost pt_regs | ||
125 | * struct can be uninitialized; it _does_ need to exist, though, because | ||
126 | * a kernel thread can become a userspace thread by doing a kernel_execve, in | ||
127 | * which case the topmost context will be initialized and used for 'returning' | ||
128 | * to userspace. | ||
129 | * | ||
130 | * The second pt_reg struct needs to be initialized to 'return' to | ||
131 | * ret_from_fork. A kernel thread will need to set r20 to the address of | ||
132 | * a function to call into (with arg in r22); userspace threads need to set | ||
133 | * r20 to NULL in which case ret_from_fork will just continue a return to | ||
134 | * userspace. | ||
135 | * | ||
136 | * A kernel thread 'fn' may return; this is effectively what happens when | ||
137 | * kernel_execve is called. In that case, the userspace pt_regs must have | ||
138 | * been initialized (which kernel_execve takes care of, see start_thread | ||
139 | * below); ret_from_fork will then continue its execution causing the | ||
140 | * 'kernel thread' to return to userspace as a userspace thread. | ||
141 | */ | ||
142 | |||
112 | int | 143 | int |
113 | copy_thread(unsigned long clone_flags, unsigned long usp, | 144 | copy_thread(unsigned long clone_flags, unsigned long usp, |
114 | unsigned long unused, struct task_struct *p, struct pt_regs *regs) | 145 | unsigned long arg, struct task_struct *p) |
115 | { | 146 | { |
116 | struct pt_regs *childregs; | 147 | struct pt_regs *userregs; |
117 | struct pt_regs *kregs; | 148 | struct pt_regs *kregs; |
118 | unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; | 149 | unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; |
119 | struct thread_info *ti; | ||
120 | unsigned long top_of_kernel_stack; | 150 | unsigned long top_of_kernel_stack; |
121 | 151 | ||
122 | top_of_kernel_stack = sp; | 152 | top_of_kernel_stack = sp; |
123 | 153 | ||
124 | p->set_child_tid = p->clear_child_tid = NULL; | 154 | p->set_child_tid = p->clear_child_tid = NULL; |
125 | 155 | ||
126 | /* Copy registers */ | 156 | /* Locate userspace context on stack... */ |
127 | /* redzone */ | 157 | sp -= STACK_FRAME_OVERHEAD; /* redzone */ |
128 | sp -= STACK_FRAME_OVERHEAD; | ||
129 | sp -= sizeof(struct pt_regs); | 158 | sp -= sizeof(struct pt_regs); |
130 | childregs = (struct pt_regs *)sp; | 159 | userregs = (struct pt_regs *) sp; |
131 | 160 | ||
132 | /* Copy parent registers */ | 161 | /* ...and kernel context */ |
133 | *childregs = *regs; | 162 | sp -= STACK_FRAME_OVERHEAD; /* redzone */ |
163 | sp -= sizeof(struct pt_regs); | ||
164 | kregs = (struct pt_regs *)sp; | ||
134 | 165 | ||
135 | if ((childregs->sr & SPR_SR_SM) == 1) { | 166 | if (unlikely(p->flags & PF_KTHREAD)) { |
136 | /* for kernel thread, set `current_thread_info' | 167 | memset(kregs, 0, sizeof(struct pt_regs)); |
137 | * and stackptr in new task | 168 | kregs->gpr[20] = usp; /* fn, kernel thread */ |
138 | */ | 169 | kregs->gpr[22] = arg; |
139 | childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; | ||
140 | childregs->gpr[10] = (unsigned long)task_thread_info(p); | ||
141 | } else { | 170 | } else { |
142 | childregs->sp = usp; | 171 | *userregs = *current_pt_regs(); |
143 | } | ||
144 | |||
145 | childregs->gpr[11] = 0; /* Result from fork() */ | ||
146 | 172 | ||
147 | /* | 173 | if (usp) |
148 | * The way this works is that at some point in the future | 174 | userregs->sp = usp; |
149 | * some task will call _switch to switch to the new task. | 175 | userregs->gpr[11] = 0; /* Result from fork() */ |
150 | * That will pop off the stack frame created below and start | ||
151 | * the new task running at ret_from_fork. The new task will | ||
152 | * do some house keeping and then return from the fork or clone | ||
153 | * system call, using the stack frame created above. | ||
154 | */ | ||
155 | /* redzone */ | ||
156 | sp -= STACK_FRAME_OVERHEAD; | ||
157 | sp -= sizeof(struct pt_regs); | ||
158 | kregs = (struct pt_regs *)sp; | ||
159 | 176 | ||
160 | ti = task_thread_info(p); | 177 | kregs->gpr[20] = 0; /* Userspace thread */ |
161 | ti->ksp = sp; | 178 | } |
162 | 179 | ||
163 | /* kregs->sp must store the location of the 'pre-switch' kernel stack | 180 | /* |
164 | * pointer... for a newly forked process, this is simply the top of | 181 | * _switch wants the kernel stack page in pt_regs->sp so that it |
165 | * the kernel stack. | 182 | * can restore it to thread_info->ksp... see _switch for details. |
166 | */ | 183 | */ |
167 | kregs->sp = top_of_kernel_stack; | 184 | kregs->sp = top_of_kernel_stack; |
168 | kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */ | ||
169 | kregs->gpr[10] = (unsigned long)task_thread_info(p); | ||
170 | kregs->gpr[9] = (unsigned long)ret_from_fork; | 185 | kregs->gpr[9] = (unsigned long)ret_from_fork; |
171 | 186 | ||
187 | task_thread_info(p)->ksp = (unsigned long)kregs; | ||
188 | |||
172 | return 0; | 189 | return 0; |
173 | } | 190 | } |
174 | 191 | ||
@@ -177,16 +194,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
177 | */ | 194 | */ |
178 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) | 195 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) |
179 | { | 196 | { |
180 | unsigned long sr = regs->sr & ~SPR_SR_SM; | 197 | unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; |
181 | 198 | ||
182 | set_fs(USER_DS); | 199 | set_fs(USER_DS); |
183 | memset(regs->gpr, 0, sizeof(regs->gpr)); | 200 | memset(regs, 0, sizeof(struct pt_regs)); |
184 | 201 | ||
185 | regs->pc = pc; | 202 | regs->pc = pc; |
186 | regs->sr = sr; | 203 | regs->sr = sr; |
187 | regs->sp = sp; | 204 | regs->sp = sp; |
188 | |||
189 | /* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/ | ||
190 | } | 205 | } |
191 | 206 | ||
192 | /* Fill in the fpu structure for a core dump. */ | 207 | /* Fill in the fpu structure for a core dump. */ |
@@ -237,74 +252,9 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) | |||
237 | dest[35] = 0; | 252 | dest[35] = 0; |
238 | } | 253 | } |
239 | 254 | ||
240 | extern void _kernel_thread_helper(void); | ||
241 | |||
242 | void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg) | ||
243 | { | ||
244 | do_exit(fn(arg)); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Create a kernel thread. | ||
249 | */ | ||
250 | int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) | ||
251 | { | ||
252 | struct pt_regs regs; | ||
253 | |||
254 | memset(®s, 0, sizeof(regs)); | ||
255 | |||
256 | regs.gpr[20] = (unsigned long)fn; | ||
257 | regs.gpr[22] = (unsigned long)arg; | ||
258 | regs.sr = mfspr(SPR_SR); | ||
259 | regs.pc = (unsigned long)_kernel_thread_helper; | ||
260 | |||
261 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, | ||
262 | 0, ®s, 0, NULL, NULL); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * sys_execve() executes a new program. | ||
267 | */ | ||
268 | asmlinkage long _sys_execve(const char __user *name, | ||
269 | const char __user * const __user *argv, | ||
270 | const char __user * const __user *envp, | ||
271 | struct pt_regs *regs) | ||
272 | { | ||
273 | int error; | ||
274 | struct filename *filename; | ||
275 | |||
276 | filename = getname(name); | ||
277 | error = PTR_ERR(filename); | ||
278 | |||
279 | if (IS_ERR(filename)) | ||
280 | goto out; | ||
281 | |||
282 | error = do_execve(filename->name, argv, envp, regs); | ||
283 | putname(filename); | ||
284 | |||
285 | out: | ||
286 | return error; | ||
287 | } | ||
288 | |||
289 | unsigned long get_wchan(struct task_struct *p) | 255 | unsigned long get_wchan(struct task_struct *p) |
290 | { | 256 | { |
291 | /* TODO */ | 257 | /* TODO */ |
292 | 258 | ||
293 | return 0; | 259 | return 0; |
294 | } | 260 | } |
295 | |||
296 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) | ||
297 | { | ||
298 | register long __res asm("r11") = __NR_execve; | ||
299 | register long __a asm("r3") = (long)(filename); | ||
300 | register long __b asm("r4") = (long)(argv); | ||
301 | register long __c asm("r5") = (long)(envp); | ||
302 | __asm__ volatile ("l.sys 1" | ||
303 | : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c) | ||
304 | : "0"(__res), "1"(__a), "2"(__b), "3"(__c) | ||
305 | : "r6", "r7", "r8", "r12", "r13", "r15", | ||
306 | "r17", "r19", "r21", "r23", "r25", "r27", | ||
307 | "r29", "r31"); | ||
308 | __asm__ volatile ("l.nop"); | ||
309 | return __res; | ||
310 | } | ||
diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c deleted file mode 100644 index 57060084c0cc..000000000000 --- a/arch/openrisc/kernel/sys_or32.c +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /* | ||
2 | * OpenRISC sys_or32.c | ||
3 | * | ||
4 | * Linux architectural port borrowing liberally from similar works of | ||
5 | * others. All original copyrights apply as per the original source | ||
6 | * declaration. | ||
7 | * | ||
8 | * Modifications for the OpenRISC architecture: | ||
9 | * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> | ||
10 | * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This file contains various random system calls that | ||
18 | * have a non-standard calling sequence on some platforms. | ||
19 | * Since we don't have to do any backwards compatibility, our | ||
20 | * versions are done in the most "normal" way possible. | ||
21 | */ | ||
22 | |||
23 | #include <linux/errno.h> | ||
24 | #include <linux/syscalls.h> | ||
25 | #include <linux/mm.h> | ||
26 | |||
27 | #include <asm/syscalls.h> | ||
28 | |||
29 | /* These are secondary entry points as the primary entry points are defined in | ||
30 | * entry.S where we add the 'regs' parameter value | ||
31 | */ | ||
32 | |||
33 | asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
34 | int __user *parent_tid, int __user *child_tid, | ||
35 | struct pt_regs *regs) | ||
36 | { | ||
37 | long ret; | ||
38 | |||
39 | /* FIXME: Is alignment necessary? */ | ||
40 | /* newsp = ALIGN(newsp, 4); */ | ||
41 | |||
42 | if (!newsp) | ||
43 | newsp = regs->sp; | ||
44 | |||
45 | ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | asmlinkage int _sys_fork(struct pt_regs *regs) | ||
51 | { | ||
52 | #ifdef CONFIG_MMU | ||
53 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
54 | #else | ||
55 | return -EINVAL; | ||
56 | #endif | ||
57 | } | ||
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 11def45b98c5..e688a2be30f6 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -22,6 +22,9 @@ config PARISC | |||
22 | select GENERIC_STRNCPY_FROM_USER | 22 | select GENERIC_STRNCPY_FROM_USER |
23 | select HAVE_MOD_ARCH_SPECIFIC | 23 | select HAVE_MOD_ARCH_SPECIFIC |
24 | select MODULES_USE_ELF_RELA | 24 | select MODULES_USE_ELF_RELA |
25 | select GENERIC_KERNEL_THREAD | ||
26 | select GENERIC_KERNEL_EXECVE | ||
27 | select CLONE_BACKWARDS | ||
25 | 28 | ||
26 | help | 29 | help |
27 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 30 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 0e8b7b8ce8a2..09b54a57a48d 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h | |||
@@ -326,7 +326,6 @@ struct mm_struct; | |||
326 | 326 | ||
327 | /* Free all resources held by a thread. */ | 327 | /* Free all resources held by a thread. */ |
328 | extern void release_thread(struct task_struct *); | 328 | extern void release_thread(struct task_struct *); |
329 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
330 | 329 | ||
331 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); | 330 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); |
332 | 331 | ||
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h index 21abf4fc169a..0fdb3c835952 100644 --- a/arch/parisc/include/asm/signal.h +++ b/arch/parisc/include/asm/signal.h | |||
@@ -34,8 +34,6 @@ struct k_sigaction { | |||
34 | struct sigaction sa; | 34 | struct sigaction sa; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
38 | |||
39 | #include <asm/sigcontext.h> | 37 | #include <asm/sigcontext.h> |
40 | 38 | ||
41 | #endif /* !__ASSEMBLY */ | 39 | #endif /* !__ASSEMBLY */ |
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index 541639c3f607..1efef41659c9 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h | |||
@@ -163,6 +163,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ | |||
163 | #define __ARCH_WANT_SYS_RT_SIGACTION | 163 | #define __ARCH_WANT_SYS_RT_SIGACTION |
164 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 164 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
165 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 165 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
166 | #define __ARCH_WANT_SYS_EXECVE | ||
167 | #define __ARCH_WANT_SYS_FORK | ||
168 | #define __ARCH_WANT_SYS_VFORK | ||
169 | #define __ARCH_WANT_SYS_CLONE | ||
166 | 170 | ||
167 | #endif /* __ASSEMBLY__ */ | 171 | #endif /* __ASSEMBLY__ */ |
168 | 172 | ||
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 18670a078849..bfb44247d7a7 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -708,59 +708,9 @@ ENTRY(end_fault_vector) | |||
708 | .import do_cpu_irq_mask,code | 708 | .import do_cpu_irq_mask,code |
709 | 709 | ||
710 | /* | 710 | /* |
711 | * r26 = function to be called | ||
712 | * r25 = argument to pass in | ||
713 | * r24 = flags for do_fork() | ||
714 | * | ||
715 | * Kernel threads don't ever return, so they don't need | ||
716 | * a true register context. We just save away the arguments | ||
717 | * for copy_thread/ret_ to properly set up the child. | ||
718 | */ | ||
719 | |||
720 | #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ | ||
721 | #define CLONE_UNTRACED 0x00800000 | ||
722 | |||
723 | .import do_fork | ||
724 | ENTRY(__kernel_thread) | ||
725 | STREG %r2, -RP_OFFSET(%r30) | ||
726 | |||
727 | copy %r30, %r1 | ||
728 | ldo PT_SZ_ALGN(%r30),%r30 | ||
729 | #ifdef CONFIG_64BIT | ||
730 | /* Yo, function pointers in wide mode are little structs... -PB */ | ||
731 | ldd 24(%r26), %r2 | ||
732 | STREG %r2, PT_GR27(%r1) /* Store childs %dp */ | ||
733 | ldd 16(%r26), %r26 | ||
734 | |||
735 | STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ | ||
736 | copy %r0, %r22 /* user_tid */ | ||
737 | #endif | ||
738 | STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ | ||
739 | STREG %r25, PT_GR25(%r1) | ||
740 | ldil L%CLONE_UNTRACED, %r26 | ||
741 | ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ | ||
742 | or %r26, %r24, %r26 /* will have kernel mappings. */ | ||
743 | ldi 1, %r25 /* stack_start, signals kernel thread */ | ||
744 | stw %r0, -52(%r30) /* user_tid */ | ||
745 | #ifdef CONFIG_64BIT | ||
746 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
747 | #endif | ||
748 | BL do_fork, %r2 | ||
749 | copy %r1, %r24 /* pt_regs */ | ||
750 | |||
751 | /* Parent Returns here */ | ||
752 | |||
753 | LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 | ||
754 | ldo -PT_SZ_ALGN(%r30), %r30 | ||
755 | bv %r0(%r2) | ||
756 | nop | ||
757 | ENDPROC(__kernel_thread) | ||
758 | |||
759 | /* | ||
760 | * Child Returns here | 711 | * Child Returns here |
761 | * | 712 | * |
762 | * copy_thread moved args from temp save area set up above | 713 | * copy_thread moved args into task save area. |
763 | * into task save area. | ||
764 | */ | 714 | */ |
765 | 715 | ||
766 | ENTRY(ret_from_kernel_thread) | 716 | ENTRY(ret_from_kernel_thread) |
@@ -769,51 +719,17 @@ ENTRY(ret_from_kernel_thread) | |||
769 | BL schedule_tail, %r2 | 719 | BL schedule_tail, %r2 |
770 | nop | 720 | nop |
771 | 721 | ||
772 | LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 | 722 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 |
773 | LDREG TASK_PT_GR25(%r1), %r26 | 723 | LDREG TASK_PT_GR25(%r1), %r26 |
774 | #ifdef CONFIG_64BIT | 724 | #ifdef CONFIG_64BIT |
775 | LDREG TASK_PT_GR27(%r1), %r27 | 725 | LDREG TASK_PT_GR27(%r1), %r27 |
776 | LDREG TASK_PT_GR22(%r1), %r22 | ||
777 | #endif | 726 | #endif |
778 | LDREG TASK_PT_GR26(%r1), %r1 | 727 | LDREG TASK_PT_GR26(%r1), %r1 |
779 | ble 0(%sr7, %r1) | 728 | ble 0(%sr7, %r1) |
780 | copy %r31, %r2 | 729 | copy %r31, %r2 |
781 | 730 | b finish_child_return | |
782 | #ifdef CONFIG_64BIT | ||
783 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
784 | loadgp /* Thread could have been in a module */ | ||
785 | #endif | ||
786 | #ifndef CONFIG_64BIT | ||
787 | b sys_exit | ||
788 | #else | ||
789 | load32 sys_exit, %r1 | ||
790 | bv %r0(%r1) | ||
791 | #endif | ||
792 | ldi 0, %r26 | ||
793 | ENDPROC(ret_from_kernel_thread) | ||
794 | |||
795 | .import sys_execve, code | ||
796 | ENTRY(__execve) | ||
797 | copy %r2, %r15 | ||
798 | copy %r30, %r16 | ||
799 | ldo PT_SZ_ALGN(%r30), %r30 | ||
800 | STREG %r26, PT_GR26(%r16) | ||
801 | STREG %r25, PT_GR25(%r16) | ||
802 | STREG %r24, PT_GR24(%r16) | ||
803 | #ifdef CONFIG_64BIT | ||
804 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
805 | #endif | ||
806 | BL sys_execve, %r2 | ||
807 | copy %r16, %r26 | ||
808 | |||
809 | cmpib,=,n 0,%r28,intr_return /* forward */ | ||
810 | |||
811 | /* yes, this will trap and die. */ | ||
812 | copy %r15, %r2 | ||
813 | copy %r16, %r30 | ||
814 | bv %r0(%r2) | ||
815 | nop | 731 | nop |
816 | ENDPROC(__execve) | 732 | ENDPROC(ret_from_kernel_thread) |
817 | 733 | ||
818 | 734 | ||
819 | /* | 735 | /* |
@@ -1772,151 +1688,36 @@ dtlb_fault: | |||
1772 | LDREG PT_GR18(\regs),%r18 | 1688 | LDREG PT_GR18(\regs),%r18 |
1773 | .endm | 1689 | .endm |
1774 | 1690 | ||
1775 | ENTRY(sys_fork_wrapper) | 1691 | .macro fork_like name |
1692 | ENTRY(sys_\name\()_wrapper) | ||
1776 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | 1693 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 |
1777 | ldo TASK_REGS(%r1),%r1 | 1694 | ldo TASK_REGS(%r1),%r1 |
1778 | reg_save %r1 | 1695 | reg_save %r1 |
1779 | mfctl %cr27, %r3 | 1696 | mfctl %cr27, %r28 |
1780 | STREG %r3, PT_CR27(%r1) | 1697 | b sys_\name |
1781 | 1698 | STREG %r28, PT_CR27(%r1) | |
1782 | STREG %r2,-RP_OFFSET(%r30) | 1699 | ENDPROC(sys_\name\()_wrapper) |
1783 | ldo FRAME_SIZE(%r30),%r30 | 1700 | .endm |
1784 | #ifdef CONFIG_64BIT | ||
1785 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1786 | #endif | ||
1787 | |||
1788 | /* These are call-clobbered registers and therefore | ||
1789 | also syscall-clobbered (we hope). */ | ||
1790 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1791 | STREG %r30,PT_GR21(%r1) | ||
1792 | |||
1793 | LDREG PT_GR30(%r1),%r25 | ||
1794 | copy %r1,%r24 | ||
1795 | BL sys_clone,%r2 | ||
1796 | ldi SIGCHLD,%r26 | ||
1797 | |||
1798 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1799 | wrapper_exit: | ||
1800 | ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ | ||
1801 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1802 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1803 | |||
1804 | LDREG PT_CR27(%r1), %r3 | ||
1805 | mtctl %r3, %cr27 | ||
1806 | reg_restore %r1 | ||
1807 | 1701 | ||
1808 | /* strace expects syscall # to be preserved in r20 */ | 1702 | fork_like clone |
1809 | ldi __NR_fork,%r20 | 1703 | fork_like fork |
1810 | bv %r0(%r2) | 1704 | fork_like vfork |
1811 | STREG %r20,PT_GR20(%r1) | ||
1812 | ENDPROC(sys_fork_wrapper) | ||
1813 | 1705 | ||
1814 | /* Set the return value for the child */ | 1706 | /* Set the return value for the child */ |
1815 | ENTRY(child_return) | 1707 | ENTRY(child_return) |
1816 | BL schedule_tail, %r2 | 1708 | BL schedule_tail, %r2 |
1817 | nop | 1709 | nop |
1710 | finish_child_return: | ||
1711 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | ||
1712 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1818 | 1713 | ||
1819 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 | 1714 | LDREG PT_CR27(%r1), %r3 |
1820 | LDREG TASK_PT_GR19(%r1),%r2 | 1715 | mtctl %r3, %cr27 |
1821 | b wrapper_exit | 1716 | reg_restore %r1 |
1717 | b syscall_exit | ||
1822 | copy %r0,%r28 | 1718 | copy %r0,%r28 |
1823 | ENDPROC(child_return) | 1719 | ENDPROC(child_return) |
1824 | 1720 | ||
1825 | |||
1826 | ENTRY(sys_clone_wrapper) | ||
1827 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1828 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1829 | reg_save %r1 | ||
1830 | mfctl %cr27, %r3 | ||
1831 | STREG %r3, PT_CR27(%r1) | ||
1832 | |||
1833 | STREG %r2,-RP_OFFSET(%r30) | ||
1834 | ldo FRAME_SIZE(%r30),%r30 | ||
1835 | #ifdef CONFIG_64BIT | ||
1836 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1837 | #endif | ||
1838 | |||
1839 | /* WARNING - Clobbers r19 and r21, userspace must save these! */ | ||
1840 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1841 | STREG %r30,PT_GR21(%r1) | ||
1842 | BL sys_clone,%r2 | ||
1843 | copy %r1,%r24 | ||
1844 | |||
1845 | b wrapper_exit | ||
1846 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1847 | ENDPROC(sys_clone_wrapper) | ||
1848 | |||
1849 | |||
1850 | ENTRY(sys_vfork_wrapper) | ||
1851 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1852 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1853 | reg_save %r1 | ||
1854 | mfctl %cr27, %r3 | ||
1855 | STREG %r3, PT_CR27(%r1) | ||
1856 | |||
1857 | STREG %r2,-RP_OFFSET(%r30) | ||
1858 | ldo FRAME_SIZE(%r30),%r30 | ||
1859 | #ifdef CONFIG_64BIT | ||
1860 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1861 | #endif | ||
1862 | |||
1863 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1864 | STREG %r30,PT_GR21(%r1) | ||
1865 | |||
1866 | BL sys_vfork,%r2 | ||
1867 | copy %r1,%r26 | ||
1868 | |||
1869 | b wrapper_exit | ||
1870 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1871 | ENDPROC(sys_vfork_wrapper) | ||
1872 | |||
1873 | |||
1874 | .macro execve_wrapper execve | ||
1875 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1876 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1877 | |||
1878 | /* | ||
1879 | * Do we need to save/restore r3-r18 here? | ||
1880 | * I don't think so. why would new thread need old | ||
1881 | * threads registers? | ||
1882 | */ | ||
1883 | |||
1884 | /* %arg0 - %arg3 are already saved for us. */ | ||
1885 | |||
1886 | STREG %r2,-RP_OFFSET(%r30) | ||
1887 | ldo FRAME_SIZE(%r30),%r30 | ||
1888 | #ifdef CONFIG_64BIT | ||
1889 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1890 | #endif | ||
1891 | BL \execve,%r2 | ||
1892 | copy %r1,%arg0 | ||
1893 | |||
1894 | ldo -FRAME_SIZE(%r30),%r30 | ||
1895 | LDREG -RP_OFFSET(%r30),%r2 | ||
1896 | |||
1897 | /* If exec succeeded we need to load the args */ | ||
1898 | |||
1899 | ldo -1024(%r0),%r1 | ||
1900 | cmpb,>>= %r28,%r1,error_\execve | ||
1901 | copy %r2,%r19 | ||
1902 | |||
1903 | error_\execve: | ||
1904 | bv %r0(%r19) | ||
1905 | nop | ||
1906 | .endm | ||
1907 | |||
1908 | .import sys_execve | ||
1909 | ENTRY(sys_execve_wrapper) | ||
1910 | execve_wrapper sys_execve | ||
1911 | ENDPROC(sys_execve_wrapper) | ||
1912 | |||
1913 | #ifdef CONFIG_64BIT | ||
1914 | .import sys32_execve | ||
1915 | ENTRY(sys32_execve_wrapper) | ||
1916 | execve_wrapper sys32_execve | ||
1917 | ENDPROC(sys32_execve_wrapper) | ||
1918 | #endif | ||
1919 | |||
1920 | ENTRY(sys_rt_sigreturn_wrapper) | 1721 | ENTRY(sys_rt_sigreturn_wrapper) |
1921 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 | 1722 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 |
1922 | ldo TASK_REGS(%r26),%r26 /* get pt regs */ | 1723 | ldo TASK_REGS(%r26),%r26 /* get pt regs */ |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index cbc37216bf90..d13507246c5d 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -52,6 +52,7 @@ | |||
52 | 52 | ||
53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
54 | #include <asm/asm-offsets.h> | 54 | #include <asm/asm-offsets.h> |
55 | #include <asm/assembly.h> | ||
55 | #include <asm/pdc.h> | 56 | #include <asm/pdc.h> |
56 | #include <asm/pdc_chassis.h> | 57 | #include <asm/pdc_chassis.h> |
57 | #include <asm/pgalloc.h> | 58 | #include <asm/pgalloc.h> |
@@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off; | |||
165 | EXPORT_SYMBOL(pm_power_off); | 166 | EXPORT_SYMBOL(pm_power_off); |
166 | 167 | ||
167 | /* | 168 | /* |
168 | * Create a kernel thread | ||
169 | */ | ||
170 | |||
171 | extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
172 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
173 | { | ||
174 | |||
175 | /* | ||
176 | * FIXME: Once we are sure we don't need any debug here, | ||
177 | * kernel_thread can become a #define. | ||
178 | */ | ||
179 | |||
180 | return __kernel_thread(fn, arg, flags); | ||
181 | } | ||
182 | EXPORT_SYMBOL(kernel_thread); | ||
183 | |||
184 | /* | ||
185 | * Free current thread data structures etc.. | 169 | * Free current thread data structures etc.. |
186 | */ | 170 | */ |
187 | void exit_thread(void) | 171 | void exit_thread(void) |
@@ -218,48 +202,11 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) | |||
218 | return 1; | 202 | return 1; |
219 | } | 203 | } |
220 | 204 | ||
221 | /* Note that "fork()" is implemented in terms of clone, with | ||
222 | parameters (SIGCHLD, regs->gr[30], regs). */ | ||
223 | int | ||
224 | sys_clone(unsigned long clone_flags, unsigned long usp, | ||
225 | struct pt_regs *regs) | ||
226 | { | ||
227 | /* Arugments from userspace are: | ||
228 | r26 = Clone flags. | ||
229 | r25 = Child stack. | ||
230 | r24 = parent_tidptr. | ||
231 | r23 = Is the TLS storage descriptor | ||
232 | r22 = child_tidptr | ||
233 | |||
234 | However, these last 3 args are only examined | ||
235 | if the proper flags are set. */ | ||
236 | int __user *parent_tidptr = (int __user *)regs->gr[24]; | ||
237 | int __user *child_tidptr = (int __user *)regs->gr[22]; | ||
238 | |||
239 | /* usp must be word aligned. This also prevents users from | ||
240 | * passing in the value 1 (which is the signal for a special | ||
241 | * return for a kernel thread) */ | ||
242 | usp = ALIGN(usp, 4); | ||
243 | |||
244 | /* A zero value for usp means use the current stack */ | ||
245 | if (usp == 0) | ||
246 | usp = regs->gr[30]; | ||
247 | |||
248 | return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr); | ||
249 | } | ||
250 | |||
251 | int | ||
252 | sys_vfork(struct pt_regs *regs) | ||
253 | { | ||
254 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL); | ||
255 | } | ||
256 | |||
257 | int | 205 | int |
258 | copy_thread(unsigned long clone_flags, unsigned long usp, | 206 | copy_thread(unsigned long clone_flags, unsigned long usp, |
259 | unsigned long unused, /* in ia64 this is "user_stack_size" */ | 207 | unsigned long arg, struct task_struct *p) |
260 | struct task_struct * p, struct pt_regs * pregs) | ||
261 | { | 208 | { |
262 | struct pt_regs * cregs = &(p->thread.regs); | 209 | struct pt_regs *cregs = &(p->thread.regs); |
263 | void *stack = task_stack_page(p); | 210 | void *stack = task_stack_page(p); |
264 | 211 | ||
265 | /* We have to use void * instead of a function pointer, because | 212 | /* We have to use void * instead of a function pointer, because |
@@ -270,48 +217,39 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
270 | #ifdef CONFIG_HPUX | 217 | #ifdef CONFIG_HPUX |
271 | extern void * const hpux_child_return; | 218 | extern void * const hpux_child_return; |
272 | #endif | 219 | #endif |
220 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
221 | memset(cregs, 0, sizeof(struct pt_regs)); | ||
222 | if (!usp) /* idle thread */ | ||
223 | return 0; | ||
273 | 224 | ||
274 | *cregs = *pregs; | ||
275 | |||
276 | /* Set the return value for the child. Note that this is not | ||
277 | actually restored by the syscall exit path, but we put it | ||
278 | here for consistency in case of signals. */ | ||
279 | cregs->gr[28] = 0; /* child */ | ||
280 | |||
281 | /* | ||
282 | * We need to differentiate between a user fork and a | ||
283 | * kernel fork. We can't use user_mode, because the | ||
284 | * the syscall path doesn't save iaoq. Right now | ||
285 | * We rely on the fact that kernel_thread passes | ||
286 | * in zero for usp. | ||
287 | */ | ||
288 | if (usp == 1) { | ||
289 | /* kernel thread */ | 225 | /* kernel thread */ |
290 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; | ||
291 | /* Must exit via ret_from_kernel_thread in order | 226 | /* Must exit via ret_from_kernel_thread in order |
292 | * to call schedule_tail() | 227 | * to call schedule_tail() |
293 | */ | 228 | */ |
229 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; | ||
294 | cregs->kpc = (unsigned long) &ret_from_kernel_thread; | 230 | cregs->kpc = (unsigned long) &ret_from_kernel_thread; |
295 | /* | 231 | /* |
296 | * Copy function and argument to be called from | 232 | * Copy function and argument to be called from |
297 | * ret_from_kernel_thread. | 233 | * ret_from_kernel_thread. |
298 | */ | 234 | */ |
299 | #ifdef CONFIG_64BIT | 235 | #ifdef CONFIG_64BIT |
300 | cregs->gr[27] = pregs->gr[27]; | 236 | cregs->gr[27] = ((unsigned long *)usp)[3]; |
237 | cregs->gr[26] = ((unsigned long *)usp)[2]; | ||
238 | #else | ||
239 | cregs->gr[26] = usp; | ||
301 | #endif | 240 | #endif |
302 | cregs->gr[26] = pregs->gr[26]; | 241 | cregs->gr[25] = arg; |
303 | cregs->gr[25] = pregs->gr[25]; | ||
304 | } else { | 242 | } else { |
305 | /* user thread */ | 243 | /* user thread */ |
306 | /* | 244 | /* usp must be word aligned. This also prevents users from |
307 | * Note that the fork wrappers are responsible | 245 | * passing in the value 1 (which is the signal for a special |
308 | * for setting gr[21]. | 246 | * return for a kernel thread) */ |
309 | */ | 247 | if (usp) { |
310 | 248 | usp = ALIGN(usp, 4); | |
311 | /* Use same stack depth as parent */ | 249 | if (likely(usp)) |
312 | cregs->ksp = (unsigned long)stack | 250 | cregs->gr[30] = usp; |
313 | + (pregs->gr[21] & (THREAD_SIZE - 1)); | 251 | } |
314 | cregs->gr[30] = usp; | 252 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; |
315 | if (personality(p->personality) == PER_HPUX) { | 253 | if (personality(p->personality) == PER_HPUX) { |
316 | #ifdef CONFIG_HPUX | 254 | #ifdef CONFIG_HPUX |
317 | cregs->kpc = (unsigned long) &hpux_child_return; | 255 | cregs->kpc = (unsigned long) &hpux_child_return; |
@@ -323,8 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
323 | } | 261 | } |
324 | /* Setup thread TLS area from the 4th parameter in clone */ | 262 | /* Setup thread TLS area from the 4th parameter in clone */ |
325 | if (clone_flags & CLONE_SETTLS) | 263 | if (clone_flags & CLONE_SETTLS) |
326 | cregs->cr27 = pregs->gr[23]; | 264 | cregs->cr27 = cregs->gr[23]; |
327 | |||
328 | } | 265 | } |
329 | 266 | ||
330 | return 0; | 267 | return 0; |
@@ -335,39 +272,6 @@ unsigned long thread_saved_pc(struct task_struct *t) | |||
335 | return t->thread.regs.kpc; | 272 | return t->thread.regs.kpc; |
336 | } | 273 | } |
337 | 274 | ||
338 | /* | ||
339 | * sys_execve() executes a new program. | ||
340 | */ | ||
341 | |||
342 | asmlinkage int sys_execve(struct pt_regs *regs) | ||
343 | { | ||
344 | int error; | ||
345 | struct filename *filename; | ||
346 | |||
347 | filename = getname((const char __user *) regs->gr[26]); | ||
348 | error = PTR_ERR(filename); | ||
349 | if (IS_ERR(filename)) | ||
350 | goto out; | ||
351 | error = do_execve(filename->name, | ||
352 | (const char __user *const __user *) regs->gr[25], | ||
353 | (const char __user *const __user *) regs->gr[24], | ||
354 | regs); | ||
355 | putname(filename); | ||
356 | out: | ||
357 | |||
358 | return error; | ||
359 | } | ||
360 | |||
361 | extern int __execve(const char *filename, | ||
362 | const char *const argv[], | ||
363 | const char *const envp[], struct task_struct *task); | ||
364 | int kernel_execve(const char *filename, | ||
365 | const char *const argv[], | ||
366 | const char *const envp[]) | ||
367 | { | ||
368 | return __execve(filename, argv, envp, current); | ||
369 | } | ||
370 | |||
371 | unsigned long | 275 | unsigned long |
372 | get_wchan(struct task_struct *p) | 276 | get_wchan(struct task_struct *p) |
373 | { | 277 | { |
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index bf5b93a885d3..9cfdaa19ab63 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -53,28 +53,6 @@ | |||
53 | #define DBG(x) | 53 | #define DBG(x) |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | /* | ||
57 | * sys32_execve() executes a new program. | ||
58 | */ | ||
59 | |||
60 | asmlinkage int sys32_execve(struct pt_regs *regs) | ||
61 | { | ||
62 | int error; | ||
63 | struct filename *filename; | ||
64 | |||
65 | DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); | ||
66 | filename = getname((const char __user *) regs->gr[26]); | ||
67 | error = PTR_ERR(filename); | ||
68 | if (IS_ERR(filename)) | ||
69 | goto out; | ||
70 | error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]), | ||
71 | compat_ptr(regs->gr[24]), regs); | ||
72 | putname(filename); | ||
73 | out: | ||
74 | |||
75 | return error; | ||
76 | } | ||
77 | |||
78 | asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, | 56 | asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, |
79 | int r22, int r21, int r20) | 57 | int r22, int r21, int r20) |
80 | { | 58 | { |
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index cbf5d59d5d6a..54d950b067b7 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -66,7 +66,7 @@ | |||
66 | ENTRY_SAME(creat) | 66 | ENTRY_SAME(creat) |
67 | ENTRY_SAME(link) | 67 | ENTRY_SAME(link) |
68 | ENTRY_SAME(unlink) /* 10 */ | 68 | ENTRY_SAME(unlink) /* 10 */ |
69 | ENTRY_DIFF(execve_wrapper) | 69 | ENTRY_COMP(execve) |
70 | ENTRY_SAME(chdir) | 70 | ENTRY_SAME(chdir) |
71 | /* See comments in kernel/time.c!!! Maybe we don't need this? */ | 71 | /* See comments in kernel/time.c!!! Maybe we don't need this? */ |
72 | ENTRY_COMP(time) | 72 | ENTRY_COMP(time) |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a902a5c1c76a..951a517a1a0f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -144,6 +144,8 @@ config PPC | |||
144 | select GENERIC_KERNEL_THREAD | 144 | select GENERIC_KERNEL_THREAD |
145 | select HAVE_MOD_ARCH_SPECIFIC | 145 | select HAVE_MOD_ARCH_SPECIFIC |
146 | select MODULES_USE_ELF_RELA | 146 | select MODULES_USE_ELF_RELA |
147 | select GENERIC_KERNEL_EXECVE | ||
148 | select CLONE_BACKWARDS | ||
147 | 149 | ||
148 | config EARLY_PRINTK | 150 | config EARLY_PRINTK |
149 | bool | 151 | bool |
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h index 189998bb61c4..a101637725a2 100644 --- a/arch/powerpc/include/asm/signal.h +++ b/arch/powerpc/include/asm/signal.h | |||
@@ -3,6 +3,4 @@ | |||
3 | 3 | ||
4 | #include <uapi/asm/signal.h> | 4 | #include <uapi/asm/signal.h> |
5 | 5 | ||
6 | struct pt_regs; | ||
7 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
8 | #endif /* _ASM_POWERPC_SIGNAL_H */ | 6 | #endif /* _ASM_POWERPC_SIGNAL_H */ |
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h index 329db4ec12ca..b5308d3e6d39 100644 --- a/arch/powerpc/include/asm/syscalls.h +++ b/arch/powerpc/include/asm/syscalls.h | |||
@@ -17,15 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, | |||
17 | asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, | 17 | asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, |
18 | unsigned long prot, unsigned long flags, | 18 | unsigned long prot, unsigned long flags, |
19 | unsigned long fd, unsigned long pgoff); | 19 | unsigned long fd, unsigned long pgoff); |
20 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp, | ||
21 | int __user *parent_tidp, void __user *child_threadptr, | ||
22 | int __user *child_tidp, int p6, struct pt_regs *regs); | ||
23 | asmlinkage int sys_fork(unsigned long p1, unsigned long p2, | ||
24 | unsigned long p3, unsigned long p4, unsigned long p5, | ||
25 | unsigned long p6, struct pt_regs *regs); | ||
26 | asmlinkage int sys_vfork(unsigned long p1, unsigned long p2, | ||
27 | unsigned long p3, unsigned long p4, unsigned long p5, | ||
28 | unsigned long p6, struct pt_regs *regs); | ||
29 | asmlinkage long sys_pipe(int __user *fildes); | 20 | asmlinkage long sys_pipe(int __user *fildes); |
30 | asmlinkage long sys_pipe2(int __user *fildes, int flags); | 21 | asmlinkage long sys_pipe2(int __user *fildes, int flags); |
31 | asmlinkage long sys_rt_sigaction(int sig, | 22 | asmlinkage long sys_rt_sigaction(int sig, |
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 921dce6d8445..76fe846ec40e 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -56,7 +56,9 @@ | |||
56 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE | 56 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE |
57 | #endif | 57 | #endif |
58 | #define __ARCH_WANT_SYS_EXECVE | 58 | #define __ARCH_WANT_SYS_EXECVE |
59 | #define __ARCH_WANT_KERNEL_EXECVE | 59 | #define __ARCH_WANT_SYS_FORK |
60 | #define __ARCH_WANT_SYS_VFORK | ||
61 | #define __ARCH_WANT_SYS_CLONE | ||
60 | 62 | ||
61 | /* | 63 | /* |
62 | * "Conditional" syscalls | 64 | * "Conditional" syscalls |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 9499385676e7..d22e73e4618b 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -444,11 +444,6 @@ ret_from_kernel_thread: | |||
444 | PPC440EP_ERR42 | 444 | PPC440EP_ERR42 |
445 | blrl | 445 | blrl |
446 | li r3,0 | 446 | li r3,0 |
447 | b do_exit # no return | ||
448 | |||
449 | .globl __ret_from_kernel_execve | ||
450 | __ret_from_kernel_execve: | ||
451 | addi r1,r3,-STACK_FRAME_OVERHEAD | ||
452 | b ret_from_syscall | 447 | b ret_from_syscall |
453 | 448 | ||
454 | /* Traced system call support */ | 449 | /* Traced system call support */ |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 56e0ff0878b5..e9a906c27234 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -373,17 +373,11 @@ _GLOBAL(ret_from_fork) | |||
373 | _GLOBAL(ret_from_kernel_thread) | 373 | _GLOBAL(ret_from_kernel_thread) |
374 | bl .schedule_tail | 374 | bl .schedule_tail |
375 | REST_NVGPRS(r1) | 375 | REST_NVGPRS(r1) |
376 | REST_GPR(2,r1) | 376 | ld r14, 0(r14) |
377 | mtlr r14 | 377 | mtlr r14 |
378 | mr r3,r15 | 378 | mr r3,r15 |
379 | blrl | 379 | blrl |
380 | li r3,0 | 380 | li r3,0 |
381 | b .do_exit # no return | ||
382 | |||
383 | _GLOBAL(__ret_from_kernel_execve) | ||
384 | addi r1,r3,-STACK_FRAME_OVERHEAD | ||
385 | li r10,1 | ||
386 | std r10,SOFTE(r1) | ||
387 | b syscall_exit | 381 | b syscall_exit |
388 | 382 | ||
389 | .section ".toc","aw" | 383 | .section ".toc","aw" |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ba48233500f6..81430674e71c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -733,8 +733,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
733 | extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ | 733 | extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ |
734 | 734 | ||
735 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 735 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
736 | unsigned long arg, struct task_struct *p, | 736 | unsigned long arg, struct task_struct *p) |
737 | struct pt_regs *regs) | ||
738 | { | 737 | { |
739 | struct pt_regs *childregs, *kregs; | 738 | struct pt_regs *childregs, *kregs; |
740 | extern void ret_from_fork(void); | 739 | extern void ret_from_fork(void); |
@@ -745,25 +744,25 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
745 | /* Copy registers */ | 744 | /* Copy registers */ |
746 | sp -= sizeof(struct pt_regs); | 745 | sp -= sizeof(struct pt_regs); |
747 | childregs = (struct pt_regs *) sp; | 746 | childregs = (struct pt_regs *) sp; |
748 | if (!regs) { | 747 | if (unlikely(p->flags & PF_KTHREAD)) { |
749 | /* for kernel thread, set `current' and stackptr in new task */ | 748 | struct thread_info *ti = (void *)task_stack_page(p); |
750 | memset(childregs, 0, sizeof(struct pt_regs)); | 749 | memset(childregs, 0, sizeof(struct pt_regs)); |
751 | childregs->gpr[1] = sp + sizeof(struct pt_regs); | 750 | childregs->gpr[1] = sp + sizeof(struct pt_regs); |
751 | childregs->gpr[14] = usp; /* function */ | ||
752 | #ifdef CONFIG_PPC64 | 752 | #ifdef CONFIG_PPC64 |
753 | childregs->gpr[14] = *(unsigned long *)usp; | ||
754 | childregs->gpr[2] = ((unsigned long *)usp)[1], | ||
755 | clear_tsk_thread_flag(p, TIF_32BIT); | 753 | clear_tsk_thread_flag(p, TIF_32BIT); |
756 | #else | 754 | childregs->softe = 1; |
757 | childregs->gpr[14] = usp; /* function */ | ||
758 | childregs->gpr[2] = (unsigned long) p; | ||
759 | #endif | 755 | #endif |
760 | childregs->gpr[15] = arg; | 756 | childregs->gpr[15] = arg; |
761 | p->thread.regs = NULL; /* no user register state */ | 757 | p->thread.regs = NULL; /* no user register state */ |
758 | ti->flags |= _TIF_RESTOREALL; | ||
762 | f = ret_from_kernel_thread; | 759 | f = ret_from_kernel_thread; |
763 | } else { | 760 | } else { |
761 | struct pt_regs *regs = current_pt_regs(); | ||
764 | CHECK_FULL_REGS(regs); | 762 | CHECK_FULL_REGS(regs); |
765 | *childregs = *regs; | 763 | *childregs = *regs; |
766 | childregs->gpr[1] = usp; | 764 | if (usp) |
765 | childregs->gpr[1] = usp; | ||
767 | p->thread.regs = childregs; | 766 | p->thread.regs = childregs; |
768 | childregs->gpr[3] = 0; /* Result from fork() */ | 767 | childregs->gpr[3] = 0; /* Result from fork() */ |
769 | if (clone_flags & CLONE_SETTLS) { | 768 | if (clone_flags & CLONE_SETTLS) { |
@@ -1027,51 +1026,6 @@ int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) | |||
1027 | return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); | 1026 | return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); |
1028 | } | 1027 | } |
1029 | 1028 | ||
1030 | #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) | ||
1031 | |||
1032 | int sys_clone(unsigned long clone_flags, unsigned long usp, | ||
1033 | int __user *parent_tidp, void __user *child_threadptr, | ||
1034 | int __user *child_tidp, int p6, | ||
1035 | struct pt_regs *regs) | ||
1036 | { | ||
1037 | CHECK_FULL_REGS(regs); | ||
1038 | if (usp == 0) | ||
1039 | usp = regs->gpr[1]; /* stack pointer for child */ | ||
1040 | #ifdef CONFIG_PPC64 | ||
1041 | if (is_32bit_task()) { | ||
1042 | parent_tidp = TRUNC_PTR(parent_tidp); | ||
1043 | child_tidp = TRUNC_PTR(child_tidp); | ||
1044 | } | ||
1045 | #endif | ||
1046 | return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); | ||
1047 | } | ||
1048 | |||
1049 | int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, | ||
1050 | unsigned long p4, unsigned long p5, unsigned long p6, | ||
1051 | struct pt_regs *regs) | ||
1052 | { | ||
1053 | CHECK_FULL_REGS(regs); | ||
1054 | return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); | ||
1055 | } | ||
1056 | |||
1057 | int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, | ||
1058 | unsigned long p4, unsigned long p5, unsigned long p6, | ||
1059 | struct pt_regs *regs) | ||
1060 | { | ||
1061 | CHECK_FULL_REGS(regs); | ||
1062 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], | ||
1063 | regs, 0, NULL, NULL); | ||
1064 | } | ||
1065 | |||
1066 | void __ret_from_kernel_execve(struct pt_regs *normal) | ||
1067 | __noreturn; | ||
1068 | |||
1069 | void ret_from_kernel_execve(struct pt_regs *normal) | ||
1070 | { | ||
1071 | set_thread_flag(TIF_RESTOREALL); | ||
1072 | __ret_from_kernel_execve(normal); | ||
1073 | } | ||
1074 | |||
1075 | static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, | 1029 | static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, |
1076 | unsigned long nbytes) | 1030 | unsigned long nbytes) |
1077 | { | 1031 | { |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index d385f396dfee..3cbb8757704e 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -138,8 +138,10 @@ config S390 | |||
138 | select KTIME_SCALAR if 32BIT | 138 | select KTIME_SCALAR if 32BIT |
139 | select HAVE_ARCH_SECCOMP_FILTER | 139 | select HAVE_ARCH_SECCOMP_FILTER |
140 | select GENERIC_KERNEL_THREAD | 140 | select GENERIC_KERNEL_THREAD |
141 | select GENERIC_KERNEL_EXECVE | ||
141 | select HAVE_MOD_ARCH_SPECIFIC | 142 | select HAVE_MOD_ARCH_SPECIFIC |
142 | select MODULES_USE_ELF_RELA | 143 | select MODULES_USE_ELF_RELA |
144 | select CLONE_BACKWARDS2 | ||
143 | 145 | ||
144 | config SCHED_OMIT_FRAME_POINTER | 146 | config SCHED_OMIT_FRAME_POINTER |
145 | def_bool y | 147 | def_bool y |
diff --git a/arch/s390/include/asm/signal.h b/arch/s390/include/asm/signal.h index bffdbdd5b3d7..db7ddfaf5b79 100644 --- a/arch/s390/include/asm/signal.h +++ b/arch/s390/include/asm/signal.h | |||
@@ -39,6 +39,4 @@ struct k_sigaction { | |||
39 | struct sigaction sa; | 39 | struct sigaction sa; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
43 | |||
44 | #endif | 42 | #endif |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index bbbae41fa9a5..086bb8eaf6ab 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
@@ -54,7 +54,9 @@ | |||
54 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 54 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
55 | # endif | 55 | # endif |
56 | #define __ARCH_WANT_SYS_EXECVE | 56 | #define __ARCH_WANT_SYS_EXECVE |
57 | #define __ARCH_WANT_KERNEL_EXECVE | 57 | #define __ARCH_WANT_SYS_FORK |
58 | #define __ARCH_WANT_SYS_VFORK | ||
59 | #define __ARCH_WANT_SYS_CLONE | ||
58 | 60 | ||
59 | /* | 61 | /* |
60 | * "Conditional" syscalls | 62 | * "Conditional" syscalls |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ef46f66bc0d6..aa8f2ba6289b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -330,40 +330,18 @@ ENTRY(ret_from_fork) | |||
330 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 330 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
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 ? | ||
334 | je 1f | ||
335 | l %r1,BASED(.Lschedule_tail) | 333 | l %r1,BASED(.Lschedule_tail) |
336 | basr %r14,%r1 # call schedule_tail | 334 | basr %r14,%r1 # call schedule_tail |
337 | TRACE_IRQS_ON | 335 | TRACE_IRQS_ON |
338 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 336 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
339 | j sysc_tracenogo | 337 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
340 | 338 | jne sysc_tracenogo | |
341 | 1: # it's a kernel thread | 339 | # it's a kernel thread |
342 | st %r15,__PT_R15(%r11) # store stack pointer for new kthread | 340 | lm %r9,%r10,__PT_R9(%r11) # load gprs |
343 | l %r1,BASED(.Lschedule_tail) | ||
344 | basr %r14,%r1 # call schedule_tail | ||
345 | TRACE_IRQS_ON | ||
346 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
347 | lm %r9,%r11,__PT_R9(%r11) # load gprs | ||
348 | ENTRY(kernel_thread_starter) | 341 | ENTRY(kernel_thread_starter) |
349 | la %r2,0(%r10) | 342 | la %r2,0(%r10) |
350 | basr %r14,%r9 | 343 | basr %r14,%r9 |
351 | la %r2,0 | 344 | j sysc_tracenogo |
352 | br %r11 # do_exit | ||
353 | |||
354 | # | ||
355 | # kernel_execve function needs to deal with pt_regs that is not | ||
356 | # at the usual place | ||
357 | # | ||
358 | ENTRY(ret_from_kernel_execve) | ||
359 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
360 | lr %r15,%r2 | ||
361 | lr %r11,%r2 | ||
362 | ahi %r15,-STACK_FRAME_OVERHEAD | ||
363 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | ||
364 | l %r12,__LC_THREAD_INFO | ||
365 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
366 | j sysc_return | ||
367 | 345 | ||
368 | /* | 346 | /* |
369 | * Program check handler routine | 347 | * Program check handler routine |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index d0d3f69a7346..d8251b98f17a 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
@@ -54,10 +54,6 @@ long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low, | |||
54 | long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); | 54 | long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); |
55 | long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, | 55 | long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, |
56 | u32 len_low); | 56 | u32 len_low); |
57 | long sys_fork(void); | ||
58 | long sys_clone(unsigned long newsp, unsigned long clone_flags, | ||
59 | int __user *parent_tidptr, int __user *child_tidptr); | ||
60 | long sys_vfork(void); | ||
61 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); | 57 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); |
62 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 58 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
63 | struct old_sigaction __user *oact); | 59 | struct old_sigaction __user *oact); |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 07d8de353984..499e95e90f38 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -352,33 +352,17 @@ sysc_tracenogo: | |||
352 | ENTRY(ret_from_fork) | 352 | 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 ? | ||
356 | je 1f | ||
357 | brasl %r14,schedule_tail | 355 | brasl %r14,schedule_tail |
358 | TRACE_IRQS_ON | 356 | TRACE_IRQS_ON |
359 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 357 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
360 | j sysc_tracenogo | 358 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
361 | 1: # it's a kernel thread | 359 | jne sysc_tracenogo |
362 | stg %r15,__PT_R15(%r11) # store stack pointer for new kthread | 360 | # it's a kernel thread |
363 | brasl %r14,schedule_tail | 361 | lmg %r9,%r10,__PT_R9(%r11) # load gprs |
364 | TRACE_IRQS_ON | ||
365 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
366 | lmg %r9,%r11,__PT_R9(%r11) # load gprs | ||
367 | ENTRY(kernel_thread_starter) | 362 | ENTRY(kernel_thread_starter) |
368 | la %r2,0(%r10) | 363 | la %r2,0(%r10) |
369 | basr %r14,%r9 | 364 | basr %r14,%r9 |
370 | la %r2,0 | 365 | j sysc_tracenogo |
371 | br %r11 # do_exit | ||
372 | |||
373 | ENTRY(ret_from_kernel_execve) | ||
374 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
375 | lgr %r15,%r2 | ||
376 | lgr %r11,%r2 | ||
377 | aghi %r15,-STACK_FRAME_OVERHEAD | ||
378 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | ||
379 | lg %r12,__LC_THREAD_INFO | ||
380 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
381 | j sysc_return | ||
382 | 366 | ||
383 | /* | 367 | /* |
384 | * Program check handler routine | 368 | * Program check handler routine |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index cd31ad457a9b..536d64579d9a 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -117,8 +117,7 @@ void release_thread(struct task_struct *dead_task) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | 119 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, |
120 | unsigned long arg, | 120 | unsigned long arg, struct task_struct *p) |
121 | struct task_struct *p, struct pt_regs *regs) | ||
122 | { | 121 | { |
123 | struct thread_info *ti; | 122 | struct thread_info *ti; |
124 | struct fake_frame | 123 | struct fake_frame |
@@ -150,7 +149,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
150 | frame->sf.gprs[9] = (unsigned long) frame; | 149 | frame->sf.gprs[9] = (unsigned long) frame; |
151 | 150 | ||
152 | /* Store access registers to kernel stack of new process. */ | 151 | /* Store access registers to kernel stack of new process. */ |
153 | if (unlikely(!regs)) { | 152 | if (unlikely(p->flags & PF_KTHREAD)) { |
154 | /* kernel thread */ | 153 | /* kernel thread */ |
155 | memset(&frame->childregs, 0, sizeof(struct pt_regs)); | 154 | memset(&frame->childregs, 0, sizeof(struct pt_regs)); |
156 | frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | | 155 | frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | |
@@ -164,9 +163,10 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
164 | 163 | ||
165 | return 0; | 164 | return 0; |
166 | } | 165 | } |
167 | frame->childregs = *regs; | 166 | frame->childregs = *current_pt_regs(); |
168 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | 167 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ |
169 | frame->childregs.gprs[15] = new_stackp; | 168 | if (new_stackp) |
169 | frame->childregs.gprs[15] = new_stackp; | ||
170 | 170 | ||
171 | /* Don't copy runtime instrumentation info */ | 171 | /* Don't copy runtime instrumentation info */ |
172 | p->thread.ri_cb = NULL; | 172 | p->thread.ri_cb = NULL; |
@@ -183,57 +183,24 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
183 | sizeof(s390_fp_regs)); | 183 | sizeof(s390_fp_regs)); |
184 | /* Set a new TLS ? */ | 184 | /* Set a new TLS ? */ |
185 | if (clone_flags & CLONE_SETTLS) | 185 | if (clone_flags & CLONE_SETTLS) |
186 | p->thread.acrs[0] = regs->gprs[6]; | 186 | p->thread.acrs[0] = frame->childregs.gprs[6]; |
187 | #else /* CONFIG_64BIT */ | 187 | #else /* CONFIG_64BIT */ |
188 | /* Save the fpu registers to new thread structure. */ | 188 | /* Save the fpu registers to new thread structure. */ |
189 | save_fp_regs(&p->thread.fp_regs); | 189 | save_fp_regs(&p->thread.fp_regs); |
190 | /* Set a new TLS ? */ | 190 | /* Set a new TLS ? */ |
191 | if (clone_flags & CLONE_SETTLS) { | 191 | if (clone_flags & CLONE_SETTLS) { |
192 | unsigned long tls = frame->childregs.gprs[6]; | ||
192 | if (is_compat_task()) { | 193 | if (is_compat_task()) { |
193 | p->thread.acrs[0] = (unsigned int) regs->gprs[6]; | 194 | p->thread.acrs[0] = (unsigned int)tls; |
194 | } else { | 195 | } else { |
195 | p->thread.acrs[0] = (unsigned int)(regs->gprs[6] >> 32); | 196 | p->thread.acrs[0] = (unsigned int)(tls >> 32); |
196 | p->thread.acrs[1] = (unsigned int) regs->gprs[6]; | 197 | p->thread.acrs[1] = (unsigned int)tls; |
197 | } | 198 | } |
198 | } | 199 | } |
199 | #endif /* CONFIG_64BIT */ | 200 | #endif /* CONFIG_64BIT */ |
200 | return 0; | 201 | return 0; |
201 | } | 202 | } |
202 | 203 | ||
203 | SYSCALL_DEFINE0(fork) | ||
204 | { | ||
205 | struct pt_regs *regs = task_pt_regs(current); | ||
206 | return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); | ||
207 | } | ||
208 | |||
209 | SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, | ||
210 | int __user *, parent_tidptr, int __user *, child_tidptr) | ||
211 | { | ||
212 | struct pt_regs *regs = task_pt_regs(current); | ||
213 | |||
214 | if (!newsp) | ||
215 | newsp = regs->gprs[15]; | ||
216 | return do_fork(clone_flags, newsp, regs, 0, | ||
217 | parent_tidptr, child_tidptr); | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * This is trivial, and on the face of it looks like it | ||
222 | * could equally well be done in user mode. | ||
223 | * | ||
224 | * Not so, for quite unobvious reasons - register pressure. | ||
225 | * In user mode vfork() cannot have a stack frame, and if | ||
226 | * done by calling the "clone()" system call directly, you | ||
227 | * do not have enough call-clobbered registers to hold all | ||
228 | * the information you need. | ||
229 | */ | ||
230 | SYSCALL_DEFINE0(vfork) | ||
231 | { | ||
232 | struct pt_regs *regs = task_pt_regs(current); | ||
233 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
234 | regs->gprs[15], regs, 0, NULL, NULL); | ||
235 | } | ||
236 | |||
237 | asmlinkage void execve_tail(void) | 204 | asmlinkage void execve_tail(void) |
238 | { | 205 | { |
239 | current->thread.fp_regs.fpc = 0; | 206 | current->thread.fp_regs.fpc = 0; |
diff --git a/arch/score/Kconfig b/arch/score/Kconfig index 4f93a431a45a..45893390c7dd 100644 --- a/arch/score/Kconfig +++ b/arch/score/Kconfig | |||
@@ -13,6 +13,9 @@ config SCORE | |||
13 | select GENERIC_CLOCKEVENTS | 13 | select GENERIC_CLOCKEVENTS |
14 | select HAVE_MOD_ARCH_SPECIFIC | 14 | select HAVE_MOD_ARCH_SPECIFIC |
15 | select MODULES_USE_ELF_REL | 15 | select MODULES_USE_ELF_REL |
16 | select GENERIC_KERNEL_THREAD | ||
17 | select GENERIC_KERNEL_EXECVE | ||
18 | select CLONE_BACKWARDS | ||
16 | 19 | ||
17 | choice | 20 | choice |
18 | prompt "System type" | 21 | prompt "System type" |
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h index ab3aceb54209..d9a922d8711b 100644 --- a/arch/score/include/asm/processor.h +++ b/arch/score/include/asm/processor.h | |||
@@ -13,7 +13,6 @@ struct task_struct; | |||
13 | */ | 13 | */ |
14 | extern void (*cpu_wait)(void); | 14 | extern void (*cpu_wait)(void); |
15 | 15 | ||
16 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
17 | extern unsigned long thread_saved_pc(struct task_struct *tsk); | 16 | extern unsigned long thread_saved_pc(struct task_struct *tsk); |
18 | extern void start_thread(struct pt_regs *regs, | 17 | extern void start_thread(struct pt_regs *regs, |
19 | unsigned long pc, unsigned long sp); | 18 | unsigned long pc, unsigned long sp); |
diff --git a/arch/score/include/asm/syscalls.h b/arch/score/include/asm/syscalls.h index 1dd5e0d6b0c3..acaeed680956 100644 --- a/arch/score/include/asm/syscalls.h +++ b/arch/score/include/asm/syscalls.h | |||
@@ -1,8 +1,6 @@ | |||
1 | #ifndef _ASM_SCORE_SYSCALLS_H | 1 | #ifndef _ASM_SCORE_SYSCALLS_H |
2 | #define _ASM_SCORE_SYSCALLS_H | 2 | #define _ASM_SCORE_SYSCALLS_H |
3 | 3 | ||
4 | asmlinkage long score_clone(struct pt_regs *regs); | ||
5 | asmlinkage long score_execve(struct pt_regs *regs); | ||
6 | asmlinkage long score_sigaltstack(struct pt_regs *regs); | 4 | asmlinkage long score_sigaltstack(struct pt_regs *regs); |
7 | asmlinkage long score_rt_sigreturn(struct pt_regs *regs); | 5 | asmlinkage long score_rt_sigreturn(struct pt_regs *regs); |
8 | 6 | ||
diff --git a/arch/score/include/asm/unistd.h b/arch/score/include/asm/unistd.h index a862384e9c16..56001c93095a 100644 --- a/arch/score/include/asm/unistd.h +++ b/arch/score/include/asm/unistd.h | |||
@@ -4,5 +4,9 @@ | |||
4 | #define __ARCH_WANT_SYSCALL_NO_FLAGS | 4 | #define __ARCH_WANT_SYSCALL_NO_FLAGS |
5 | #define __ARCH_WANT_SYSCALL_OFF_T | 5 | #define __ARCH_WANT_SYSCALL_OFF_T |
6 | #define __ARCH_WANT_SYSCALL_DEPRECATED | 6 | #define __ARCH_WANT_SYSCALL_DEPRECATED |
7 | #define __ARCH_WANT_SYS_EXECVE | ||
8 | #define __ARCH_WANT_SYS_CLONE | ||
9 | #define __ARCH_WANT_SYS_FORK | ||
10 | #define __ARCH_WANT_SYS_VFORK | ||
7 | 11 | ||
8 | #include <asm-generic/unistd.h> | 12 | #include <asm-generic/unistd.h> |
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S index 83bb96079c43..1557ca1a2951 100644 --- a/arch/score/kernel/entry.S +++ b/arch/score/kernel/entry.S | |||
@@ -278,6 +278,13 @@ need_resched: | |||
278 | nop | 278 | nop |
279 | #endif | 279 | #endif |
280 | 280 | ||
281 | ENTRY(ret_from_kernel_thread) | ||
282 | bl schedule_tail # r4=struct task_struct *prev | ||
283 | nop | ||
284 | mv r4, r13 | ||
285 | brl r12 | ||
286 | j syscall_exit | ||
287 | |||
281 | ENTRY(ret_from_fork) | 288 | ENTRY(ret_from_fork) |
282 | bl schedule_tail # r4=struct task_struct *prev | 289 | bl schedule_tail # r4=struct task_struct *prev |
283 | 290 | ||
@@ -480,16 +487,6 @@ illegal_syscall: | |||
480 | sw r9, [r0, PT_R7] | 487 | sw r9, [r0, PT_R7] |
481 | j syscall_return | 488 | j syscall_return |
482 | 489 | ||
483 | ENTRY(sys_execve) | ||
484 | mv r4, r0 | ||
485 | la r8, score_execve | ||
486 | br r8 | ||
487 | |||
488 | ENTRY(sys_clone) | ||
489 | mv r4, r0 | ||
490 | la r8, score_clone | ||
491 | br r8 | ||
492 | |||
493 | ENTRY(sys_rt_sigreturn) | 490 | ENTRY(sys_rt_sigreturn) |
494 | mv r4, r0 | 491 | mv r4, r0 |
495 | la r8, score_rt_sigreturn | 492 | la r8, score_rt_sigreturn |
@@ -499,16 +496,3 @@ ENTRY(sys_sigaltstack) | |||
499 | mv r4, r0 | 496 | mv r4, r0 |
500 | la r8, score_sigaltstack | 497 | la r8, score_sigaltstack |
501 | br r8 | 498 | br r8 |
502 | |||
503 | #ifdef __ARCH_WANT_SYSCALL_DEPRECATED | ||
504 | ENTRY(sys_fork) | ||
505 | mv r4, r0 | ||
506 | la r8, score_fork | ||
507 | br r8 | ||
508 | |||
509 | ENTRY(sys_vfork) | ||
510 | mv r4, r0 | ||
511 | la r8, score_vfork | ||
512 | br r8 | ||
513 | #endif /* __ARCH_WANT_SYSCALL_DEPRECATED */ | ||
514 | |||
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 637970cfd3f4..79568466b578 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c | |||
@@ -60,6 +60,7 @@ void __noreturn cpu_idle(void) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | void ret_from_fork(void); | 62 | void ret_from_fork(void); |
63 | void ret_from_kernel_thread(void); | ||
63 | 64 | ||
64 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) | 65 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) |
65 | { | 66 | { |
@@ -86,29 +87,27 @@ void flush_thread(void) {} | |||
86 | * set up the kernel stack and exception frames for a new process | 87 | * set up the kernel stack and exception frames for a new process |
87 | */ | 88 | */ |
88 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 89 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
89 | unsigned long unused, | 90 | unsigned long arg, struct task_struct *p) |
90 | struct task_struct *p, struct pt_regs *regs) | ||
91 | { | 91 | { |
92 | struct thread_info *ti = task_thread_info(p); | 92 | struct thread_info *ti = task_thread_info(p); |
93 | struct pt_regs *childregs = task_pt_regs(p); | 93 | struct pt_regs *childregs = task_pt_regs(p); |
94 | struct pt_regs *regs = current_pt_regs(); | ||
94 | 95 | ||
95 | p->set_child_tid = NULL; | 96 | p->thread.reg0 = (unsigned long) childregs; |
96 | p->clear_child_tid = NULL; | 97 | if (unlikely(p->flags & PF_KTHREAD)) { |
97 | 98 | memset(childregs, 0, sizeof(struct pt_regs)); | |
98 | *childregs = *regs; | 99 | p->thread->reg12 = usp; |
99 | childregs->regs[7] = 0; /* Clear error flag */ | 100 | p->thread->reg13 = arg; |
100 | childregs->regs[4] = 0; /* Child gets zero as return value */ | 101 | p->thread.reg3 = (unsigned long) ret_from_kernel_thread; |
101 | regs->regs[4] = p->pid; | ||
102 | |||
103 | if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */ | ||
104 | childregs->regs[0] = usp; /* user fork */ | ||
105 | } else { | 102 | } else { |
106 | childregs->regs[28] = (unsigned long) ti; /* kernel fork */ | 103 | *childregs = *current_pt_regs(); |
107 | childregs->regs[0] = (unsigned long) childregs; | 104 | childregs->regs[7] = 0; /* Clear error flag */ |
105 | childregs->regs[4] = 0; /* Child gets zero as return value */ | ||
106 | if (usp) | ||
107 | childregs->regs[0] = usp; /* user fork */ | ||
108 | p->thread.reg3 = (unsigned long) ret_from_fork; | ||
108 | } | 109 | } |
109 | 110 | ||
110 | p->thread.reg0 = (unsigned long) childregs; | ||
111 | p->thread.reg3 = (unsigned long) ret_from_fork; | ||
112 | p->thread.cp0_psr = 0; | 111 | p->thread.cp0_psr = 0; |
113 | 112 | ||
114 | return 0; | 113 | return 0; |
@@ -120,32 +119,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) | |||
120 | return 1; | 119 | return 1; |
121 | } | 120 | } |
122 | 121 | ||
123 | static void __noreturn | ||
124 | kernel_thread_helper(void *unused0, int (*fn)(void *), | ||
125 | void *arg, void *unused1) | ||
126 | { | ||
127 | do_exit(fn(arg)); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * Create a kernel thread. | ||
132 | */ | ||
133 | long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
134 | { | ||
135 | struct pt_regs regs; | ||
136 | |||
137 | memset(®s, 0, sizeof(regs)); | ||
138 | |||
139 | regs.regs[6] = (unsigned long) arg; | ||
140 | regs.regs[5] = (unsigned long) fn; | ||
141 | regs.cp0_epc = (unsigned long) kernel_thread_helper; | ||
142 | regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \ | ||
143 | ((regs.cp0_psr & 0x3) << 2); | ||
144 | |||
145 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \ | ||
146 | 0, ®s, 0, NULL, NULL); | ||
147 | } | ||
148 | |||
149 | unsigned long thread_saved_pc(struct task_struct *tsk) | 122 | unsigned long thread_saved_pc(struct task_struct *tsk) |
150 | { | 123 | { |
151 | return task_pt_regs(tsk)->cp0_epc; | 124 | return task_pt_regs(tsk)->cp0_epc; |
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c index d45cf00a3351..47c20ba46167 100644 --- a/arch/score/kernel/sys_score.c +++ b/arch/score/kernel/sys_score.c | |||
@@ -48,92 +48,3 @@ sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, | |||
48 | return -EINVAL; | 48 | return -EINVAL; |
49 | return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | 49 | return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); |
50 | } | 50 | } |
51 | |||
52 | asmlinkage long | ||
53 | score_fork(struct pt_regs *regs) | ||
54 | { | ||
55 | return do_fork(SIGCHLD, regs->regs[0], regs, 0, NULL, NULL); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Clone a task - this clones the calling program thread. | ||
60 | * This is called indirectly via a small wrapper | ||
61 | */ | ||
62 | asmlinkage long | ||
63 | score_clone(struct pt_regs *regs) | ||
64 | { | ||
65 | unsigned long clone_flags; | ||
66 | unsigned long newsp; | ||
67 | int __user *parent_tidptr, *child_tidptr; | ||
68 | |||
69 | clone_flags = regs->regs[4]; | ||
70 | newsp = regs->regs[5]; | ||
71 | if (!newsp) | ||
72 | newsp = regs->regs[0]; | ||
73 | parent_tidptr = (int __user *)regs->regs[6]; | ||
74 | child_tidptr = (int __user *)regs->regs[8]; | ||
75 | |||
76 | return do_fork(clone_flags, newsp, regs, 0, | ||
77 | parent_tidptr, child_tidptr); | ||
78 | } | ||
79 | |||
80 | asmlinkage long | ||
81 | score_vfork(struct pt_regs *regs) | ||
82 | { | ||
83 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
84 | regs->regs[0], regs, 0, NULL, NULL); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * sys_execve() executes a new program. | ||
89 | * This is called indirectly via a small wrapper | ||
90 | */ | ||
91 | asmlinkage long | ||
92 | score_execve(struct pt_regs *regs) | ||
93 | { | ||
94 | int error; | ||
95 | struct filename *filename; | ||
96 | |||
97 | filename = getname((char __user*)regs->regs[4]); | ||
98 | error = PTR_ERR(filename); | ||
99 | if (IS_ERR(filename)) | ||
100 | return error; | ||
101 | |||
102 | error = do_execve(filename->name, | ||
103 | (const char __user *const __user *)regs->regs[5], | ||
104 | (const char __user *const __user *)regs->regs[6], | ||
105 | regs); | ||
106 | |||
107 | putname(filename); | ||
108 | return error; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Do a system call from kernel instead of calling sys_execve so we | ||
113 | * end up with proper pt_regs. | ||
114 | */ | ||
115 | asmlinkage | ||
116 | int kernel_execve(const char *filename, | ||
117 | const char *const argv[], | ||
118 | const char *const envp[]) | ||
119 | { | ||
120 | register unsigned long __r4 asm("r4") = (unsigned long) filename; | ||
121 | register unsigned long __r5 asm("r5") = (unsigned long) argv; | ||
122 | register unsigned long __r6 asm("r6") = (unsigned long) envp; | ||
123 | register unsigned long __r7 asm("r7"); | ||
124 | |||
125 | __asm__ __volatile__ (" \n" | ||
126 | "ldi r27, %5 \n" | ||
127 | "syscall \n" | ||
128 | "mv %0, r4 \n" | ||
129 | "mv %1, r7 \n" | ||
130 | : "=&r" (__r4), "=r" (__r7) | ||
131 | : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve) | ||
132 | : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25", | ||
133 | "r26", "r27", "memory"); | ||
134 | |||
135 | if (__r7 == 0) | ||
136 | return __r4; | ||
137 | |||
138 | return -__r4; | ||
139 | } | ||
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index babc2b826c5c..8451317eed58 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -40,6 +40,8 @@ config SUPERH | |||
40 | select GENERIC_STRNLEN_USER | 40 | select GENERIC_STRNLEN_USER |
41 | select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER | 41 | select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER |
42 | select MODULES_USE_ELF_RELA | 42 | select MODULES_USE_ELF_RELA |
43 | select GENERIC_KERNEL_THREAD | ||
44 | select GENERIC_KERNEL_EXECVE | ||
43 | help | 45 | help |
44 | The SuperH is a RISC processor targeted for use in embedded systems | 46 | The SuperH is a RISC processor targeted for use in embedded systems |
45 | and consumer electronics; it was also used in the Sega Dreamcast | 47 | and consumer electronics; it was also used in the Sega Dreamcast |
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index b6311fd2d066..b1320d55ca30 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h | |||
@@ -126,11 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo | |||
126 | /* Free all resources held by a thread. */ | 126 | /* Free all resources held by a thread. */ |
127 | extern void release_thread(struct task_struct *); | 127 | extern void release_thread(struct task_struct *); |
128 | 128 | ||
129 | /* | ||
130 | * create a kernel thread without removing it from tasklists | ||
131 | */ | ||
132 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
133 | |||
134 | /* Copy and release all segment info associated with a VM */ | 129 | /* Copy and release all segment info associated with a VM */ |
135 | #define copy_segments(p, mm) do { } while(0) | 130 | #define copy_segments(p, mm) do { } while(0) |
136 | #define release_segments(mm) do { } while(0) | 131 | #define release_segments(mm) do { } while(0) |
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index cd6029fb2c01..1ee8946f0952 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h | |||
@@ -159,11 +159,6 @@ struct mm_struct; | |||
159 | 159 | ||
160 | /* Free all resources held by a thread. */ | 160 | /* Free all resources held by a thread. */ |
161 | extern void release_thread(struct task_struct *); | 161 | extern void release_thread(struct task_struct *); |
162 | /* | ||
163 | * create a kernel thread without removing it from tasklists | ||
164 | */ | ||
165 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
166 | |||
167 | 162 | ||
168 | /* Copy and release all segment info associated with a VM */ | 163 | /* Copy and release all segment info associated with a VM */ |
169 | #define copy_segments(p, mm) do { } while (0) | 164 | #define copy_segments(p, mm) do { } while (0) |
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h index 6c1fa559753c..cc25485996bb 100644 --- a/arch/sh/include/asm/syscalls_32.h +++ b/arch/sh/include/asm/syscalls_32.h | |||
@@ -9,20 +9,6 @@ | |||
9 | 9 | ||
10 | struct pt_regs; | 10 | struct pt_regs; |
11 | 11 | ||
12 | asmlinkage int sys_fork(unsigned long r4, unsigned long r5, | ||
13 | unsigned long r6, unsigned long r7, | ||
14 | struct pt_regs __regs); | ||
15 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
16 | unsigned long parent_tidptr, | ||
17 | unsigned long child_tidptr, | ||
18 | struct pt_regs __regs); | ||
19 | asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | ||
20 | unsigned long r6, unsigned long r7, | ||
21 | struct pt_regs __regs); | ||
22 | asmlinkage int sys_execve(const char __user *ufilename, | ||
23 | const char __user *const __user *uargv, | ||
24 | const char __user *const __user *uenvp, | ||
25 | unsigned long r7, struct pt_regs __regs); | ||
26 | asmlinkage int sys_sigsuspend(old_sigset_t mask); | 12 | asmlinkage int sys_sigsuspend(old_sigset_t mask); |
27 | asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, | 13 | asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, |
28 | struct old_sigaction __user *oact); | 14 | struct old_sigaction __user *oact); |
diff --git a/arch/sh/include/asm/syscalls_64.h b/arch/sh/include/asm/syscalls_64.h index ee519f41d950..d62e8eb22f74 100644 --- a/arch/sh/include/asm/syscalls_64.h +++ b/arch/sh/include/asm/syscalls_64.h | |||
@@ -9,23 +9,6 @@ | |||
9 | 9 | ||
10 | struct pt_regs; | 10 | struct pt_regs; |
11 | 11 | ||
12 | asmlinkage int sys_fork(unsigned long r2, unsigned long r3, | ||
13 | unsigned long r4, unsigned long r5, | ||
14 | unsigned long r6, unsigned long r7, | ||
15 | struct pt_regs *pregs); | ||
16 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
17 | unsigned long r4, unsigned long r5, | ||
18 | unsigned long r6, unsigned long r7, | ||
19 | struct pt_regs *pregs); | ||
20 | asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, | ||
21 | unsigned long r4, unsigned long r5, | ||
22 | unsigned long r6, unsigned long r7, | ||
23 | struct pt_regs *pregs); | ||
24 | asmlinkage int sys_execve(const char *ufilename, char **uargv, | ||
25 | char **uenvp, unsigned long r5, | ||
26 | unsigned long r6, unsigned long r7, | ||
27 | struct pt_regs *pregs); | ||
28 | |||
29 | /* Misc syscall related bits */ | 12 | /* Misc syscall related bits */ |
30 | asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs); | 13 | asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs); |
31 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); | 14 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); |
diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index 38956dfa76f7..43d3f26b2eab 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h | |||
@@ -28,6 +28,10 @@ | |||
28 | # define __ARCH_WANT_SYS_SIGPENDING | 28 | # define __ARCH_WANT_SYS_SIGPENDING |
29 | # define __ARCH_WANT_SYS_SIGPROCMASK | 29 | # define __ARCH_WANT_SYS_SIGPROCMASK |
30 | # define __ARCH_WANT_SYS_RT_SIGACTION | 30 | # define __ARCH_WANT_SYS_RT_SIGACTION |
31 | # define __ARCH_WANT_SYS_EXECVE | ||
32 | # define __ARCH_WANT_SYS_FORK | ||
33 | # define __ARCH_WANT_SYS_VFORK | ||
34 | # define __ARCH_WANT_SYS_CLONE | ||
31 | 35 | ||
32 | /* | 36 | /* |
33 | * "Conditional" syscalls | 37 | * "Conditional" syscalls |
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 88571ff8eeec..f259b37874e9 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -16,7 +16,7 @@ obj-y := debugtraps.o dma-nommu.o dumpstack.o \ | |||
16 | machvec.o nmi_debug.o process.o \ | 16 | machvec.o nmi_debug.o process.o \ |
17 | process_$(BITS).o ptrace.o ptrace_$(BITS).o \ | 17 | process_$(BITS).o ptrace.o ptrace_$(BITS).o \ |
18 | reboot.o return_address.o \ | 18 | reboot.o return_address.o \ |
19 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ | 19 | setup.o signal_$(BITS).o sys_sh.o \ |
20 | syscalls_$(BITS).o time.o topology.o traps.o \ | 20 | syscalls_$(BITS).o time.o topology.o traps.o \ |
21 | traps_$(BITS).o unwinder.o | 21 | traps_$(BITS).o unwinder.o |
22 | 22 | ||
@@ -25,6 +25,7 @@ obj-y += iomap.o | |||
25 | obj-$(CONFIG_HAS_IOPORT) += ioport.o | 25 | obj-$(CONFIG_HAS_IOPORT) += ioport.o |
26 | endif | 26 | endif |
27 | 27 | ||
28 | obj-$(CONFIG_SUPERH32) += sys_sh32.o | ||
28 | obj-y += cpu/ | 29 | obj-y += cpu/ |
29 | obj-$(CONFIG_VSYSCALL) += vsyscall/ | 30 | obj-$(CONFIG_VSYSCALL) += vsyscall/ |
30 | obj-$(CONFIG_SMP) += smp.o | 31 | obj-$(CONFIG_SMP) += smp.o |
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index 7e605b95592a..0c8d0377d40b 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S | |||
@@ -1228,6 +1228,25 @@ ret_from_fork: | |||
1228 | pta ret_from_syscall, tr0 | 1228 | pta ret_from_syscall, tr0 |
1229 | blink tr0, ZERO | 1229 | blink tr0, ZERO |
1230 | 1230 | ||
1231 | .global ret_from_kernel_thread | ||
1232 | ret_from_kernel_thread: | ||
1233 | |||
1234 | movi schedule_tail,r5 | ||
1235 | ori r5, 1, r5 | ||
1236 | ptabs r5, tr0 | ||
1237 | blink tr0, LINK | ||
1238 | |||
1239 | ld.q SP, FRAME_R(2), r2 | ||
1240 | ld.q SP, FRAME_R(3), r3 | ||
1241 | ptabs r3, tr0 | ||
1242 | blink tr0, LINK | ||
1243 | |||
1244 | ld.q SP, FRAME_S(FSPC), r2 | ||
1245 | addi r2, 4, r2 /* Move PC, being pre-execution event */ | ||
1246 | st.q SP, FRAME_S(FSPC), r2 | ||
1247 | pta ret_from_syscall, tr0 | ||
1248 | blink tr0, ZERO | ||
1249 | |||
1231 | syscall_allowed: | 1250 | syscall_allowed: |
1232 | /* Use LINK to deflect the exit point, default is syscall_ret */ | 1251 | /* Use LINK to deflect the exit point, default is syscall_ret */ |
1233 | pta syscall_ret, tr0 | 1252 | pta syscall_ret, tr0 |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index b96489d8b27d..9b6e4beeb296 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -297,6 +297,19 @@ ret_from_fork: | |||
297 | mov r0, r4 | 297 | mov r0, r4 |
298 | bra syscall_exit | 298 | bra syscall_exit |
299 | nop | 299 | nop |
300 | |||
301 | .align 2 | ||
302 | .globl ret_from_kernel_thread | ||
303 | ret_from_kernel_thread: | ||
304 | mov.l 1f, r8 | ||
305 | jsr @r8 | ||
306 | mov r0, r4 | ||
307 | mov.l @(OFF_R5,r15), r5 ! fn | ||
308 | jsr @r5 | ||
309 | mov.l @(OFF_R4,r15), r4 ! arg | ||
310 | bra syscall_exit | ||
311 | nop | ||
312 | |||
300 | .align 2 | 313 | .align 2 |
301 | 1: .long schedule_tail | 314 | 1: .long schedule_tail |
302 | 315 | ||
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index ba7345f37bc9..73eb66fc6253 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs) | |||
68 | show_code(regs); | 68 | show_code(regs); |
69 | } | 69 | } |
70 | 70 | ||
71 | /* | ||
72 | * Create a kernel thread | ||
73 | */ | ||
74 | __noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
75 | { | ||
76 | do_exit(fn(arg)); | ||
77 | } | ||
78 | |||
79 | /* Don't use this in BL=1(cli). Or else, CPU resets! */ | ||
80 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
81 | { | ||
82 | struct pt_regs regs; | ||
83 | int pid; | ||
84 | |||
85 | memset(®s, 0, sizeof(regs)); | ||
86 | regs.regs[4] = (unsigned long)arg; | ||
87 | regs.regs[5] = (unsigned long)fn; | ||
88 | |||
89 | regs.pc = (unsigned long)kernel_thread_helper; | ||
90 | regs.sr = SR_MD; | ||
91 | #if defined(CONFIG_SH_FPU) | ||
92 | regs.sr |= SR_FD; | ||
93 | #endif | ||
94 | |||
95 | /* Ok, create the new process.. */ | ||
96 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | ||
97 | ®s, 0, NULL, NULL); | ||
98 | |||
99 | return pid; | ||
100 | } | ||
101 | EXPORT_SYMBOL(kernel_thread); | ||
102 | |||
103 | void start_thread(struct pt_regs *regs, unsigned long new_pc, | 71 | void start_thread(struct pt_regs *regs, unsigned long new_pc, |
104 | unsigned long new_sp) | 72 | unsigned long new_sp) |
105 | { | 73 | { |
@@ -157,10 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
157 | EXPORT_SYMBOL(dump_fpu); | 125 | EXPORT_SYMBOL(dump_fpu); |
158 | 126 | ||
159 | asmlinkage void ret_from_fork(void); | 127 | asmlinkage void ret_from_fork(void); |
128 | asmlinkage void ret_from_kernel_thread(void); | ||
160 | 129 | ||
161 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
162 | unsigned long unused, | 131 | unsigned long arg, struct task_struct *p) |
163 | struct task_struct *p, struct pt_regs *regs) | ||
164 | { | 132 | { |
165 | struct thread_info *ti = task_thread_info(p); | 133 | struct thread_info *ti = task_thread_info(p); |
166 | struct pt_regs *childregs; | 134 | struct pt_regs *childregs; |
@@ -177,29 +145,35 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
177 | } | 145 | } |
178 | #endif | 146 | #endif |
179 | 147 | ||
180 | childregs = task_pt_regs(p); | 148 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
181 | *childregs = *regs; | ||
182 | 149 | ||
183 | if (user_mode(regs)) { | 150 | childregs = task_pt_regs(p); |
184 | childregs->regs[15] = usp; | 151 | p->thread.sp = (unsigned long) childregs; |
185 | ti->addr_limit = USER_DS; | 152 | if (unlikely(p->flags & PF_KTHREAD)) { |
186 | } else { | 153 | memset(childregs, 0, sizeof(struct pt_regs)); |
187 | childregs->regs[15] = (unsigned long)childregs; | 154 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
155 | childregs->regs[4] = arg; | ||
156 | childregs->regs[5] = usp; | ||
157 | childregs->sr = SR_MD; | ||
158 | #if defined(CONFIG_SH_FPU) | ||
159 | childregs->sr |= SR_FD; | ||
160 | #endif | ||
188 | ti->addr_limit = KERNEL_DS; | 161 | ti->addr_limit = KERNEL_DS; |
189 | ti->status &= ~TS_USEDFPU; | 162 | ti->status &= ~TS_USEDFPU; |
190 | p->fpu_counter = 0; | 163 | p->fpu_counter = 0; |
164 | return 0; | ||
191 | } | 165 | } |
166 | *childregs = *current_pt_regs(); | ||
167 | |||
168 | if (usp) | ||
169 | childregs->regs[15] = usp; | ||
170 | ti->addr_limit = USER_DS; | ||
192 | 171 | ||
193 | if (clone_flags & CLONE_SETTLS) | 172 | if (clone_flags & CLONE_SETTLS) |
194 | childregs->gbr = childregs->regs[0]; | 173 | childregs->gbr = childregs->regs[0]; |
195 | 174 | ||
196 | childregs->regs[0] = 0; /* Set return value for child */ | 175 | childregs->regs[0] = 0; /* Set return value for child */ |
197 | |||
198 | p->thread.sp = (unsigned long) childregs; | ||
199 | p->thread.pc = (unsigned long) ret_from_fork; | 176 | p->thread.pc = (unsigned long) ret_from_fork; |
200 | |||
201 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
202 | |||
203 | return 0; | 177 | return 0; |
204 | } | 178 | } |
205 | 179 | ||
@@ -243,74 +217,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next) | |||
243 | return prev; | 217 | return prev; |
244 | } | 218 | } |
245 | 219 | ||
246 | asmlinkage int sys_fork(unsigned long r4, unsigned long r5, | ||
247 | unsigned long r6, unsigned long r7, | ||
248 | struct pt_regs __regs) | ||
249 | { | ||
250 | #ifdef CONFIG_MMU | ||
251 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
252 | return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); | ||
253 | #else | ||
254 | /* fork almost works, enough to trick you into looking elsewhere :-( */ | ||
255 | return -EINVAL; | ||
256 | #endif | ||
257 | } | ||
258 | |||
259 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
260 | unsigned long parent_tidptr, | ||
261 | unsigned long child_tidptr, | ||
262 | struct pt_regs __regs) | ||
263 | { | ||
264 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
265 | if (!newsp) | ||
266 | newsp = regs->regs[15]; | ||
267 | return do_fork(clone_flags, newsp, regs, 0, | ||
268 | (int __user *)parent_tidptr, | ||
269 | (int __user *)child_tidptr); | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * This is trivial, and on the face of it looks like it | ||
274 | * could equally well be done in user mode. | ||
275 | * | ||
276 | * Not so, for quite unobvious reasons - register pressure. | ||
277 | * In user mode vfork() cannot have a stack frame, and if | ||
278 | * done by calling the "clone()" system call directly, you | ||
279 | * do not have enough call-clobbered registers to hold all | ||
280 | * the information you need. | ||
281 | */ | ||
282 | asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | ||
283 | unsigned long r6, unsigned long r7, | ||
284 | struct pt_regs __regs) | ||
285 | { | ||
286 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
287 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, | ||
288 | 0, NULL, NULL); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * sys_execve() executes a new program. | ||
293 | */ | ||
294 | asmlinkage int sys_execve(const char __user *ufilename, | ||
295 | const char __user *const __user *uargv, | ||
296 | const char __user *const __user *uenvp, | ||
297 | unsigned long r7, struct pt_regs __regs) | ||
298 | { | ||
299 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
300 | int error; | ||
301 | struct filename *filename; | ||
302 | |||
303 | filename = getname(ufilename); | ||
304 | error = PTR_ERR(filename); | ||
305 | if (IS_ERR(filename)) | ||
306 | goto out; | ||
307 | |||
308 | error = do_execve(filename->name, uargv, uenvp, regs); | ||
309 | putname(filename); | ||
310 | out: | ||
311 | return error; | ||
312 | } | ||
313 | |||
314 | unsigned long get_wchan(struct task_struct *p) | 220 | unsigned long get_wchan(struct task_struct *p) |
315 | { | 221 | { |
316 | unsigned long pc; | 222 | unsigned long pc; |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 98a709f0c3c4..e611c85144b1 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -285,39 +285,6 @@ void show_regs(struct pt_regs *regs) | |||
285 | } | 285 | } |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * Create a kernel thread | ||
289 | */ | ||
290 | __noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
291 | { | ||
292 | do_exit(fn(arg)); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * This is the mechanism for creating a new kernel thread. | ||
297 | * | ||
298 | * NOTE! Only a kernel-only process(ie the swapper or direct descendants | ||
299 | * who haven't done an "execve()") should use this: it will work within | ||
300 | * a system call from a "real" process, but the process memory space will | ||
301 | * not be freed until both the parent and the child have exited. | ||
302 | */ | ||
303 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
304 | { | ||
305 | struct pt_regs regs; | ||
306 | |||
307 | memset(®s, 0, sizeof(regs)); | ||
308 | regs.regs[2] = (unsigned long)arg; | ||
309 | regs.regs[3] = (unsigned long)fn; | ||
310 | |||
311 | regs.pc = (unsigned long)kernel_thread_helper; | ||
312 | regs.sr = (1 << 30); | ||
313 | |||
314 | /* Ok, create the new process.. */ | ||
315 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | ||
316 | ®s, 0, NULL, NULL); | ||
317 | } | ||
318 | EXPORT_SYMBOL(kernel_thread); | ||
319 | |||
320 | /* | ||
321 | * Free current thread data structures etc.. | 288 | * Free current thread data structures etc.. |
322 | */ | 289 | */ |
323 | void exit_thread(void) | 290 | void exit_thread(void) |
@@ -401,26 +368,37 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
401 | EXPORT_SYMBOL(dump_fpu); | 368 | EXPORT_SYMBOL(dump_fpu); |
402 | 369 | ||
403 | asmlinkage void ret_from_fork(void); | 370 | asmlinkage void ret_from_fork(void); |
371 | asmlinkage void ret_from_kernel_thread(void); | ||
404 | 372 | ||
405 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 373 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
406 | unsigned long unused, | 374 | unsigned long arg, struct task_struct *p) |
407 | struct task_struct *p, struct pt_regs *regs) | ||
408 | { | 375 | { |
409 | struct pt_regs *childregs; | 376 | struct pt_regs *childregs, *regs = current_pt_regs(); |
410 | 377 | ||
411 | #ifdef CONFIG_SH_FPU | 378 | #ifdef CONFIG_SH_FPU |
412 | if(last_task_used_math == current) { | 379 | /* can't happen for a kernel thread */ |
380 | if (last_task_used_math == current) { | ||
413 | enable_fpu(); | 381 | enable_fpu(); |
414 | save_fpu(current); | 382 | save_fpu(current); |
415 | disable_fpu(); | 383 | disable_fpu(); |
416 | last_task_used_math = NULL; | 384 | last_task_used_math = NULL; |
417 | regs->sr |= SR_FD; | 385 | current_pt_regs()->sr |= SR_FD; |
418 | } | 386 | } |
419 | #endif | 387 | #endif |
420 | /* Copy from sh version */ | 388 | /* Copy from sh version */ |
421 | childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; | 389 | childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; |
390 | p->thread.sp = (unsigned long) childregs; | ||
422 | 391 | ||
423 | *childregs = *regs; | 392 | if (unlikely(p->flags & PF_KTHREAD)) { |
393 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
394 | childregs->regs[2] = (unsigned long)arg; | ||
395 | childregs->regs[3] = (unsigned long)fn; | ||
396 | childregs->sr = (1 << 30); /* not user_mode */ | ||
397 | childregs->sr |= SR_FD; /* Invalidate FPU flag */ | ||
398 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | ||
399 | return 0; | ||
400 | } | ||
401 | *childregs = *current_pt_regs(); | ||
424 | 402 | ||
425 | /* | 403 | /* |
426 | * Sign extend the edited stack. | 404 | * Sign extend the edited stack. |
@@ -428,85 +406,18 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
428 | * 32-bit wide and context switch must take care | 406 | * 32-bit wide and context switch must take care |
429 | * of NEFF sign extension. | 407 | * of NEFF sign extension. |
430 | */ | 408 | */ |
431 | if (user_mode(regs)) { | 409 | if (usp) |
432 | childregs->regs[15] = neff_sign_extend(usp); | 410 | childregs->regs[15] = neff_sign_extend(usp); |
433 | p->thread.uregs = childregs; | 411 | p->thread.uregs = childregs; |
434 | } else { | ||
435 | childregs->regs[15] = | ||
436 | neff_sign_extend((unsigned long)task_stack_page(p) + | ||
437 | THREAD_SIZE); | ||
438 | } | ||
439 | 412 | ||
440 | childregs->regs[9] = 0; /* Set return value for child */ | 413 | childregs->regs[9] = 0; /* Set return value for child */ |
441 | childregs->sr |= SR_FD; /* Invalidate FPU flag */ | 414 | childregs->sr |= SR_FD; /* Invalidate FPU flag */ |
442 | 415 | ||
443 | p->thread.sp = (unsigned long) childregs; | ||
444 | p->thread.pc = (unsigned long) ret_from_fork; | 416 | p->thread.pc = (unsigned long) ret_from_fork; |
445 | 417 | ||
446 | return 0; | 418 | return 0; |
447 | } | 419 | } |
448 | 420 | ||
449 | asmlinkage int sys_fork(unsigned long r2, unsigned long r3, | ||
450 | unsigned long r4, unsigned long r5, | ||
451 | unsigned long r6, unsigned long r7, | ||
452 | struct pt_regs *pregs) | ||
453 | { | ||
454 | return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); | ||
455 | } | ||
456 | |||
457 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
458 | unsigned long r4, unsigned long r5, | ||
459 | unsigned long r6, unsigned long r7, | ||
460 | struct pt_regs *pregs) | ||
461 | { | ||
462 | if (!newsp) | ||
463 | newsp = pregs->regs[15]; | ||
464 | return do_fork(clone_flags, newsp, pregs, 0, 0, 0); | ||
465 | } | ||
466 | |||
467 | /* | ||
468 | * This is trivial, and on the face of it looks like it | ||
469 | * could equally well be done in user mode. | ||
470 | * | ||
471 | * Not so, for quite unobvious reasons - register pressure. | ||
472 | * In user mode vfork() cannot have a stack frame, and if | ||
473 | * done by calling the "clone()" system call directly, you | ||
474 | * do not have enough call-clobbered registers to hold all | ||
475 | * the information you need. | ||
476 | */ | ||
477 | asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, | ||
478 | unsigned long r4, unsigned long r5, | ||
479 | unsigned long r6, unsigned long r7, | ||
480 | struct pt_regs *pregs) | ||
481 | { | ||
482 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * sys_execve() executes a new program. | ||
487 | */ | ||
488 | asmlinkage int sys_execve(const char *ufilename, char **uargv, | ||
489 | char **uenvp, unsigned long r5, | ||
490 | unsigned long r6, unsigned long r7, | ||
491 | struct pt_regs *pregs) | ||
492 | { | ||
493 | int error; | ||
494 | struct filename *filename; | ||
495 | |||
496 | filename = getname((char __user *)ufilename); | ||
497 | error = PTR_ERR(filename); | ||
498 | if (IS_ERR(filename)) | ||
499 | goto out; | ||
500 | |||
501 | error = do_execve(filename->name, | ||
502 | (const char __user *const __user *)uargv, | ||
503 | (const char __user *const __user *)uenvp, | ||
504 | pregs); | ||
505 | putname(filename); | ||
506 | out: | ||
507 | return error; | ||
508 | } | ||
509 | |||
510 | #ifdef CONFIG_FRAME_POINTER | 421 | #ifdef CONFIG_FRAME_POINTER |
511 | static int in_sh64_switch_to(unsigned long pc) | 422 | static int in_sh64_switch_to(unsigned long pc) |
512 | { | 423 | { |
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c index f56b6fe5c5d0..497bab3a0401 100644 --- a/arch/sh/kernel/sys_sh32.c +++ b/arch/sh/kernel/sys_sh32.c | |||
@@ -60,27 +60,3 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, | |||
60 | (u64)len0 << 32 | len1, advice); | 60 | (u64)len0 << 32 | len1, advice); |
61 | #endif | 61 | #endif |
62 | } | 62 | } |
63 | |||
64 | #if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) | ||
65 | #define SYSCALL_ARG3 "trapa #0x23" | ||
66 | #else | ||
67 | #define SYSCALL_ARG3 "trapa #0x13" | ||
68 | #endif | ||
69 | |||
70 | /* | ||
71 | * Do a system call from kernel instead of calling sys_execve so we | ||
72 | * end up with proper pt_regs. | ||
73 | */ | ||
74 | int kernel_execve(const char *filename, | ||
75 | const char *const argv[], | ||
76 | const char *const envp[]) | ||
77 | { | ||
78 | register long __sc0 __asm__ ("r3") = __NR_execve; | ||
79 | register long __sc4 __asm__ ("r4") = (long) filename; | ||
80 | register long __sc5 __asm__ ("r5") = (long) argv; | ||
81 | register long __sc6 __asm__ ("r6") = (long) envp; | ||
82 | __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) | ||
83 | : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) | ||
84 | : "memory"); | ||
85 | return __sc0; | ||
86 | } | ||
diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c deleted file mode 100644 index c5a38c4bf410..000000000000 --- a/arch/sh/kernel/sys_sh64.c +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/sys_sh64.c | ||
3 | * | ||
4 | * Copyright (C) 2000, 2001 Paolo Alberelli | ||
5 | * | ||
6 | * This file contains various random system calls that | ||
7 | * have a non-standard calling sequence on the Linux/SH5 | ||
8 | * platform. | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | */ | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/rwsem.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/smp.h> | ||
20 | #include <linux/sem.h> | ||
21 | #include <linux/msg.h> | ||
22 | #include <linux/shm.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/mman.h> | ||
25 | #include <linux/file.h> | ||
26 | #include <linux/syscalls.h> | ||
27 | #include <linux/ipc.h> | ||
28 | #include <asm/uaccess.h> | ||
29 | #include <asm/ptrace.h> | ||
30 | #include <asm/unistd.h> | ||
31 | |||
32 | /* | ||
33 | * Do a system call from kernel instead of calling sys_execve so we | ||
34 | * end up with proper pt_regs. | ||
35 | */ | ||
36 | int kernel_execve(const char *filename, | ||
37 | const char *const argv[], | ||
38 | const char *const envp[]) | ||
39 | { | ||
40 | register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); | ||
41 | register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; | ||
42 | register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; | ||
43 | register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; | ||
44 | __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" | ||
45 | : "=r" (__sc0) | ||
46 | : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); | ||
47 | __asm__ __volatile__ ("!dummy %0 %1 %2 %3" | ||
48 | : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); | ||
49 | return __sc0; | ||
50 | } | ||
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 9f2edb5c5551..0c7d365fa402 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -41,6 +41,8 @@ config SPARC | |||
41 | select GENERIC_STRNCPY_FROM_USER | 41 | select GENERIC_STRNCPY_FROM_USER |
42 | select GENERIC_STRNLEN_USER | 42 | select GENERIC_STRNLEN_USER |
43 | select MODULES_USE_ELF_RELA | 43 | select MODULES_USE_ELF_RELA |
44 | select GENERIC_KERNEL_THREAD | ||
45 | select GENERIC_KERNEL_EXECVE | ||
44 | 46 | ||
45 | config SPARC32 | 47 | config SPARC32 |
46 | def_bool !64BIT | 48 | def_bool !64BIT |
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h index f74ac9ee33a8..c1e01914fd98 100644 --- a/arch/sparc/include/asm/processor_32.h +++ b/arch/sparc/include/asm/processor_32.h | |||
@@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, | |||
106 | 106 | ||
107 | /* Free all resources held by a thread. */ | 107 | /* Free all resources held by a thread. */ |
108 | #define release_thread(tsk) do { } while(0) | 108 | #define release_thread(tsk) do { } while(0) |
109 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
110 | 109 | ||
111 | extern unsigned long get_wchan(struct task_struct *); | 110 | extern unsigned long get_wchan(struct task_struct *); |
112 | 111 | ||
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index 721e25f0e2ea..cce72ce4c334 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h | |||
@@ -94,6 +94,7 @@ struct thread_struct { | |||
94 | #ifndef __ASSEMBLY__ | 94 | #ifndef __ASSEMBLY__ |
95 | 95 | ||
96 | #include <linux/types.h> | 96 | #include <linux/types.h> |
97 | #include <asm/fpumacro.h> | ||
97 | 98 | ||
98 | /* Return saved PC of a blocked thread. */ | 99 | /* Return saved PC of a blocked thread. */ |
99 | struct task_struct; | 100 | struct task_struct; |
@@ -143,6 +144,10 @@ do { \ | |||
143 | : \ | 144 | : \ |
144 | : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ | 145 | : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ |
145 | "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ | 146 | "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ |
147 | fprs_write(0); \ | ||
148 | current_thread_info()->xfsr[0] = 0; \ | ||
149 | current_thread_info()->fpsaved[0] = 0; \ | ||
150 | regs->tstate &= ~TSTATE_PEF; \ | ||
146 | } while (0) | 151 | } while (0) |
147 | 152 | ||
148 | #define start_thread32(regs, pc, sp) \ | 153 | #define start_thread32(regs, pc, sp) \ |
@@ -183,13 +188,15 @@ do { \ | |||
183 | : \ | 188 | : \ |
184 | : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ | 189 | : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ |
185 | "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ | 190 | "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ |
191 | fprs_write(0); \ | ||
192 | current_thread_info()->xfsr[0] = 0; \ | ||
193 | current_thread_info()->fpsaved[0] = 0; \ | ||
194 | regs->tstate &= ~TSTATE_PEF; \ | ||
186 | } while (0) | 195 | } while (0) |
187 | 196 | ||
188 | /* Free all resources held by a thread. */ | 197 | /* Free all resources held by a thread. */ |
189 | #define release_thread(tsk) do { } while (0) | 198 | #define release_thread(tsk) do { } while (0) |
190 | 199 | ||
191 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
192 | |||
193 | extern unsigned long get_wchan(struct task_struct *task); | 200 | extern unsigned long get_wchan(struct task_struct *task); |
194 | 201 | ||
195 | #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) | 202 | #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) |
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index da43bdc62294..bdfafd7af46f 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h | |||
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) | |||
32 | #define arch_ptrace_stop(exit_code, info) \ | 32 | #define arch_ptrace_stop(exit_code, info) \ |
33 | synchronize_user_stack() | 33 | synchronize_user_stack() |
34 | 34 | ||
35 | #define current_pt_regs() \ | ||
36 | ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | ||
37 | |||
35 | struct global_reg_snapshot { | 38 | struct global_reg_snapshot { |
36 | unsigned long tstate; | 39 | unsigned long tstate; |
37 | unsigned long tpc; | 40 | unsigned long tpc; |
@@ -55,9 +58,7 @@ union global_cpu_snapshot { | |||
55 | 58 | ||
56 | extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; | 59 | extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; |
57 | 60 | ||
58 | #define force_successful_syscall_return() \ | 61 | #define force_successful_syscall_return() set_thread_noerror(1) |
59 | do { current_thread_info()->syscall_noerror = 1; \ | ||
60 | } while (0) | ||
61 | #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) | 62 | #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) |
62 | #define instruction_pointer(regs) ((regs)->tpc) | 63 | #define instruction_pointer(regs) ((regs)->tpc) |
63 | #define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) | 64 | #define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) |
@@ -100,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) | |||
100 | #define arch_ptrace_stop(exit_code, info) \ | 101 | #define arch_ptrace_stop(exit_code, info) \ |
101 | synchronize_user_stack() | 102 | synchronize_user_stack() |
102 | 103 | ||
104 | #define current_pt_regs() \ | ||
105 | ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | ||
106 | |||
103 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) | 107 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) |
104 | #define instruction_pointer(regs) ((regs)->pc) | 108 | #define instruction_pointer(regs) ((regs)->pc) |
105 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) | 109 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) |
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h index d243c2ae02d2..77b85850d543 100644 --- a/arch/sparc/include/asm/signal.h +++ b/arch/sparc/include/asm/signal.h | |||
@@ -26,7 +26,5 @@ struct k_sigaction { | |||
26 | void __user *ka_restorer; | 26 | void __user *ka_restorer; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
30 | |||
31 | #endif /* !(__ASSEMBLY__) */ | 29 | #endif /* !(__ASSEMBLY__) */ |
32 | #endif /* !(__SPARC_SIGNAL_H) */ | 30 | #endif /* !(__SPARC_SIGNAL_H) */ |
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h index 7923c4a2be38..cad36f56fa03 100644 --- a/arch/sparc/include/asm/switch_to_64.h +++ b/arch/sparc/include/asm/switch_to_64.h | |||
@@ -23,7 +23,7 @@ do { flush_tlb_pending(); \ | |||
23 | /* If you are tempted to conditionalize the following */ \ | 23 | /* If you are tempted to conditionalize the following */ \ |
24 | /* so that ASI is only written if it changes, think again. */ \ | 24 | /* so that ASI is only written if it changes, think again. */ \ |
25 | __asm__ __volatile__("wr %%g0, %0, %%asi" \ | 25 | __asm__ __volatile__("wr %%g0, %0, %%asi" \ |
26 | : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ | 26 | : : "r" (task_thread_info(next)->current_ds));\ |
27 | trap_block[current_thread_info()->cpu].thread = \ | 27 | trap_block[current_thread_info()->cpu].thread = \ |
28 | task_thread_info(next); \ | 28 | task_thread_info(next); \ |
29 | __asm__ __volatile__( \ | 29 | __asm__ __volatile__( \ |
diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h index 45a43f637a14..bf8972adea17 100644 --- a/arch/sparc/include/asm/syscalls.h +++ b/arch/sparc/include/asm/syscalls.h | |||
@@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
8 | struct pt_regs *regs, | 8 | struct pt_regs *regs, |
9 | unsigned long stack_size); | 9 | unsigned long stack_size); |
10 | 10 | ||
11 | extern asmlinkage int sparc_execve(struct pt_regs *regs); | ||
12 | |||
13 | #endif /* _SPARC64_SYSCALLS_H */ | 11 | #endif /* _SPARC64_SYSCALLS_H */ |
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index a3fe4dcc0aa6..269bd92313df 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h | |||
@@ -14,12 +14,12 @@ | |||
14 | #define TI_FLAG_FAULT_CODE_SHIFT 56 | 14 | #define TI_FLAG_FAULT_CODE_SHIFT 56 |
15 | #define TI_FLAG_BYTE_WSTATE 1 | 15 | #define TI_FLAG_BYTE_WSTATE 1 |
16 | #define TI_FLAG_WSTATE_SHIFT 48 | 16 | #define TI_FLAG_WSTATE_SHIFT 48 |
17 | #define TI_FLAG_BYTE_CWP 2 | 17 | #define TI_FLAG_BYTE_NOERROR 2 |
18 | #define TI_FLAG_CWP_SHIFT 40 | 18 | #define TI_FLAG_BYTE_NOERROR_SHIFT 40 |
19 | #define TI_FLAG_BYTE_CURRENT_DS 3 | 19 | #define TI_FLAG_BYTE_FPDEPTH 3 |
20 | #define TI_FLAG_CURRENT_DS_SHIFT 32 | 20 | #define TI_FLAG_FPDEPTH_SHIFT 32 |
21 | #define TI_FLAG_BYTE_FPDEPTH 4 | 21 | #define TI_FLAG_BYTE_CWP 4 |
22 | #define TI_FLAG_FPDEPTH_SHIFT 24 | 22 | #define TI_FLAG_CWP_SHIFT 24 |
23 | #define TI_FLAG_BYTE_WSAVED 5 | 23 | #define TI_FLAG_BYTE_WSAVED 5 |
24 | #define TI_FLAG_WSAVED_SHIFT 16 | 24 | #define TI_FLAG_WSAVED_SHIFT 16 |
25 | 25 | ||
@@ -47,7 +47,7 @@ struct thread_info { | |||
47 | struct exec_domain *exec_domain; | 47 | struct exec_domain *exec_domain; |
48 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 48 | int preempt_count; /* 0 => preemptable, <0 => BUG */ |
49 | __u8 new_child; | 49 | __u8 new_child; |
50 | __u8 syscall_noerror; | 50 | __u8 current_ds; |
51 | __u16 cpu; | 51 | __u16 cpu; |
52 | 52 | ||
53 | unsigned long *utraps; | 53 | unsigned long *utraps; |
@@ -74,9 +74,9 @@ struct thread_info { | |||
74 | #define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) | 74 | #define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) |
75 | #define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) | 75 | #define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) |
76 | #define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) | 76 | #define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) |
77 | #define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS) | ||
78 | #define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) | 77 | #define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) |
79 | #define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) | 78 | #define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) |
79 | #define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR) | ||
80 | #define TI_FPSAVED 0x00000010 | 80 | #define TI_FPSAVED 0x00000010 |
81 | #define TI_KSP 0x00000018 | 81 | #define TI_KSP 0x00000018 |
82 | #define TI_FAULT_ADDR 0x00000020 | 82 | #define TI_FAULT_ADDR 0x00000020 |
@@ -84,7 +84,7 @@ struct thread_info { | |||
84 | #define TI_EXEC_DOMAIN 0x00000030 | 84 | #define TI_EXEC_DOMAIN 0x00000030 |
85 | #define TI_PRE_COUNT 0x00000038 | 85 | #define TI_PRE_COUNT 0x00000038 |
86 | #define TI_NEW_CHILD 0x0000003c | 86 | #define TI_NEW_CHILD 0x0000003c |
87 | #define TI_SYS_NOERROR 0x0000003d | 87 | #define TI_CURRENT_DS 0x0000003d |
88 | #define TI_CPU 0x0000003e | 88 | #define TI_CPU 0x0000003e |
89 | #define TI_UTRAPS 0x00000040 | 89 | #define TI_UTRAPS 0x00000040 |
90 | #define TI_REG_WINDOW 0x00000048 | 90 | #define TI_REG_WINDOW 0x00000048 |
@@ -121,7 +121,7 @@ struct thread_info { | |||
121 | #define INIT_THREAD_INFO(tsk) \ | 121 | #define INIT_THREAD_INFO(tsk) \ |
122 | { \ | 122 | { \ |
123 | .task = &tsk, \ | 123 | .task = &tsk, \ |
124 | .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ | 124 | .current_ds = ASI_P, \ |
125 | .exec_domain = &default_exec_domain, \ | 125 | .exec_domain = &default_exec_domain, \ |
126 | .preempt_count = INIT_PREEMPT_COUNT, \ | 126 | .preempt_count = INIT_PREEMPT_COUNT, \ |
127 | .restart_block = { \ | 127 | .restart_block = { \ |
@@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
153 | #define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) | 153 | #define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) |
154 | #define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) | 154 | #define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) |
155 | #define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) | 155 | #define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) |
156 | #define get_thread_current_ds() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS]) | 156 | #define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR]) |
157 | #define set_thread_current_ds(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val)) | 157 | #define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val)) |
158 | #define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) | 158 | #define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) |
159 | #define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) | 159 | #define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) |
160 | #define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) | 160 | #define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) |
161 | #define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) | 161 | #define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) |
162 | |||
163 | #endif /* !(__ASSEMBLY__) */ | 162 | #endif /* !(__ASSEMBLY__) */ |
164 | 163 | ||
165 | /* | 164 | /* |
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 73083e1d38d9..e562d3caee57 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h | |||
@@ -38,14 +38,14 @@ | |||
38 | #define VERIFY_READ 0 | 38 | #define VERIFY_READ 0 |
39 | #define VERIFY_WRITE 1 | 39 | #define VERIFY_WRITE 1 |
40 | 40 | ||
41 | #define get_fs() ((mm_segment_t) { get_thread_current_ds() }) | 41 | #define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) |
42 | #define get_ds() (KERNEL_DS) | 42 | #define get_ds() (KERNEL_DS) |
43 | 43 | ||
44 | #define segment_eq(a,b) ((a).seg == (b).seg) | 44 | #define segment_eq(a,b) ((a).seg == (b).seg) |
45 | 45 | ||
46 | #define set_fs(val) \ | 46 | #define set_fs(val) \ |
47 | do { \ | 47 | do { \ |
48 | set_thread_current_ds((val).seg); \ | 48 | current_thread_info()->current_ds =(val).seg; \ |
49 | __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ | 49 | __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ |
50 | } while(0) | 50 | } while(0) |
51 | 51 | ||
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 0ecea6ed943e..c3e5d8b64171 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 46 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
47 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE | 47 | #define __ARCH_WANT_COMPAT_SYS_SENDFILE |
48 | #endif | 48 | #endif |
49 | #define __ARCH_WANT_SYS_EXECVE | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * "Conditional" syscalls | 52 | * "Conditional" syscalls |
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index dcaa1cf0de40..21fd1a8f47d2 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -806,23 +806,10 @@ sys_nis_syscall: | |||
806 | call c_sys_nis_syscall | 806 | call c_sys_nis_syscall |
807 | mov %l5, %o7 | 807 | mov %l5, %o7 |
808 | 808 | ||
809 | .align 4 | ||
810 | .globl sys_execve | ||
811 | sys_execve: | ||
812 | mov %o7, %l5 | ||
813 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg | ||
814 | call sparc_execve | ||
815 | mov %l5, %o7 | ||
816 | |||
817 | .globl sunos_execv | ||
818 | sunos_execv: | 809 | sunos_execv: |
819 | st %g0, [%sp + STACKFRAME_SZ + PT_I2] | 810 | .globl sunos_execv |
820 | 811 | b sys_execve | |
821 | call sparc_execve | 812 | clr %i2 |
822 | add %sp, STACKFRAME_SZ, %o0 | ||
823 | |||
824 | b ret_sys_call | ||
825 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 | ||
826 | 813 | ||
827 | .align 4 | 814 | .align 4 |
828 | .globl sys_sparc_pipe | 815 | .globl sys_sparc_pipe |
@@ -959,17 +946,9 @@ flush_patch_four: | |||
959 | .align 4 | 946 | .align 4 |
960 | linux_sparc_ni_syscall: | 947 | linux_sparc_ni_syscall: |
961 | sethi %hi(sys_ni_syscall), %l7 | 948 | sethi %hi(sys_ni_syscall), %l7 |
962 | b syscall_is_too_hard | 949 | b do_syscall |
963 | or %l7, %lo(sys_ni_syscall), %l7 | 950 | or %l7, %lo(sys_ni_syscall), %l7 |
964 | 951 | ||
965 | linux_fast_syscall: | ||
966 | andn %l7, 3, %l7 | ||
967 | mov %i0, %o0 | ||
968 | mov %i1, %o1 | ||
969 | mov %i2, %o2 | ||
970 | jmpl %l7 + %g0, %g0 | ||
971 | mov %i3, %o3 | ||
972 | |||
973 | linux_syscall_trace: | 952 | linux_syscall_trace: |
974 | add %sp, STACKFRAME_SZ, %o0 | 953 | add %sp, STACKFRAME_SZ, %o0 |
975 | call syscall_trace | 954 | call syscall_trace |
@@ -991,6 +970,23 @@ ret_from_fork: | |||
991 | b ret_sys_call | 970 | b ret_sys_call |
992 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 | 971 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 |
993 | 972 | ||
973 | .globl ret_from_kernel_thread | ||
974 | ret_from_kernel_thread: | ||
975 | call schedule_tail | ||
976 | ld [%g3 + TI_TASK], %o0 | ||
977 | ld [%sp + STACKFRAME_SZ + PT_G1], %l0 | ||
978 | call %l0 | ||
979 | ld [%sp + STACKFRAME_SZ + PT_G2], %o0 | ||
980 | rd %psr, %l1 | ||
981 | ld [%sp + STACKFRAME_SZ + PT_PSR], %l0 | ||
982 | andn %l0, PSR_CWP, %l0 | ||
983 | nop | ||
984 | and %l1, PSR_CWP, %l1 | ||
985 | or %l0, %l1, %l0 | ||
986 | st %l0, [%sp + STACKFRAME_SZ + PT_PSR] | ||
987 | b ret_sys_call | ||
988 | mov 0, %o0 | ||
989 | |||
994 | /* Linux native system calls enter here... */ | 990 | /* Linux native system calls enter here... */ |
995 | .align 4 | 991 | .align 4 |
996 | .globl linux_sparc_syscall | 992 | .globl linux_sparc_syscall |
@@ -1002,11 +998,8 @@ linux_sparc_syscall: | |||
1002 | bgeu linux_sparc_ni_syscall | 998 | bgeu linux_sparc_ni_syscall |
1003 | sll %g1, 2, %l4 | 999 | sll %g1, 2, %l4 |
1004 | ld [%l7 + %l4], %l7 | 1000 | ld [%l7 + %l4], %l7 |
1005 | andcc %l7, 1, %g0 | ||
1006 | bne linux_fast_syscall | ||
1007 | /* Just do first insn from SAVE_ALL in the delay slot */ | ||
1008 | 1001 | ||
1009 | syscall_is_too_hard: | 1002 | do_syscall: |
1010 | SAVE_ALL_HEAD | 1003 | SAVE_ALL_HEAD |
1011 | rd %wim, %l3 | 1004 | rd %wim, %l3 |
1012 | 1005 | ||
diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S index 786b185e6e3f..1276ca2567ba 100644 --- a/arch/sparc/kernel/etrap_64.S +++ b/arch/sparc/kernel/etrap_64.S | |||
@@ -92,8 +92,10 @@ etrap_save: save %g2, -STACK_BIAS, %sp | |||
92 | rdpr %wstate, %g2 | 92 | rdpr %wstate, %g2 |
93 | wrpr %g0, 0, %canrestore | 93 | wrpr %g0, 0, %canrestore |
94 | sll %g2, 3, %g2 | 94 | sll %g2, 3, %g2 |
95 | |||
96 | /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR. */ | ||
95 | mov 1, %l5 | 97 | mov 1, %l5 |
96 | stb %l5, [%l6 + TI_FPDEPTH] | 98 | sth %l5, [%l6 + TI_SYS_NOERROR] |
97 | 99 | ||
98 | wrpr %g3, 0, %otherwin | 100 | wrpr %g3, 0, %otherwin |
99 | wrpr %g2, 0, %wstate | 101 | wrpr %g2, 0, %wstate |
@@ -152,7 +154,9 @@ etrap_save: save %g2, -STACK_BIAS, %sp | |||
152 | add %l6, TI_FPSAVED + 1, %l4 | 154 | add %l6, TI_FPSAVED + 1, %l4 |
153 | srl %l5, 1, %l3 | 155 | srl %l5, 1, %l3 |
154 | add %l5, 2, %l5 | 156 | add %l5, 2, %l5 |
155 | stb %l5, [%l6 + TI_FPDEPTH] | 157 | |
158 | /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR. */ | ||
159 | sth %l5, [%l6 + TI_SYS_NOERROR] | ||
156 | ba,pt %xcc, 2b | 160 | ba,pt %xcc, 2b |
157 | stb %g0, [%l4 + %l3] | 161 | stb %g0, [%l4 + %l3] |
158 | nop | 162 | nop |
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 487bffb36f5e..be8e862badaf 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c | |||
@@ -286,8 +286,7 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, | |||
286 | parent_tid_ptr = regs->u_regs[UREG_I2]; | 286 | parent_tid_ptr = regs->u_regs[UREG_I2]; |
287 | child_tid_ptr = regs->u_regs[UREG_I4]; | 287 | child_tid_ptr = regs->u_regs[UREG_I4]; |
288 | 288 | ||
289 | ret = do_fork(clone_flags, stack_start, | 289 | ret = do_fork(clone_flags, stack_start, stack_size, |
290 | regs, stack_size, | ||
291 | (int __user *) parent_tid_ptr, | 290 | (int __user *) parent_tid_ptr, |
292 | (int __user *) child_tid_ptr); | 291 | (int __user *) child_tid_ptr); |
293 | 292 | ||
@@ -316,13 +315,13 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, | |||
316 | * XXX See comment above sys_vfork in sparc64. todo. | 315 | * XXX See comment above sys_vfork in sparc64. todo. |
317 | */ | 316 | */ |
318 | extern void ret_from_fork(void); | 317 | extern void ret_from_fork(void); |
318 | extern void ret_from_kernel_thread(void); | ||
319 | 319 | ||
320 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 320 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
321 | unsigned long unused, | 321 | unsigned long arg, struct task_struct *p) |
322 | struct task_struct *p, struct pt_regs *regs) | ||
323 | { | 322 | { |
324 | struct thread_info *ti = task_thread_info(p); | 323 | struct thread_info *ti = task_thread_info(p); |
325 | struct pt_regs *childregs; | 324 | struct pt_regs *childregs, *regs = current_pt_regs(); |
326 | char *new_stack; | 325 | char *new_stack; |
327 | 326 | ||
328 | #ifndef CONFIG_SMP | 327 | #ifndef CONFIG_SMP |
@@ -336,16 +335,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
336 | } | 335 | } |
337 | 336 | ||
338 | /* | 337 | /* |
339 | * p->thread_info new_stack childregs | 338 | * p->thread_info new_stack childregs stack bottom |
340 | * ! ! ! {if(PSR_PS) } | 339 | * ! ! ! ! |
341 | * V V (stk.fr.) V (pt_regs) { (stk.fr.) } | 340 | * V V (stk.fr.) V (pt_regs) V |
342 | * +----- - - - - - ------+===========+============={+==========}+ | 341 | * +----- - - - - - ------+===========+=============+ |
343 | */ | 342 | */ |
344 | new_stack = task_stack_page(p) + THREAD_SIZE; | 343 | new_stack = task_stack_page(p) + THREAD_SIZE; |
345 | if (regs->psr & PSR_PS) | ||
346 | new_stack -= STACKFRAME_SZ; | ||
347 | new_stack -= STACKFRAME_SZ + TRACEREG_SZ; | 344 | new_stack -= STACKFRAME_SZ + TRACEREG_SZ; |
348 | memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); | ||
349 | childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); | 345 | childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); |
350 | 346 | ||
351 | /* | 347 | /* |
@@ -356,55 +352,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
356 | * Thus, kpsr|=PSR_PIL. | 352 | * Thus, kpsr|=PSR_PIL. |
357 | */ | 353 | */ |
358 | ti->ksp = (unsigned long) new_stack; | 354 | ti->ksp = (unsigned long) new_stack; |
355 | p->thread.kregs = childregs; | ||
356 | |||
357 | if (unlikely(p->flags & PF_KTHREAD)) { | ||
358 | extern int nwindows; | ||
359 | unsigned long psr; | ||
360 | memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ); | ||
361 | p->thread.flags |= SPARC_FLAG_KTHREAD; | ||
362 | p->thread.current_ds = KERNEL_DS; | ||
363 | ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8); | ||
364 | childregs->u_regs[UREG_G1] = sp; /* function */ | ||
365 | childregs->u_regs[UREG_G2] = arg; | ||
366 | psr = childregs->psr = get_psr(); | ||
367 | ti->kpsr = psr | PSR_PIL; | ||
368 | ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows); | ||
369 | return 0; | ||
370 | } | ||
371 | memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); | ||
372 | childregs->u_regs[UREG_FP] = sp; | ||
373 | p->thread.flags &= ~SPARC_FLAG_KTHREAD; | ||
374 | p->thread.current_ds = USER_DS; | ||
359 | ti->kpc = (((unsigned long) ret_from_fork) - 0x8); | 375 | ti->kpc = (((unsigned long) ret_from_fork) - 0x8); |
360 | ti->kpsr = current->thread.fork_kpsr | PSR_PIL; | 376 | ti->kpsr = current->thread.fork_kpsr | PSR_PIL; |
361 | ti->kwim = current->thread.fork_kwim; | 377 | ti->kwim = current->thread.fork_kwim; |
362 | 378 | ||
363 | if(regs->psr & PSR_PS) { | 379 | if (sp != regs->u_regs[UREG_FP]) { |
364 | extern struct pt_regs fake_swapper_regs; | 380 | struct sparc_stackf __user *childstack; |
381 | struct sparc_stackf __user *parentstack; | ||
365 | 382 | ||
366 | p->thread.kregs = &fake_swapper_regs; | 383 | /* |
367 | new_stack += STACKFRAME_SZ + TRACEREG_SZ; | 384 | * This is a clone() call with supplied user stack. |
368 | childregs->u_regs[UREG_FP] = (unsigned long) new_stack; | 385 | * Set some valid stack frames to give to the child. |
369 | p->thread.flags |= SPARC_FLAG_KTHREAD; | 386 | */ |
370 | p->thread.current_ds = KERNEL_DS; | 387 | childstack = (struct sparc_stackf __user *) |
371 | memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); | 388 | (sp & ~0xfUL); |
372 | childregs->u_regs[UREG_G6] = (unsigned long) ti; | 389 | parentstack = (struct sparc_stackf __user *) |
373 | } else { | 390 | regs->u_regs[UREG_FP]; |
374 | p->thread.kregs = childregs; | ||
375 | childregs->u_regs[UREG_FP] = sp; | ||
376 | p->thread.flags &= ~SPARC_FLAG_KTHREAD; | ||
377 | p->thread.current_ds = USER_DS; | ||
378 | |||
379 | if (sp != regs->u_regs[UREG_FP]) { | ||
380 | struct sparc_stackf __user *childstack; | ||
381 | struct sparc_stackf __user *parentstack; | ||
382 | |||
383 | /* | ||
384 | * This is a clone() call with supplied user stack. | ||
385 | * Set some valid stack frames to give to the child. | ||
386 | */ | ||
387 | childstack = (struct sparc_stackf __user *) | ||
388 | (sp & ~0xfUL); | ||
389 | parentstack = (struct sparc_stackf __user *) | ||
390 | regs->u_regs[UREG_FP]; | ||
391 | 391 | ||
392 | #if 0 | 392 | #if 0 |
393 | printk("clone: parent stack:\n"); | 393 | printk("clone: parent stack:\n"); |
394 | show_stackframe(parentstack); | 394 | show_stackframe(parentstack); |
395 | #endif | 395 | #endif |
396 | 396 | ||
397 | childstack = clone_stackframe(childstack, parentstack); | 397 | childstack = clone_stackframe(childstack, parentstack); |
398 | if (!childstack) | 398 | if (!childstack) |
399 | return -EFAULT; | 399 | return -EFAULT; |
400 | 400 | ||
401 | #if 0 | 401 | #if 0 |
402 | printk("clone: child stack:\n"); | 402 | printk("clone: child stack:\n"); |
403 | show_stackframe(childstack); | 403 | show_stackframe(childstack); |
404 | #endif | 404 | #endif |
405 | 405 | ||
406 | childregs->u_regs[UREG_FP] = (unsigned long)childstack; | 406 | childregs->u_regs[UREG_FP] = (unsigned long)childstack; |
407 | } | ||
408 | } | 407 | } |
409 | 408 | ||
410 | #ifdef CONFIG_SMP | 409 | #ifdef CONFIG_SMP |
@@ -475,69 +474,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) | |||
475 | return 1; | 474 | return 1; |
476 | } | 475 | } |
477 | 476 | ||
478 | /* | ||
479 | * sparc_execve() executes a new program after the asm stub has set | ||
480 | * things up for us. This should basically do what I want it to. | ||
481 | */ | ||
482 | asmlinkage int sparc_execve(struct pt_regs *regs) | ||
483 | { | ||
484 | int error, base = 0; | ||
485 | struct filename *filename; | ||
486 | |||
487 | /* Check for indirect call. */ | ||
488 | if(regs->u_regs[UREG_G1] == 0) | ||
489 | base = 1; | ||
490 | |||
491 | filename = getname((char __user *)regs->u_regs[base + UREG_I0]); | ||
492 | error = PTR_ERR(filename); | ||
493 | if(IS_ERR(filename)) | ||
494 | goto out; | ||
495 | error = do_execve(filename->name, | ||
496 | (const char __user *const __user *) | ||
497 | regs->u_regs[base + UREG_I1], | ||
498 | (const char __user *const __user *) | ||
499 | regs->u_regs[base + UREG_I2], | ||
500 | regs); | ||
501 | putname(filename); | ||
502 | out: | ||
503 | return error; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * This is the mechanism for creating a new kernel thread. | ||
508 | * | ||
509 | * NOTE! Only a kernel-only process(ie the swapper or direct descendants | ||
510 | * who haven't done an "execve()") should use this: it will work within | ||
511 | * a system call from a "real" process, but the process memory space will | ||
512 | * not be freed until both the parent and the child have exited. | ||
513 | */ | ||
514 | pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
515 | { | ||
516 | long retval; | ||
517 | |||
518 | __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */ | ||
519 | "mov %5, %%g3\n\t" /* and arg. */ | ||
520 | "mov %1, %%g1\n\t" | ||
521 | "mov %2, %%o0\n\t" /* Clone flags. */ | ||
522 | "mov 0, %%o1\n\t" /* usp arg == 0 */ | ||
523 | "t 0x10\n\t" /* Linux/Sparc clone(). */ | ||
524 | "cmp %%o1, 0\n\t" | ||
525 | "be 1f\n\t" /* The parent, just return. */ | ||
526 | " nop\n\t" /* Delay slot. */ | ||
527 | "jmpl %%g2, %%o7\n\t" /* Call the function. */ | ||
528 | " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ | ||
529 | "mov %3, %%g1\n\t" | ||
530 | "t 0x10\n\t" /* Linux/Sparc exit(). */ | ||
531 | /* Notreached by child. */ | ||
532 | "1: mov %%o0, %0\n\t" : | ||
533 | "=r" (retval) : | ||
534 | "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), | ||
535 | "i" (__NR_exit), "r" (fn), "r" (arg) : | ||
536 | "g1", "g2", "g3", "o0", "o1", "memory", "cc"); | ||
537 | return retval; | ||
538 | } | ||
539 | EXPORT_SYMBOL(kernel_thread); | ||
540 | |||
541 | unsigned long get_wchan(struct task_struct *task) | 477 | unsigned long get_wchan(struct task_struct *task) |
542 | { | 478 | { |
543 | unsigned long pc, fp, bias = 0; | 479 | unsigned long pc, fp, bias = 0; |
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index c6e0c2910043..cdb80b2adbe0 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c | |||
@@ -601,8 +601,7 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
601 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; | 601 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; |
602 | } | 602 | } |
603 | 603 | ||
604 | ret = do_fork(clone_flags, stack_start, | 604 | ret = do_fork(clone_flags, stack_start, stack_size, |
605 | regs, stack_size, | ||
606 | parent_tid_ptr, child_tid_ptr); | 605 | parent_tid_ptr, child_tid_ptr); |
607 | 606 | ||
608 | /* If we get an error and potentially restart the system | 607 | /* If we get an error and potentially restart the system |
@@ -622,64 +621,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
622 | * Child --> %o0 == parents pid, %o1 == 1 | 621 | * Child --> %o0 == parents pid, %o1 == 1 |
623 | */ | 622 | */ |
624 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 623 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
625 | unsigned long unused, | 624 | unsigned long arg, struct task_struct *p) |
626 | struct task_struct *p, struct pt_regs *regs) | ||
627 | { | 625 | { |
628 | struct thread_info *t = task_thread_info(p); | 626 | struct thread_info *t = task_thread_info(p); |
627 | struct pt_regs *regs = current_pt_regs(); | ||
629 | struct sparc_stackf *parent_sf; | 628 | struct sparc_stackf *parent_sf; |
630 | unsigned long child_stack_sz; | 629 | unsigned long child_stack_sz; |
631 | char *child_trap_frame; | 630 | char *child_trap_frame; |
632 | int kernel_thread; | ||
633 | |||
634 | kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; | ||
635 | parent_sf = ((struct sparc_stackf *) regs) - 1; | ||
636 | 631 | ||
637 | /* Calculate offset to stack_frame & pt_regs */ | 632 | /* Calculate offset to stack_frame & pt_regs */ |
638 | child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + | 633 | child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ); |
639 | (kernel_thread ? STACKFRAME_SZ : 0)); | ||
640 | child_trap_frame = (task_stack_page(p) + | 634 | child_trap_frame = (task_stack_page(p) + |
641 | (THREAD_SIZE - child_stack_sz)); | 635 | (THREAD_SIZE - child_stack_sz)); |
642 | memcpy(child_trap_frame, parent_sf, child_stack_sz); | ||
643 | 636 | ||
644 | t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | | ||
645 | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | | ||
646 | (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); | ||
647 | t->new_child = 1; | 637 | t->new_child = 1; |
648 | t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; | 638 | t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; |
649 | t->kregs = (struct pt_regs *) (child_trap_frame + | 639 | t->kregs = (struct pt_regs *) (child_trap_frame + |
650 | sizeof(struct sparc_stackf)); | 640 | sizeof(struct sparc_stackf)); |
651 | t->fpsaved[0] = 0; | 641 | t->fpsaved[0] = 0; |
652 | 642 | ||
653 | if (kernel_thread) { | 643 | if (unlikely(p->flags & PF_KTHREAD)) { |
654 | struct sparc_stackf *child_sf = (struct sparc_stackf *) | 644 | memset(child_trap_frame, 0, child_stack_sz); |
655 | (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); | 645 | __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = |
656 | 646 | (current_pt_regs()->tstate + 1) & TSTATE_CWP; | |
657 | /* Zero terminate the stack backtrace. */ | 647 | t->current_ds = ASI_P; |
658 | child_sf->fp = NULL; | 648 | t->kregs->u_regs[UREG_G1] = sp; /* function */ |
659 | t->kregs->u_regs[UREG_FP] = | 649 | t->kregs->u_regs[UREG_G2] = arg; |
660 | ((unsigned long) child_sf) - STACK_BIAS; | 650 | return 0; |
651 | } | ||
661 | 652 | ||
662 | t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); | 653 | parent_sf = ((struct sparc_stackf *) regs) - 1; |
663 | t->kregs->u_regs[UREG_G6] = (unsigned long) t; | 654 | memcpy(child_trap_frame, parent_sf, child_stack_sz); |
664 | t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; | 655 | if (t->flags & _TIF_32BIT) { |
665 | } else { | 656 | sp &= 0x00000000ffffffffUL; |
666 | if (t->flags & _TIF_32BIT) { | 657 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; |
667 | sp &= 0x00000000ffffffffUL; | ||
668 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; | ||
669 | } | ||
670 | t->kregs->u_regs[UREG_FP] = sp; | ||
671 | t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT); | ||
672 | if (sp != regs->u_regs[UREG_FP]) { | ||
673 | unsigned long csp; | ||
674 | |||
675 | csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); | ||
676 | if (!csp) | ||
677 | return -EFAULT; | ||
678 | t->kregs->u_regs[UREG_FP] = csp; | ||
679 | } | ||
680 | if (t->utraps) | ||
681 | t->utraps[0]++; | ||
682 | } | 658 | } |
659 | t->kregs->u_regs[UREG_FP] = sp; | ||
660 | __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = | ||
661 | (regs->tstate + 1) & TSTATE_CWP; | ||
662 | t->current_ds = ASI_AIUS; | ||
663 | if (sp != regs->u_regs[UREG_FP]) { | ||
664 | unsigned long csp; | ||
665 | |||
666 | csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); | ||
667 | if (!csp) | ||
668 | return -EFAULT; | ||
669 | t->kregs->u_regs[UREG_FP] = csp; | ||
670 | } | ||
671 | if (t->utraps) | ||
672 | t->utraps[0]++; | ||
683 | 673 | ||
684 | /* Set the return value for the child. */ | 674 | /* Set the return value for the child. */ |
685 | t->kregs->u_regs[UREG_I0] = current->pid; | 675 | t->kregs->u_regs[UREG_I0] = current->pid; |
@@ -694,45 +684,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
694 | return 0; | 684 | return 0; |
695 | } | 685 | } |
696 | 686 | ||
697 | /* | ||
698 | * This is the mechanism for creating a new kernel thread. | ||
699 | * | ||
700 | * NOTE! Only a kernel-only process(ie the swapper or direct descendants | ||
701 | * who haven't done an "execve()") should use this: it will work within | ||
702 | * a system call from a "real" process, but the process memory space will | ||
703 | * not be freed until both the parent and the child have exited. | ||
704 | */ | ||
705 | pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
706 | { | ||
707 | long retval; | ||
708 | |||
709 | /* If the parent runs before fn(arg) is called by the child, | ||
710 | * the input registers of this function can be clobbered. | ||
711 | * So we stash 'fn' and 'arg' into global registers which | ||
712 | * will not be modified by the parent. | ||
713 | */ | ||
714 | __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */ | ||
715 | "mov %5, %%g3\n\t" /* Save ARG into global */ | ||
716 | "mov %1, %%g1\n\t" /* Clone syscall nr. */ | ||
717 | "mov %2, %%o0\n\t" /* Clone flags. */ | ||
718 | "mov 0, %%o1\n\t" /* usp arg == 0 */ | ||
719 | "t 0x6d\n\t" /* Linux/Sparc clone(). */ | ||
720 | "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ | ||
721 | " mov %%o0, %0\n\t" | ||
722 | "jmpl %%g2, %%o7\n\t" /* Call the function. */ | ||
723 | " mov %%g3, %%o0\n\t" /* Set arg in delay. */ | ||
724 | "mov %3, %%g1\n\t" | ||
725 | "t 0x6d\n\t" /* Linux/Sparc exit(). */ | ||
726 | /* Notreached by child. */ | ||
727 | "1:" : | ||
728 | "=r" (retval) : | ||
729 | "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), | ||
730 | "i" (__NR_exit), "r" (fn), "r" (arg) : | ||
731 | "g1", "g2", "g3", "o0", "o1", "memory", "cc"); | ||
732 | return retval; | ||
733 | } | ||
734 | EXPORT_SYMBOL(kernel_thread); | ||
735 | |||
736 | typedef struct { | 687 | typedef struct { |
737 | union { | 688 | union { |
738 | unsigned int pr_regs[32]; | 689 | unsigned int pr_regs[32]; |
@@ -799,41 +750,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) | |||
799 | } | 750 | } |
800 | EXPORT_SYMBOL(dump_fpu); | 751 | EXPORT_SYMBOL(dump_fpu); |
801 | 752 | ||
802 | /* | ||
803 | * sparc_execve() executes a new program after the asm stub has set | ||
804 | * things up for us. This should basically do what I want it to. | ||
805 | */ | ||
806 | asmlinkage int sparc_execve(struct pt_regs *regs) | ||
807 | { | ||
808 | int error, base = 0; | ||
809 | struct filename *filename; | ||
810 | |||
811 | /* User register window flush is done by entry.S */ | ||
812 | |||
813 | /* Check for indirect call. */ | ||
814 | if (regs->u_regs[UREG_G1] == 0) | ||
815 | base = 1; | ||
816 | |||
817 | filename = getname((char __user *)regs->u_regs[base + UREG_I0]); | ||
818 | error = PTR_ERR(filename); | ||
819 | if (IS_ERR(filename)) | ||
820 | goto out; | ||
821 | error = do_execve(filename->name, | ||
822 | (const char __user *const __user *) | ||
823 | regs->u_regs[base + UREG_I1], | ||
824 | (const char __user *const __user *) | ||
825 | regs->u_regs[base + UREG_I2], regs); | ||
826 | putname(filename); | ||
827 | if (!error) { | ||
828 | fprs_write(0); | ||
829 | current_thread_info()->xfsr[0] = 0; | ||
830 | current_thread_info()->fpsaved[0] = 0; | ||
831 | regs->tstate &= ~TSTATE_PEF; | ||
832 | } | ||
833 | out: | ||
834 | return error; | ||
835 | } | ||
836 | |||
837 | unsigned long get_wchan(struct task_struct *task) | 753 | unsigned long get_wchan(struct task_struct *task) |
838 | { | 754 | { |
839 | unsigned long pc, fp, bias = 0; | 755 | unsigned long pc, fp, bias = 0; |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index c3239811a1b5..03c7e929ec34 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -396,42 +396,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig, | |||
396 | return ret; | 396 | return ret; |
397 | } | 397 | } |
398 | 398 | ||
399 | /* | ||
400 | * sparc32_execve() executes a new program after the asm stub has set | ||
401 | * things up for us. This should basically do what I want it to. | ||
402 | */ | ||
403 | asmlinkage long sparc32_execve(struct pt_regs *regs) | ||
404 | { | ||
405 | int error, base = 0; | ||
406 | struct filename *filename; | ||
407 | |||
408 | /* User register window flush is done by entry.S */ | ||
409 | |||
410 | /* Check for indirect call. */ | ||
411 | if ((u32)regs->u_regs[UREG_G1] == 0) | ||
412 | base = 1; | ||
413 | |||
414 | filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); | ||
415 | error = PTR_ERR(filename); | ||
416 | if (IS_ERR(filename)) | ||
417 | goto out; | ||
418 | |||
419 | error = compat_do_execve(filename->name, | ||
420 | compat_ptr(regs->u_regs[base + UREG_I1]), | ||
421 | compat_ptr(regs->u_regs[base + UREG_I2]), regs); | ||
422 | |||
423 | putname(filename); | ||
424 | |||
425 | if (!error) { | ||
426 | fprs_write(0); | ||
427 | current_thread_info()->xfsr[0] = 0; | ||
428 | current_thread_info()->fpsaved[0] = 0; | ||
429 | regs->tstate &= ~TSTATE_PEF; | ||
430 | } | ||
431 | out: | ||
432 | return error; | ||
433 | } | ||
434 | |||
435 | #ifdef CONFIG_MODULES | 399 | #ifdef CONFIG_MODULES |
436 | 400 | ||
437 | asmlinkage long sys32_init_module(void __user *umod, u32 len, | 401 | asmlinkage long sys32_init_module(void __user *umod, u32 len, |
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 57277c830151..2da0bdcae52f 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c | |||
@@ -249,27 +249,3 @@ out: | |||
249 | up_read(&uts_sem); | 249 | up_read(&uts_sem); |
250 | return err; | 250 | return err; |
251 | } | 251 | } |
252 | |||
253 | /* | ||
254 | * Do a system call from kernel instead of calling sys_execve so we | ||
255 | * end up with proper pt_regs. | ||
256 | */ | ||
257 | int kernel_execve(const char *filename, | ||
258 | const char *const argv[], | ||
259 | const char *const envp[]) | ||
260 | { | ||
261 | long __res; | ||
262 | register long __g1 __asm__ ("g1") = __NR_execve; | ||
263 | register long __o0 __asm__ ("o0") = (long)(filename); | ||
264 | register long __o1 __asm__ ("o1") = (long)(argv); | ||
265 | register long __o2 __asm__ ("o2") = (long)(envp); | ||
266 | asm volatile ("t 0x10\n\t" | ||
267 | "bcc 1f\n\t" | ||
268 | "mov %%o0, %0\n\t" | ||
269 | "sub %%g0, %%o0, %0\n\t" | ||
270 | "1:\n\t" | ||
271 | : "=r" (__res), "=&r" (__o0) | ||
272 | : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) | ||
273 | : "cc"); | ||
274 | return __res; | ||
275 | } | ||
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 97309c0ec533..708bc29d36a8 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -646,28 +646,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, | |||
646 | return ret; | 646 | return ret; |
647 | } | 647 | } |
648 | 648 | ||
649 | /* | ||
650 | * Do a system call from kernel instead of calling sys_execve so we | ||
651 | * end up with proper pt_regs. | ||
652 | */ | ||
653 | int kernel_execve(const char *filename, | ||
654 | const char *const argv[], | ||
655 | const char *const envp[]) | ||
656 | { | ||
657 | long __res; | ||
658 | register long __g1 __asm__ ("g1") = __NR_execve; | ||
659 | register long __o0 __asm__ ("o0") = (long)(filename); | ||
660 | register long __o1 __asm__ ("o1") = (long)(argv); | ||
661 | register long __o2 __asm__ ("o2") = (long)(envp); | ||
662 | asm volatile ("t 0x6d\n\t" | ||
663 | "sub %%g0, %%o0, %0\n\t" | ||
664 | "movcc %%xcc, %%o0, %0\n\t" | ||
665 | : "=r" (__res), "=&r" (__o0) | ||
666 | : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) | ||
667 | : "cc"); | ||
668 | return __res; | ||
669 | } | ||
670 | |||
671 | asmlinkage long sys_kern_features(void) | 649 | asmlinkage long sys_kern_features(void) |
672 | { | 650 | { |
673 | return KERN_FEATURE_MIXED_MODE_STACK; | 651 | return KERN_FEATURE_MIXED_MODE_STACK; |
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index bf2347794e33..e0fed7711a94 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S | |||
@@ -1,23 +1,19 @@ | |||
1 | /* SunOS's execv() call only specifies the argv argument, the | 1 | /* SunOS's execv() call only specifies the argv argument, the |
2 | * environment settings are the same as the calling processes. | 2 | * environment settings are the same as the calling processes. |
3 | */ | 3 | */ |
4 | sys_execve: | 4 | sys64_execve: |
5 | sethi %hi(sparc_execve), %g1 | 5 | set sys_execve, %g1 |
6 | ba,pt %xcc, execve_merge | 6 | jmpl %g1, %g0 |
7 | or %g1, %lo(sparc_execve), %g1 | 7 | flushw |
8 | 8 | ||
9 | #ifdef CONFIG_COMPAT | 9 | #ifdef CONFIG_COMPAT |
10 | sunos_execv: | 10 | sunos_execv: |
11 | stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] | 11 | mov %g0, %o2 |
12 | sys32_execve: | 12 | sys32_execve: |
13 | sethi %hi(sparc32_execve), %g1 | 13 | set compat_sys_execve, %g1 |
14 | or %g1, %lo(sparc32_execve), %g1 | ||
15 | #endif | ||
16 | |||
17 | execve_merge: | ||
18 | flushw | ||
19 | jmpl %g1, %g0 | 14 | jmpl %g1, %g0 |
20 | add %sp, PTREGS_OFF, %o0 | 15 | flushw |
16 | #endif | ||
21 | 17 | ||
22 | .align 32 | 18 | .align 32 |
23 | sys_sparc_pipe: | 19 | sys_sparc_pipe: |
@@ -112,11 +108,16 @@ sys_clone: | |||
112 | ret_from_syscall: | 108 | ret_from_syscall: |
113 | /* Clear current_thread_info()->new_child. */ | 109 | /* Clear current_thread_info()->new_child. */ |
114 | stb %g0, [%g6 + TI_NEW_CHILD] | 110 | stb %g0, [%g6 + TI_NEW_CHILD] |
115 | ldx [%g6 + TI_FLAGS], %l0 | ||
116 | call schedule_tail | 111 | call schedule_tail |
117 | mov %g7, %o0 | 112 | mov %g7, %o0 |
113 | ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 | ||
114 | brnz,pt %o0, ret_sys_call | ||
115 | ldx [%g6 + TI_FLAGS], %l0 | ||
116 | ldx [%sp + PTREGS_OFF + PT_V9_G1], %l1 | ||
117 | call %l1 | ||
118 | ldx [%sp + PTREGS_OFF + PT_V9_G2], %o0 | ||
118 | ba,pt %xcc, ret_sys_call | 119 | ba,pt %xcc, ret_sys_call |
119 | ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 | 120 | mov 0, %o0 |
120 | 121 | ||
121 | .globl sparc_exit_group | 122 | .globl sparc_exit_group |
122 | .type sparc_exit_group,#function | 123 | .type sparc_exit_group,#function |
@@ -232,7 +233,6 @@ ret_sys_call: | |||
232 | ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc | 233 | ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc |
233 | 234 | ||
234 | 2: | 235 | 2: |
235 | stb %g0, [%g6 + TI_SYS_NOERROR] | ||
236 | /* System call success, clear Carry condition code. */ | 236 | /* System call success, clear Carry condition code. */ |
237 | andn %g3, %g2, %g3 | 237 | andn %g3, %g2, %g3 |
238 | 3: | 238 | 3: |
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 017b74a63dcb..cdbd9b817751 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S | |||
@@ -107,7 +107,7 @@ sys_call_table: | |||
107 | /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall | 107 | /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall |
108 | .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid | 108 | .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid |
109 | /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl | 109 | /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl |
110 | .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve | 110 | .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve |
111 | /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize | 111 | /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize |
112 | .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall | 112 | .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall |
113 | /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect | 113 | /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect |
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index b66a77968f35..e7ecf1507d90 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -2688,8 +2688,8 @@ void __init trap_init(void) | |||
2688 | TI_PRE_COUNT != offsetof(struct thread_info, | 2688 | TI_PRE_COUNT != offsetof(struct thread_info, |
2689 | preempt_count) || | 2689 | preempt_count) || |
2690 | TI_NEW_CHILD != offsetof(struct thread_info, new_child) || | 2690 | TI_NEW_CHILD != offsetof(struct thread_info, new_child) || |
2691 | TI_SYS_NOERROR != offsetof(struct thread_info, | 2691 | TI_CURRENT_DS != offsetof(struct thread_info, |
2692 | syscall_noerror) || | 2692 | current_ds) || |
2693 | TI_RESTART_BLOCK != offsetof(struct thread_info, | 2693 | TI_RESTART_BLOCK != offsetof(struct thread_info, |
2694 | restart_block) || | 2694 | restart_block) || |
2695 | TI_KUNA_REGS != offsetof(struct thread_info, | 2695 | TI_KUNA_REGS != offsetof(struct thread_info, |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 9e28a118e6a4..85be1ca539b2 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void) | |||
624 | void prom_world(int enter) | 624 | void prom_world(int enter) |
625 | { | 625 | { |
626 | if (!enter) | 626 | if (!enter) |
627 | set_fs((mm_segment_t) { get_thread_current_ds() }); | 627 | set_fs(get_fs()); |
628 | 628 | ||
629 | __asm__ __volatile__("flushw"); | 629 | __asm__ __volatile__("flushw"); |
630 | } | 630 | } |
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 875d008828b8..ea7f61e8bc9e 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -21,6 +21,8 @@ config TILE | |||
21 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 21 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
22 | select GENERIC_CLOCKEVENTS | 22 | select GENERIC_CLOCKEVENTS |
23 | select MODULES_USE_ELF_RELA | 23 | select MODULES_USE_ELF_RELA |
24 | select GENERIC_KERNEL_THREAD | ||
25 | select GENERIC_KERNEL_EXECVE | ||
24 | 26 | ||
25 | # FIXME: investigate whether we need/want these options. | 27 | # FIXME: investigate whether we need/want these options. |
26 | # select HAVE_IOREMAP_PROT | 28 | # select HAVE_IOREMAP_PROT |
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 3063e6fc8daa..ca61fb4296b3 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
@@ -275,18 +275,14 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
275 | struct compat_sigaction; | 275 | struct compat_sigaction; |
276 | struct compat_siginfo; | 276 | struct compat_siginfo; |
277 | struct compat_sigaltstack; | 277 | struct compat_sigaltstack; |
278 | long compat_sys_execve(const char __user *path, | ||
279 | compat_uptr_t __user *argv, | ||
280 | compat_uptr_t __user *envp, struct pt_regs *); | ||
281 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, | 278 | long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, |
282 | struct compat_sigaction __user *oact, | 279 | struct compat_sigaction __user *oact, |
283 | size_t sigsetsize); | 280 | size_t sigsetsize); |
284 | long compat_sys_rt_sigqueueinfo(int pid, int sig, | 281 | long compat_sys_rt_sigqueueinfo(int pid, int sig, |
285 | struct compat_siginfo __user *uinfo); | 282 | struct compat_siginfo __user *uinfo); |
286 | long compat_sys_rt_sigreturn(struct pt_regs *); | 283 | long compat_sys_rt_sigreturn(void); |
287 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 284 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
288 | struct compat_sigaltstack __user *uoss_ptr, | 285 | struct compat_sigaltstack __user *uoss_ptr); |
289 | struct pt_regs *); | ||
290 | long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); | 286 | long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); |
291 | long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); | 287 | long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); |
292 | long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, | 288 | long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, |
@@ -303,12 +299,7 @@ long compat_sys_fallocate(int fd, int mode, | |||
303 | long compat_sys_sched_rr_get_interval(compat_pid_t pid, | 299 | long compat_sys_sched_rr_get_interval(compat_pid_t pid, |
304 | struct compat_timespec __user *interval); | 300 | struct compat_timespec __user *interval); |
305 | 301 | ||
306 | /* These are the intvec_64.S trampolines. */ | 302 | /* Assembly trampoline to avoid clobbering r0. */ |
307 | long _compat_sys_execve(const char __user *path, | ||
308 | const compat_uptr_t __user *argv, | ||
309 | const compat_uptr_t __user *envp); | ||
310 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | ||
311 | struct compat_sigaltstack __user *uoss_ptr); | ||
312 | long _compat_sys_rt_sigreturn(void); | 303 | long _compat_sys_rt_sigreturn(void); |
313 | 304 | ||
314 | #endif /* _ASM_TILE_COMPAT_H */ | 305 | #endif /* _ASM_TILE_COMPAT_H */ |
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h index f8ccf08f6934..b73e1039c911 100644 --- a/arch/tile/include/asm/elf.h +++ b/arch/tile/include/asm/elf.h | |||
@@ -148,6 +148,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
148 | #define compat_start_thread(regs, ip, usp) do { \ | 148 | #define compat_start_thread(regs, ip, usp) do { \ |
149 | regs->pc = ptr_to_compat_reg((void *)(ip)); \ | 149 | regs->pc = ptr_to_compat_reg((void *)(ip)); \ |
150 | regs->sp = ptr_to_compat_reg((void *)(usp)); \ | 150 | regs->sp = ptr_to_compat_reg((void *)(usp)); \ |
151 | single_step_execve(); \ | ||
151 | } while (0) | 152 | } while (0) |
152 | 153 | ||
153 | /* | 154 | /* |
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index 8c4dd9ff91eb..2b70dfb1442e 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
@@ -211,6 +211,7 @@ static inline void start_thread(struct pt_regs *regs, | |||
211 | { | 211 | { |
212 | regs->pc = pc; | 212 | regs->pc = pc; |
213 | regs->sp = usp; | 213 | regs->sp = usp; |
214 | single_step_execve(); | ||
214 | } | 215 | } |
215 | 216 | ||
216 | /* Free all resources held by a thread. */ | 217 | /* Free all resources held by a thread. */ |
@@ -219,8 +220,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
219 | /* Nothing for now */ | 220 | /* Nothing for now */ |
220 | } | 221 | } |
221 | 222 | ||
222 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
223 | |||
224 | extern int do_work_pending(struct pt_regs *regs, u32 flags); | 223 | extern int do_work_pending(struct pt_regs *regs, u32 flags); |
225 | 224 | ||
226 | 225 | ||
@@ -239,6 +238,9 @@ unsigned long get_wchan(struct task_struct *p); | |||
239 | #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) | 238 | #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) |
240 | #define task_pt_regs(task) \ | 239 | #define task_pt_regs(task) \ |
241 | ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) | 240 | ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) |
241 | #define current_pt_regs() \ | ||
242 | ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ | ||
243 | (KSTK_PTREGS_GAP - 1)) - 1) | ||
242 | #define task_sp(task) (task_pt_regs(task)->sp) | 244 | #define task_sp(task) (task_pt_regs(task)->sp) |
243 | #define task_pc(task) (task_pt_regs(task)->pc) | 245 | #define task_pc(task) (task_pt_regs(task)->pc) |
244 | /* Aliases for pc and sp (used in fs/proc/array.c) */ | 246 | /* Aliases for pc and sp (used in fs/proc/array.c) */ |
diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h index 1d48c5fee8b7..b8f888cbe6b0 100644 --- a/arch/tile/include/asm/switch_to.h +++ b/arch/tile/include/asm/switch_to.h | |||
@@ -68,7 +68,10 @@ extern unsigned long get_switch_to_pc(void); | |||
68 | /* Support function for forking a new task. */ | 68 | /* Support function for forking a new task. */ |
69 | void ret_from_fork(void); | 69 | void ret_from_fork(void); |
70 | 70 | ||
71 | /* Called from ret_from_fork() when a new process starts up. */ | 71 | /* Support function for forking a new kernel thread. */ |
72 | void ret_from_kernel_thread(void *fn, void *arg); | ||
73 | |||
74 | /* Called from ret_from_xxx() when a new process starts up. */ | ||
72 | struct task_struct *sim_notify_fork(struct task_struct *prev); | 75 | struct task_struct *sim_notify_fork(struct task_struct *prev); |
73 | 76 | ||
74 | #endif /* !__ASSEMBLY__ */ | 77 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index 06f0464cfed9..4c8462a62cb6 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h | |||
@@ -51,8 +51,7 @@ long sys_cacheflush(unsigned long addr, unsigned long len, | |||
51 | 51 | ||
52 | #ifndef __tilegx__ | 52 | #ifndef __tilegx__ |
53 | /* mm/fault.c */ | 53 | /* mm/fault.c */ |
54 | long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); | 54 | long sys_cmpxchg_badaddr(unsigned long address); |
55 | long _sys_cmpxchg_badaddr(unsigned long address); | ||
56 | #endif | 55 | #endif |
57 | 56 | ||
58 | #ifdef CONFIG_COMPAT | 57 | #ifdef CONFIG_COMPAT |
@@ -63,14 +62,16 @@ long sys_truncate64(const char __user *path, loff_t length); | |||
63 | long sys_ftruncate64(unsigned int fd, loff_t length); | 62 | long sys_ftruncate64(unsigned int fd, loff_t length); |
64 | #endif | 63 | #endif |
65 | 64 | ||
65 | /* Provide versions of standard syscalls that use current_pt_regs(). */ | ||
66 | long sys_rt_sigreturn(void); | ||
67 | long sys_sigaltstack(const stack_t __user *, stack_t __user *); | ||
68 | #define sys_rt_sigreturn sys_rt_sigreturn | ||
69 | #define sys_sigaltstack sys_sigaltstack | ||
70 | |||
66 | /* These are the intvec*.S trampolines. */ | 71 | /* These are the intvec*.S trampolines. */ |
67 | long _sys_sigaltstack(const stack_t __user *, stack_t __user *); | ||
68 | long _sys_rt_sigreturn(void); | 72 | long _sys_rt_sigreturn(void); |
69 | long _sys_clone(unsigned long clone_flags, unsigned long newsp, | 73 | long _sys_clone(unsigned long clone_flags, unsigned long newsp, |
70 | void __user *parent_tid, void __user *child_tid); | 74 | void __user *parent_tid, void __user *child_tid); |
71 | long _sys_execve(const char __user *filename, | ||
72 | const char __user *const __user *argv, | ||
73 | const char __user *const __user *envp); | ||
74 | 75 | ||
75 | #include <asm-generic/syscalls.h> | 76 | #include <asm-generic/syscalls.h> |
76 | 77 | ||
diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h index 6e032a0a268e..b51c6ee3cd6c 100644 --- a/arch/tile/include/asm/unistd.h +++ b/arch/tile/include/asm/unistd.h | |||
@@ -16,4 +16,6 @@ | |||
16 | #define __ARCH_WANT_SYS_LLSEEK | 16 | #define __ARCH_WANT_SYS_LLSEEK |
17 | #endif | 17 | #endif |
18 | #define __ARCH_WANT_SYS_NEWFSTATAT | 18 | #define __ARCH_WANT_SYS_NEWFSTATAT |
19 | #define __ARCH_WANT_SYS_EXECVE | ||
20 | #define __ARCH_WANT_SYS_CLONE | ||
19 | #include <uapi/asm/unistd.h> | 21 | #include <uapi/asm/unistd.h> |
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index d67459b9ac2a..9cd7cb6041c0 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c | |||
@@ -102,9 +102,7 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid, | |||
102 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 | 102 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 |
103 | #define compat_sys_readahead sys32_readahead | 103 | #define compat_sys_readahead sys32_readahead |
104 | 104 | ||
105 | /* Call the trampolines to manage pt_regs where necessary. */ | 105 | /* Call the assembly trampolines where necessary. */ |
106 | #define compat_sys_execve _compat_sys_execve | ||
107 | #define compat_sys_sigaltstack _compat_sys_sigaltstack | ||
108 | #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn | 106 | #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn |
109 | #define sys_clone _sys_clone | 107 | #define sys_clone _sys_clone |
110 | 108 | ||
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 08b4fe1717bb..2e4cc69224a6 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
@@ -197,8 +197,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 199 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
200 | struct compat_sigaltstack __user *uoss_ptr, | 200 | struct compat_sigaltstack __user *uoss_ptr) |
201 | struct pt_regs *regs) | ||
202 | { | 201 | { |
203 | stack_t uss, uoss; | 202 | stack_t uss, uoss; |
204 | int ret; | 203 | int ret; |
@@ -219,7 +218,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
219 | set_fs(KERNEL_DS); | 218 | set_fs(KERNEL_DS); |
220 | ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, | 219 | ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, |
221 | (stack_t __user __force *)&uoss, | 220 | (stack_t __user __force *)&uoss, |
222 | (unsigned long)compat_ptr(regs->sp)); | 221 | (unsigned long)compat_ptr(current_pt_regs()->sp)); |
223 | set_fs(seg); | 222 | set_fs(seg); |
224 | if (ret >= 0 && uoss_ptr) { | 223 | if (ret >= 0 && uoss_ptr) { |
225 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || | 224 | if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || |
@@ -232,8 +231,9 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
232 | } | 231 | } |
233 | 232 | ||
234 | /* The assembly shim for this function arranges to ignore the return value. */ | 233 | /* The assembly shim for this function arranges to ignore the return value. */ |
235 | long compat_sys_rt_sigreturn(struct pt_regs *regs) | 234 | long compat_sys_rt_sigreturn(void) |
236 | { | 235 | { |
236 | struct pt_regs *regs = current_pt_regs(); | ||
237 | struct compat_rt_sigframe __user *frame = | 237 | struct compat_rt_sigframe __user *frame = |
238 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); | 238 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); |
239 | sigset_t set; | 239 | sigset_t set; |
@@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) | |||
248 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 248 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
249 | goto badframe; | 249 | goto badframe; |
250 | 250 | ||
251 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) | 251 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT) |
252 | goto badframe; | 252 | goto badframe; |
253 | 253 | ||
254 | return 0; | 254 | return 0; |
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index c31637baff28..f116cb0bce20 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S | |||
@@ -28,17 +28,6 @@ STD_ENTRY(current_text_addr) | |||
28 | STD_ENDPROC(current_text_addr) | 28 | STD_ENDPROC(current_text_addr) |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Implement execve(). The i386 code has a note that forking from kernel | ||
32 | * space results in no copy on write until the execve, so we should be | ||
33 | * careful not to write to the stack here. | ||
34 | */ | ||
35 | STD_ENTRY(kernel_execve) | ||
36 | moveli TREG_SYSCALL_NR_NAME, __NR_execve | ||
37 | swint1 | ||
38 | jrp lr | ||
39 | STD_ENDPROC(kernel_execve) | ||
40 | |||
41 | /* | ||
42 | * We don't run this function directly, but instead copy it to a page | 31 | * We don't run this function directly, but instead copy it to a page |
43 | * we map into every user process. See vdso_setup(). | 32 | * we map into every user process. See vdso_setup(). |
44 | * | 33 | * |
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 6943515100f8..f212bf7cea86 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
@@ -1291,6 +1291,21 @@ STD_ENTRY(ret_from_fork) | |||
1291 | } | 1291 | } |
1292 | STD_ENDPROC(ret_from_fork) | 1292 | STD_ENDPROC(ret_from_fork) |
1293 | 1293 | ||
1294 | STD_ENTRY(ret_from_kernel_thread) | ||
1295 | jal sim_notify_fork | ||
1296 | jal schedule_tail | ||
1297 | FEEDBACK_REENTER(ret_from_fork) | ||
1298 | { | ||
1299 | move r0, r31 | ||
1300 | jalr r30 | ||
1301 | } | ||
1302 | FEEDBACK_REENTER(ret_from_kernel_thread) | ||
1303 | { | ||
1304 | movei r30, 0 /* not an NMI */ | ||
1305 | j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
1306 | } | ||
1307 | STD_ENDPROC(ret_from_kernel_thread) | ||
1308 | |||
1294 | /* | 1309 | /* |
1295 | * Code for ill interrupt. | 1310 | * Code for ill interrupt. |
1296 | */ | 1311 | */ |
@@ -1437,15 +1452,6 @@ STD_ENTRY_LOCAL(bad_intr) | |||
1437 | panic "Unhandled interrupt %#x: PC %#lx" | 1452 | panic "Unhandled interrupt %#x: PC %#lx" |
1438 | STD_ENDPROC(bad_intr) | 1453 | STD_ENDPROC(bad_intr) |
1439 | 1454 | ||
1440 | /* Put address of pt_regs in reg and jump. */ | ||
1441 | #define PTREGS_SYSCALL(x, reg) \ | ||
1442 | STD_ENTRY(_##x); \ | ||
1443 | { \ | ||
1444 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1445 | j x \ | ||
1446 | }; \ | ||
1447 | STD_ENDPROC(_##x) | ||
1448 | |||
1449 | /* | 1455 | /* |
1450 | * Special-case sigreturn to not write r0 to the stack on return. | 1456 | * Special-case sigreturn to not write r0 to the stack on return. |
1451 | * This is technically more efficient, but it also avoids difficulties | 1457 | * This is technically more efficient, but it also avoids difficulties |
@@ -1461,12 +1467,9 @@ STD_ENTRY_LOCAL(bad_intr) | |||
1461 | }; \ | 1467 | }; \ |
1462 | STD_ENDPROC(_##x) | 1468 | STD_ENDPROC(_##x) |
1463 | 1469 | ||
1464 | PTREGS_SYSCALL(sys_execve, r3) | ||
1465 | PTREGS_SYSCALL(sys_sigaltstack, r2) | ||
1466 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) | 1470 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
1467 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) | ||
1468 | 1471 | ||
1469 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1472 | /* Save additional callee-saves to pt_regs and jump to standard function. */ |
1470 | STD_ENTRY(_sys_clone) | 1473 | STD_ENTRY(_sys_clone) |
1471 | push_extra_callee_saves r4 | 1474 | push_extra_callee_saves r4 |
1472 | j sys_clone | 1475 | j sys_clone |
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 7c06d597ffd0..54bc9a6678e8 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S | |||
@@ -1150,6 +1150,21 @@ STD_ENTRY(ret_from_fork) | |||
1150 | } | 1150 | } |
1151 | STD_ENDPROC(ret_from_fork) | 1151 | STD_ENDPROC(ret_from_fork) |
1152 | 1152 | ||
1153 | STD_ENTRY(ret_from_kernel_thread) | ||
1154 | jal sim_notify_fork | ||
1155 | jal schedule_tail | ||
1156 | FEEDBACK_REENTER(ret_from_fork) | ||
1157 | { | ||
1158 | move r0, r31 | ||
1159 | jalr r30 | ||
1160 | } | ||
1161 | FEEDBACK_REENTER(ret_from_kernel_thread) | ||
1162 | { | ||
1163 | movei r30, 0 /* not an NMI */ | ||
1164 | j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
1165 | } | ||
1166 | STD_ENDPROC(ret_from_kernel_thread) | ||
1167 | |||
1153 | /* Various stub interrupt handlers and syscall handlers */ | 1168 | /* Various stub interrupt handlers and syscall handlers */ |
1154 | 1169 | ||
1155 | STD_ENTRY_LOCAL(_kernel_double_fault) | 1170 | STD_ENTRY_LOCAL(_kernel_double_fault) |
@@ -1166,15 +1181,6 @@ STD_ENTRY_LOCAL(bad_intr) | |||
1166 | panic "Unhandled interrupt %#x: PC %#lx" | 1181 | panic "Unhandled interrupt %#x: PC %#lx" |
1167 | STD_ENDPROC(bad_intr) | 1182 | STD_ENDPROC(bad_intr) |
1168 | 1183 | ||
1169 | /* Put address of pt_regs in reg and jump. */ | ||
1170 | #define PTREGS_SYSCALL(x, reg) \ | ||
1171 | STD_ENTRY(_##x); \ | ||
1172 | { \ | ||
1173 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1174 | j x \ | ||
1175 | }; \ | ||
1176 | STD_ENDPROC(_##x) | ||
1177 | |||
1178 | /* | 1184 | /* |
1179 | * Special-case sigreturn to not write r0 to the stack on return. | 1185 | * Special-case sigreturn to not write r0 to the stack on return. |
1180 | * This is technically more efficient, but it also avoids difficulties | 1186 | * This is technically more efficient, but it also avoids difficulties |
@@ -1190,16 +1196,12 @@ STD_ENTRY_LOCAL(bad_intr) | |||
1190 | }; \ | 1196 | }; \ |
1191 | STD_ENDPROC(_##x) | 1197 | STD_ENDPROC(_##x) |
1192 | 1198 | ||
1193 | PTREGS_SYSCALL(sys_execve, r3) | ||
1194 | PTREGS_SYSCALL(sys_sigaltstack, r2) | ||
1195 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) | 1199 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
1196 | #ifdef CONFIG_COMPAT | 1200 | #ifdef CONFIG_COMPAT |
1197 | PTREGS_SYSCALL(compat_sys_execve, r3) | ||
1198 | PTREGS_SYSCALL(compat_sys_sigaltstack, r2) | ||
1199 | PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) | 1201 | PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) |
1200 | #endif | 1202 | #endif |
1201 | 1203 | ||
1202 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | 1204 | /* Save additional callee-saves to pt_regs and jump to standard function. */ |
1203 | STD_ENTRY(_sys_clone) | 1205 | STD_ENTRY(_sys_clone) |
1204 | push_extra_callee_saves r4 | 1206 | push_extra_callee_saves r4 |
1205 | j sys_clone | 1207 | j sys_clone |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 307d010696c9..0e5661e7d00d 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -157,24 +157,43 @@ void arch_release_thread_info(struct thread_info *info) | |||
157 | static void save_arch_state(struct thread_struct *t); | 157 | static void save_arch_state(struct thread_struct *t); |
158 | 158 | ||
159 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 159 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
160 | unsigned long stack_size, | 160 | unsigned long arg, struct task_struct *p) |
161 | struct task_struct *p, struct pt_regs *regs) | ||
162 | { | 161 | { |
163 | struct pt_regs *childregs; | 162 | struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs(); |
164 | unsigned long ksp; | 163 | unsigned long ksp; |
164 | unsigned long *callee_regs; | ||
165 | 165 | ||
166 | /* | 166 | /* |
167 | * When creating a new kernel thread we pass sp as zero. | 167 | * Set up the stack and stack pointer appropriately for the |
168 | * Assign it to a reasonable value now that we have the stack. | 168 | * new child to find itself woken up in __switch_to(). |
169 | * The callee-saved registers must be on the stack to be read; | ||
170 | * the new task will then jump to assembly support to handle | ||
171 | * calling schedule_tail(), etc., and (for userspace tasks) | ||
172 | * returning to the context set up in the pt_regs. | ||
169 | */ | 173 | */ |
170 | if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) | 174 | ksp = (unsigned long) childregs; |
171 | sp = KSTK_TOP(p); | 175 | ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ |
176 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
177 | ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); | ||
178 | callee_regs = (unsigned long *)ksp; | ||
179 | ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ | ||
180 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
181 | p->thread.ksp = ksp; | ||
172 | 182 | ||
173 | /* | 183 | /* Record the pid of the task that created this one. */ |
174 | * Do not clone step state from the parent; each thread | 184 | p->thread.creator_pid = current->pid; |
175 | * must make its own lazily. | 185 | |
176 | */ | 186 | if (unlikely(p->flags & PF_KTHREAD)) { |
177 | task_thread_info(p)->step_state = NULL; | 187 | /* kernel thread */ |
188 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
189 | memset(&callee_regs[2], 0, | ||
190 | (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long)); | ||
191 | callee_regs[0] = sp; /* r30 = function */ | ||
192 | callee_regs[1] = arg; /* r31 = arg */ | ||
193 | childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); | ||
194 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | ||
195 | return 0; | ||
196 | } | ||
178 | 197 | ||
179 | /* | 198 | /* |
180 | * Start new thread in ret_from_fork so it schedules properly | 199 | * Start new thread in ret_from_fork so it schedules properly |
@@ -182,46 +201,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
182 | */ | 201 | */ |
183 | p->thread.pc = (unsigned long) ret_from_fork; | 202 | p->thread.pc = (unsigned long) ret_from_fork; |
184 | 203 | ||
185 | /* Save user stack top pointer so we can ID the stack vm area later. */ | 204 | /* |
186 | p->thread.usp0 = sp; | 205 | * Do not clone step state from the parent; each thread |
187 | 206 | * must make its own lazily. | |
188 | /* Record the pid of the process that created this one. */ | 207 | */ |
189 | p->thread.creator_pid = current->pid; | 208 | task_thread_info(p)->step_state = NULL; |
190 | 209 | ||
191 | /* | 210 | /* |
192 | * Copy the registers onto the kernel stack so the | 211 | * Copy the registers onto the kernel stack so the |
193 | * return-from-interrupt code will reload it into registers. | 212 | * return-from-interrupt code will reload it into registers. |
194 | */ | 213 | */ |
195 | childregs = task_pt_regs(p); | 214 | *childregs = *current_pt_regs(); |
196 | *childregs = *regs; | ||
197 | childregs->regs[0] = 0; /* return value is zero */ | 215 | childregs->regs[0] = 0; /* return value is zero */ |
198 | childregs->sp = sp; /* override with new user stack pointer */ | 216 | if (sp) |
217 | childregs->sp = sp; /* override with new user stack pointer */ | ||
218 | memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], | ||
219 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); | ||
220 | |||
221 | /* Save user stack top pointer so we can ID the stack vm area later. */ | ||
222 | p->thread.usp0 = childregs->sp; | ||
199 | 223 | ||
200 | /* | 224 | /* |
201 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", | 225 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", |
202 | * which is passed in as arg #5 to sys_clone(). | 226 | * which is passed in as arg #5 to sys_clone(). |
203 | */ | 227 | */ |
204 | if (clone_flags & CLONE_SETTLS) | 228 | if (clone_flags & CLONE_SETTLS) |
205 | childregs->tp = regs->regs[4]; | 229 | childregs->tp = childregs->regs[4]; |
206 | 230 | ||
207 | /* | ||
208 | * Copy the callee-saved registers from the passed pt_regs struct | ||
209 | * into the context-switch callee-saved registers area. | ||
210 | * This way when we start the interrupt-return sequence, the | ||
211 | * callee-save registers will be correctly in registers, which | ||
212 | * is how we assume the compiler leaves them as we start doing | ||
213 | * the normal return-from-interrupt path after calling C code. | ||
214 | * Zero out the C ABI save area to mark the top of the stack. | ||
215 | */ | ||
216 | ksp = (unsigned long) childregs; | ||
217 | ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ | ||
218 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
219 | ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); | ||
220 | memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG], | ||
221 | CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); | ||
222 | ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ | ||
223 | ((long *)ksp)[0] = ((long *)ksp)[1] = 0; | ||
224 | p->thread.ksp = ksp; | ||
225 | 231 | ||
226 | #if CHIP_HAS_TILE_DMA() | 232 | #if CHIP_HAS_TILE_DMA() |
227 | /* | 233 | /* |
@@ -577,62 +583,6 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
577 | panic("work_pending: bad flags %#x\n", thread_info_flags); | 583 | panic("work_pending: bad flags %#x\n", thread_info_flags); |
578 | } | 584 | } |
579 | 585 | ||
580 | /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ | ||
581 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | ||
582 | void __user *, parent_tidptr, void __user *, child_tidptr, | ||
583 | struct pt_regs *, regs) | ||
584 | { | ||
585 | if (!newsp) | ||
586 | newsp = regs->sp; | ||
587 | return do_fork(clone_flags, newsp, regs, 0, | ||
588 | parent_tidptr, child_tidptr); | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * sys_execve() executes a new program. | ||
593 | */ | ||
594 | SYSCALL_DEFINE4(execve, const char __user *, path, | ||
595 | const char __user *const __user *, argv, | ||
596 | const char __user *const __user *, envp, | ||
597 | struct pt_regs *, regs) | ||
598 | { | ||
599 | long error; | ||
600 | struct filename *filename; | ||
601 | |||
602 | filename = getname(path); | ||
603 | error = PTR_ERR(filename); | ||
604 | if (IS_ERR(filename)) | ||
605 | goto out; | ||
606 | error = do_execve(filename->name, argv, envp, regs); | ||
607 | putname(filename); | ||
608 | if (error == 0) | ||
609 | single_step_execve(); | ||
610 | out: | ||
611 | return error; | ||
612 | } | ||
613 | |||
614 | #ifdef CONFIG_COMPAT | ||
615 | long compat_sys_execve(const char __user *path, | ||
616 | compat_uptr_t __user *argv, | ||
617 | compat_uptr_t __user *envp, | ||
618 | struct pt_regs *regs) | ||
619 | { | ||
620 | long error; | ||
621 | struct filename *filename; | ||
622 | |||
623 | filename = getname(path); | ||
624 | error = PTR_ERR(filename); | ||
625 | if (IS_ERR(filename)) | ||
626 | goto out; | ||
627 | error = compat_do_execve(filename->name, argv, envp, regs); | ||
628 | putname(filename); | ||
629 | if (error == 0) | ||
630 | single_step_execve(); | ||
631 | out: | ||
632 | return error; | ||
633 | } | ||
634 | #endif | ||
635 | |||
636 | unsigned long get_wchan(struct task_struct *p) | 586 | unsigned long get_wchan(struct task_struct *p) |
637 | { | 587 | { |
638 | struct KBacktraceIterator kbt; | 588 | struct KBacktraceIterator kbt; |
@@ -650,37 +600,6 @@ unsigned long get_wchan(struct task_struct *p) | |||
650 | return 0; | 600 | return 0; |
651 | } | 601 | } |
652 | 602 | ||
653 | /* | ||
654 | * We pass in lr as zero (cleared in kernel_thread) and the caller | ||
655 | * part of the backtrace ABI on the stack also zeroed (in copy_thread) | ||
656 | * so that backtraces will stop with this function. | ||
657 | * Note that we don't use r0, since copy_thread() clears it. | ||
658 | */ | ||
659 | static void start_kernel_thread(int dummy, int (*fn)(int), int arg) | ||
660 | { | ||
661 | do_exit(fn(arg)); | ||
662 | } | ||
663 | |||
664 | /* | ||
665 | * Create a kernel thread | ||
666 | */ | ||
667 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
668 | { | ||
669 | struct pt_regs regs; | ||
670 | |||
671 | memset(®s, 0, sizeof(regs)); | ||
672 | regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ | ||
673 | regs.pc = (long) start_kernel_thread; | ||
674 | regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ | ||
675 | regs.regs[1] = (long) fn; /* function pointer */ | ||
676 | regs.regs[2] = (long) arg; /* parameter register */ | ||
677 | |||
678 | /* Ok, create the new process.. */ | ||
679 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, | ||
680 | 0, NULL, NULL); | ||
681 | } | ||
682 | EXPORT_SYMBOL(kernel_thread); | ||
683 | |||
684 | /* Flush thread state. */ | 603 | /* Flush thread state. */ |
685 | void flush_thread(void) | 604 | void flush_thread(void) |
686 | { | 605 | { |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 67efb656d104..657a7ace4ab4 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
@@ -37,10 +37,10 @@ | |||
37 | 37 | ||
38 | #define DEBUG_SIG 0 | 38 | #define DEBUG_SIG 0 |
39 | 39 | ||
40 | SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, | 40 | SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss, |
41 | stack_t __user *, uoss, struct pt_regs *, regs) | 41 | stack_t __user *, uoss) |
42 | { | 42 | { |
43 | return do_sigaltstack(uss, uoss, regs->sp); | 43 | return do_sigaltstack(uss, uoss, current_pt_regs()->sp); |
44 | } | 44 | } |
45 | 45 | ||
46 | 46 | ||
@@ -83,8 +83,9 @@ void signal_fault(const char *type, struct pt_regs *regs, | |||
83 | } | 83 | } |
84 | 84 | ||
85 | /* The assembly shim for this function arranges to ignore the return value. */ | 85 | /* The assembly shim for this function arranges to ignore the return value. */ |
86 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | 86 | SYSCALL_DEFINE0(rt_sigreturn) |
87 | { | 87 | { |
88 | struct pt_regs *regs = current_pt_regs(); | ||
88 | struct rt_sigframe __user *frame = | 89 | struct rt_sigframe __user *frame = |
89 | (struct rt_sigframe __user *)(regs->sp); | 90 | (struct rt_sigframe __user *)(regs->sp); |
90 | sigset_t set; | 91 | sigset_t set; |
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c index b08095b402d6..b881a7be24bd 100644 --- a/arch/tile/kernel/sys.c +++ b/arch/tile/kernel/sys.c | |||
@@ -106,14 +106,10 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, | |||
106 | #define sys_readahead sys32_readahead | 106 | #define sys_readahead sys32_readahead |
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | /* Call the trampolines to manage pt_regs where necessary. */ | 109 | /* Call the assembly trampolines where necessary. */ |
110 | #define sys_execve _sys_execve | 110 | #undef sys_rt_sigreturn |
111 | #define sys_sigaltstack _sys_sigaltstack | ||
112 | #define sys_rt_sigreturn _sys_rt_sigreturn | 111 | #define sys_rt_sigreturn _sys_rt_sigreturn |
113 | #define sys_clone _sys_clone | 112 | #define sys_clone _sys_clone |
114 | #ifndef __tilegx__ | ||
115 | #define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr | ||
116 | #endif | ||
117 | 113 | ||
118 | /* | 114 | /* |
119 | * Note that we can't include <linux/unistd.h> here since the header | 115 | * Note that we can't include <linux/unistd.h> here since the header |
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index fe811fa5f1b9..3d2b81c163a6 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
@@ -70,9 +70,10 @@ static noinline void force_sig_info_fault(const char *type, int si_signo, | |||
70 | * Synthesize the fault a PL0 process would get by doing a word-load of | 70 | * Synthesize the fault a PL0 process would get by doing a word-load of |
71 | * an unaligned address or a high kernel address. | 71 | * an unaligned address or a high kernel address. |
72 | */ | 72 | */ |
73 | SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, | 73 | SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address) |
74 | struct pt_regs *, regs) | ||
75 | { | 74 | { |
75 | struct pt_regs *regs = current_pt_regs(); | ||
76 | |||
76 | if (address >= PAGE_OFFSET) | 77 | if (address >= PAGE_OFFSET) |
77 | force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, | 78 | force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, |
78 | address, INT_DTLB_MISS, current, regs); | 79 | address, INT_DTLB_MISS, current, regs); |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index b6d699cdd557..b462b13c5bae 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
@@ -161,8 +161,7 @@ void fork_handler(void) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 163 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
164 | unsigned long arg, struct task_struct * p, | 164 | unsigned long arg, struct task_struct * p) |
165 | struct pt_regs *regs) | ||
166 | { | 165 | { |
167 | void (*handler)(void); | 166 | void (*handler)(void); |
168 | int kthread = current->flags & PF_KTHREAD; | 167 | int kthread = current->flags & PF_KTHREAD; |
@@ -171,7 +170,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
171 | p->thread = (struct thread_struct) INIT_THREAD; | 170 | p->thread = (struct thread_struct) INIT_THREAD; |
172 | 171 | ||
173 | if (!kthread) { | 172 | if (!kthread) { |
174 | memcpy(&p->thread.regs.regs, ®s->regs, | 173 | memcpy(&p->thread.regs.regs, current_pt_regs(), |
175 | sizeof(p->thread.regs.regs)); | 174 | sizeof(p->thread.regs.regs)); |
176 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); | 175 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); |
177 | if (sp != 0) | 176 | if (sp != 0) |
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index a81f3705e90f..c1d0ae069b53 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c | |||
@@ -14,29 +14,6 @@ | |||
14 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
15 | #include <asm/unistd.h> | 15 | #include <asm/unistd.h> |
16 | 16 | ||
17 | long sys_fork(void) | ||
18 | { | ||
19 | return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | ||
20 | ¤t->thread.regs, 0, NULL, NULL); | ||
21 | } | ||
22 | |||
23 | long sys_vfork(void) | ||
24 | { | ||
25 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | ||
26 | UPT_SP(¤t->thread.regs.regs), | ||
27 | ¤t->thread.regs, 0, NULL, NULL); | ||
28 | } | ||
29 | |||
30 | long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
31 | void __user *parent_tid, void __user *child_tid) | ||
32 | { | ||
33 | if (!newsp) | ||
34 | newsp = UPT_SP(¤t->thread.regs.regs); | ||
35 | |||
36 | return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | ||
37 | child_tid); | ||
38 | } | ||
39 | |||
40 | long old_mmap(unsigned long addr, unsigned long len, | 17 | long old_mmap(unsigned long addr, unsigned long len, |
41 | unsigned long prot, unsigned long flags, | 18 | unsigned long prot, unsigned long flags, |
42 | unsigned long fd, unsigned long offset) | 19 | unsigned long fd, unsigned long offset) |
diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h index d18a3be89b38..00cf5e286fca 100644 --- a/arch/unicore32/include/uapi/asm/unistd.h +++ b/arch/unicore32/include/uapi/asm/unistd.h | |||
@@ -13,3 +13,4 @@ | |||
13 | /* Use the standard ABI for syscalls. */ | 13 | /* Use the standard ABI for syscalls. */ |
14 | #include <asm-generic/unistd.h> | 14 | #include <asm-generic/unistd.h> |
15 | #define __ARCH_WANT_SYS_EXECVE | 15 | #define __ARCH_WANT_SYS_EXECVE |
16 | #define __ARCH_WANT_SYS_CLONE | ||
diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S index 7049350c790f..581630d91444 100644 --- a/arch/unicore32/kernel/entry.S +++ b/arch/unicore32/kernel/entry.S | |||
@@ -668,12 +668,6 @@ __cr_alignment: | |||
668 | #endif | 668 | #endif |
669 | .ltorg | 669 | .ltorg |
670 | 670 | ||
671 | ENTRY(sys_clone) | ||
672 | add ip, sp, #S_OFF | ||
673 | stw ip, [sp+], #4 | ||
674 | b __sys_clone | ||
675 | ENDPROC(sys_clone) | ||
676 | |||
677 | ENTRY(sys_rt_sigreturn) | 671 | ENTRY(sys_rt_sigreturn) |
678 | add r0, sp, #S_OFF | 672 | add r0, sp, #S_OFF |
679 | mov why, #0 @ prevent syscall restart handling | 673 | mov why, #0 @ prevent syscall restart handling |
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index a8fe265ce2c0..62bad9fed03e 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c | |||
@@ -262,26 +262,27 @@ asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); | |||
262 | 262 | ||
263 | int | 263 | int |
264 | copy_thread(unsigned long clone_flags, unsigned long stack_start, | 264 | copy_thread(unsigned long clone_flags, unsigned long stack_start, |
265 | unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) | 265 | unsigned long stk_sz, struct task_struct *p) |
266 | { | 266 | { |
267 | struct thread_info *thread = task_thread_info(p); | 267 | struct thread_info *thread = task_thread_info(p); |
268 | struct pt_regs *childregs = task_pt_regs(p); | 268 | struct pt_regs *childregs = task_pt_regs(p); |
269 | 269 | ||
270 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); | 270 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); |
271 | thread->cpu_context.sp = (unsigned long)childregs; | 271 | thread->cpu_context.sp = (unsigned long)childregs; |
272 | if (unlikely(!regs)) { | 272 | if (unlikely(p->flags & PF_KTHREAD)) { |
273 | thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; | 273 | thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; |
274 | thread->cpu_context.r4 = stack_start; | 274 | thread->cpu_context.r4 = stack_start; |
275 | thread->cpu_context.r5 = stk_sz; | 275 | thread->cpu_context.r5 = stk_sz; |
276 | memset(childregs, 0, sizeof(struct pt_regs)); | 276 | memset(childregs, 0, sizeof(struct pt_regs)); |
277 | } else { | 277 | } else { |
278 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | 278 | thread->cpu_context.pc = (unsigned long)ret_from_fork; |
279 | *childregs = *regs; | 279 | *childregs = *current_pt_regs(); |
280 | childregs->UCreg_00 = 0; | 280 | childregs->UCreg_00 = 0; |
281 | childregs->UCreg_sp = stack_start; | 281 | if (stack_start) |
282 | childregs->UCreg_sp = stack_start; | ||
282 | 283 | ||
283 | if (clone_flags & CLONE_SETTLS) | 284 | if (clone_flags & CLONE_SETTLS) |
284 | childregs->UCreg_16 = regs->UCreg_03; | 285 | childregs->UCreg_16 = childregs->UCreg_03; |
285 | } | 286 | } |
286 | return 0; | 287 | return 0; |
287 | } | 288 | } |
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index 9680134b31f0..cfe79c9529b3 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c | |||
@@ -28,20 +28,6 @@ | |||
28 | #include <asm/syscalls.h> | 28 | #include <asm/syscalls.h> |
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | 30 | ||
31 | /* Clone a task - this clones the calling program thread. | ||
32 | * This is called indirectly via a small wrapper | ||
33 | */ | ||
34 | asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
35 | void __user *parent_tid, void __user *child_tid, | ||
36 | struct pt_regs *regs) | ||
37 | { | ||
38 | if (!newsp) | ||
39 | newsp = regs->UCreg_sp; | ||
40 | |||
41 | return do_fork(clone_flags, newsp, regs, 0, | ||
42 | parent_tid, child_tid); | ||
43 | } | ||
44 | |||
45 | /* Note: used by the compat code even in 64-bit Linux. */ | 31 | /* Note: used by the compat code even in 64-bit Linux. */ |
46 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, | 32 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, |
47 | unsigned long, prot, unsigned long, flags, | 33 | unsigned long, prot, unsigned long, flags, |
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 | ||
116 | config INSTRUCTION_DECODER | 117 | config 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 | ||
38 | static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); | 38 | static int load_aout_binary(struct linux_binprm *); |
39 | static int load_aout_library(struct file *); | 39 | static 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 | */ |
263 | static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | 263 | static 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 |
474 | GLOBAL(stub32_clone) | ||
475 | leaq sys_clone(%rip),%rax | ||
476 | mov %r8, %rcx | ||
477 | jmp ia32_ptregs_common | ||
478 | |||
479 | ALIGN | ||
475 | ia32_ptregs_common: | 480 | ia32_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 | ||
388 | asmlinkage 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 | ||
179 | extern void cpu_detect(struct cpuinfo_x86 *c); | 179 | extern void cpu_detect(struct cpuinfo_x86 *c); |
180 | 180 | ||
181 | extern struct pt_regs *idle_regs(struct pt_regs *); | ||
182 | |||
183 | extern void early_cpu_init(void); | 181 | extern void early_cpu_init(void); |
184 | extern void identify_boot_cpu(void); | 182 | extern void identify_boot_cpu(void); |
185 | extern void identify_secondary_cpu(struct cpuinfo_x86 *); | 183 | extern 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); | |||
54 | asmlinkage long sys32_personality(unsigned long); | 54 | asmlinkage long sys32_personality(unsigned long); |
55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); | 55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); |
56 | 56 | ||
57 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); | ||
58 | |||
59 | long sys32_lseek(unsigned int, int, unsigned int); | 57 | long sys32_lseek(unsigned int, int, unsigned int); |
60 | long sys32_kill(int, int); | 58 | long sys32_kill(int, int); |
61 | long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int); | 59 | long 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 @@ | |||
20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); | 20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); |
21 | long sys_iopl(unsigned int, struct pt_regs *); | 21 | long sys_iopl(unsigned int, struct pt_regs *); |
22 | 22 | ||
23 | /* kernel/process.c */ | ||
24 | int sys_fork(struct pt_regs *); | ||
25 | int sys_vfork(struct pt_regs *); | ||
26 | long sys_execve(const char __user *, | ||
27 | const char __user *const __user *, | ||
28 | const char __user *const __user *); | ||
29 | long sys_clone(unsigned long, unsigned long, void __user *, | ||
30 | void __user *, struct pt_regs *); | ||
31 | |||
32 | /* kernel/ldt.c */ | 23 | /* kernel/ldt.c */ |
33 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); | 24 | asmlinkage 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); | |||
1173 | DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); | 1173 | DEFINE_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 */ | ||
1177 | struct 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) ; \ | |||
739 | ENDPROC(ptregs_##name) | 739 | ENDPROC(ptregs_##name) |
740 | 740 | ||
741 | PTREGSCALL1(iopl) | 741 | PTREGSCALL1(iopl) |
742 | PTREGSCALL0(fork) | ||
743 | PTREGSCALL0(vfork) | ||
744 | PTREGSCALL2(sigaltstack) | 742 | PTREGSCALL2(sigaltstack) |
745 | PTREGSCALL0(sigreturn) | 743 | PTREGSCALL0(sigreturn) |
746 | PTREGSCALL0(rt_sigreturn) | 744 | PTREGSCALL0(rt_sigreturn) |
747 | PTREGSCALL2(vm86) | 745 | PTREGSCALL2(vm86) |
748 | PTREGSCALL1(vm86old) | 746 | PTREGSCALL1(vm86old) |
749 | 747 | ||
750 | /* Clone is an oddball. The 4th arg is in %edi */ | ||
751 | ENTRY(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 | ||
764 | ENDPROC(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) | |||
845 | END(\label) | 845 | END(\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 | 849 | ENTRY(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 | ||
861 | END(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 | ||
265 | int 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 | */ | ||
280 | int 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 | |||
286 | long | ||
287 | sys_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 | ||
130 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 130 | int 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 | ||
148 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
149 | unsigned long 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 | # |
9 | 0 i386 restart_syscall sys_restart_syscall | 9 | 0 i386 restart_syscall sys_restart_syscall |
10 | 1 i386 exit sys_exit | 10 | 1 i386 exit sys_exit |
11 | 2 i386 fork ptregs_fork stub32_fork | 11 | 2 i386 fork sys_fork stub32_fork |
12 | 3 i386 read sys_read | 12 | 3 i386 read sys_read |
13 | 4 i386 write sys_write | 13 | 4 i386 write sys_write |
14 | 5 i386 open sys_open compat_sys_open | 14 | 5 i386 open sys_open compat_sys_open |
@@ -126,7 +126,7 @@ | |||
126 | 117 i386 ipc sys_ipc sys32_ipc | 126 | 117 i386 ipc sys_ipc sys32_ipc |
127 | 118 i386 fsync sys_fsync | 127 | 118 i386 fsync sys_fsync |
128 | 119 i386 sigreturn ptregs_sigreturn stub32_sigreturn | 128 | 119 i386 sigreturn ptregs_sigreturn stub32_sigreturn |
129 | 120 i386 clone ptregs_clone stub32_clone | 129 | 120 i386 clone sys_clone stub32_clone |
130 | 121 i386 setdomainname sys_setdomainname | 130 | 121 i386 setdomainname sys_setdomainname |
131 | 122 i386 uname sys_newuname | 131 | 122 i386 uname sys_newuname |
132 | 123 i386 modify_ldt sys_modify_ldt | 132 | 123 i386 modify_ldt sys_modify_ldt |
@@ -196,7 +196,7 @@ | |||
196 | 187 i386 sendfile sys_sendfile sys32_sendfile | 196 | 187 i386 sendfile sys_sendfile sys32_sendfile |
197 | 188 i386 getpmsg | 197 | 188 i386 getpmsg |
198 | 189 i386 putpmsg | 198 | 189 i386 putpmsg |
199 | 190 i386 vfork ptregs_vfork stub32_vfork | 199 | 190 i386 vfork sys_vfork stub32_vfork |
200 | 191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit | 200 | 191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit |
201 | 192 i386 mmap2 sys_mmap_pgoff | 201 | 192 i386 mmap2 sys_mmap_pgoff |
202 | 193 i386 truncate64 sys_truncate64 sys32_truncate64 | 202 | 193 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 | ||
29 | config X86_64 | 30 | config 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 @@ | |||
1 | extern 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 | */ | ||
17 | long 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 | |||
24 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 9 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
25 | struct old_sigaction __user *oact) | 10 | struct old_sigaction __user *oact) |
26 | { | 11 | { |
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 0d1f36a22c98..2481f267be29 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -16,6 +16,7 @@ config XTENSA | |||
16 | select GENERIC_KERNEL_THREAD | 16 | select GENERIC_KERNEL_THREAD |
17 | select GENERIC_KERNEL_EXECVE | 17 | select GENERIC_KERNEL_EXECVE |
18 | select ARCH_WANT_OPTIONAL_GPIOLIB | 18 | select ARCH_WANT_OPTIONAL_GPIOLIB |
19 | select CLONE_BACKWARDS | ||
19 | help | 20 | help |
20 | Xtensa processors are 32-bit RISC machines designed by Tensilica | 21 | Xtensa processors are 32-bit RISC machines designed by Tensilica |
21 | primarily for embedded systems. These processors are both | 22 | primarily for embedded systems. These processors are both |
diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h index 72fd44c85b70..6f586bd90e18 100644 --- a/arch/xtensa/include/asm/signal.h +++ b/arch/xtensa/include/asm/signal.h | |||
@@ -27,7 +27,6 @@ struct k_sigaction { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | #include <asm/sigcontext.h> | 29 | #include <asm/sigcontext.h> |
30 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
31 | 30 | ||
32 | #endif /* __ASSEMBLY__ */ | 31 | #endif /* __ASSEMBLY__ */ |
33 | #endif /* _XTENSA_SIGNAL_H */ | 32 | #endif /* _XTENSA_SIGNAL_H */ |
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index 124aeee0d381..b00c928d4cce 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h | |||
@@ -10,8 +10,6 @@ | |||
10 | 10 | ||
11 | struct pt_regs; | 11 | struct pt_regs; |
12 | struct sigaction; | 12 | struct sigaction; |
13 | asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*); | ||
14 | asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); | ||
15 | asmlinkage long xtensa_ptrace(long, long, long, long); | 13 | asmlinkage long xtensa_ptrace(long, long, long, long); |
16 | asmlinkage long xtensa_sigreturn(struct pt_regs*); | 14 | asmlinkage long xtensa_sigreturn(struct pt_regs*); |
17 | asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); | 15 | asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); |
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index f4e6eaa40d1c..e002dbcc88b6 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _XTENSA_UNISTD_H | 2 | #define _XTENSA_UNISTD_H |
3 | 3 | ||
4 | #define __ARCH_WANT_SYS_EXECVE | 4 | #define __ARCH_WANT_SYS_EXECVE |
5 | #define __ARCH_WANT_SYS_CLONE | ||
5 | #include <uapi/asm/unistd.h> | 6 | #include <uapi/asm/unistd.h> |
6 | 7 | ||
7 | /* | 8 | /* |
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 9f36d0e3e0ac..5162418c5d90 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h | |||
@@ -260,7 +260,7 @@ __SYSCALL(115, sys_sendmmsg, 4) | |||
260 | /* Process Operations */ | 260 | /* Process Operations */ |
261 | 261 | ||
262 | #define __NR_clone 116 | 262 | #define __NR_clone 116 |
263 | __SYSCALL(116, xtensa_clone, 5) | 263 | __SYSCALL(116, sys_clone, 5) |
264 | #define __NR_execve 117 | 264 | #define __NR_execve 117 |
265 | __SYSCALL(117, sys_execve, 3) | 265 | __SYSCALL(117, sys_execve, 3) |
266 | #define __NR_exit 118 | 266 | #define __NR_exit 118 |
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 09ae7bfab9a7..1accf28da5f5 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -199,8 +199,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
199 | */ | 199 | */ |
200 | 200 | ||
201 | int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, | 201 | int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, |
202 | unsigned long thread_fn_arg, | 202 | unsigned long thread_fn_arg, struct task_struct *p) |
203 | struct task_struct *p, struct pt_regs *unused) | ||
204 | { | 203 | { |
205 | struct pt_regs *childregs = task_pt_regs(p); | 204 | struct pt_regs *childregs = task_pt_regs(p); |
206 | 205 | ||
@@ -364,12 +363,3 @@ int dump_fpu(void) | |||
364 | { | 363 | { |
365 | return 0; | 364 | return 0; |
366 | } | 365 | } |
367 | |||
368 | asmlinkage | ||
369 | long xtensa_clone(unsigned long clone_flags, unsigned long newsp, | ||
370 | void __user *parent_tid, void *child_tls, | ||
371 | void __user *child_tid, long a5, | ||
372 | struct pt_regs *regs) | ||
373 | { | ||
374 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
375 | } | ||