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/alpha/kernel | |
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/alpha/kernel')
-rw-r--r-- | arch/alpha/kernel/binfmt_loader.c | 4 | ||||
-rw-r--r-- | arch/alpha/kernel/entry.S | 51 | ||||
-rw-r--r-- | arch/alpha/kernel/process.c | 62 | ||||
-rw-r--r-- | arch/alpha/kernel/signal.c | 16 | ||||
-rw-r--r-- | arch/alpha/kernel/systbls.S | 6 |
5 files changed, 39 insertions, 100 deletions
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 */ |