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/avr32 | |
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/avr32')
-rw-r--r-- | arch/avr32/Kconfig | 2 | ||||
-rw-r--r-- | arch/avr32/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/avr32/include/asm/signal.h | 2 | ||||
-rw-r--r-- | arch/avr32/include/asm/unistd.h | 4 | ||||
-rw-r--r-- | arch/avr32/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/avr32/kernel/entry-avr32b.S | 14 | ||||
-rw-r--r-- | arch/avr32/kernel/process.c | 115 | ||||
-rw-r--r-- | arch/avr32/kernel/sys_avr32.c | 24 | ||||
-rw-r--r-- | arch/avr32/kernel/syscall-stubs.S | 24 | ||||
-rw-r--r-- | arch/avr32/kernel/syscall_table.S | 8 |
10 files changed, 39 insertions, 159 deletions
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 |