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/m68k | |
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/m68k')
-rw-r--r-- | arch/m68k/Kconfig | 1 | ||||
-rw-r--r-- | arch/m68k/include/asm/signal.h | 8 | ||||
-rw-r--r-- | arch/m68k/include/asm/unistd.h | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 30 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 87 | ||||
-rw-r--r-- | arch/m68k/kernel/signal.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/syscalltable.S | 6 |
7 files changed, 52 insertions, 86 deletions
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 |