diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-16 12:05:09 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-01 00:44:44 -0400 |
commit | 533e6903bea0440816a0f517b0845ccea4cc7917 (patch) | |
tree | bc01397ec305de38476ab9dab8b33c1b2d492379 /arch/m68k | |
parent | 0973c687e05a802a757664722678d2b5016f1c1c (diff) |
m68k: split ret_from_fork(), simplify kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/Kconfig | 1 | ||||
-rw-r--r-- | arch/m68k/include/asm/processor.h | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 11 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 84 |
4 files changed, 36 insertions, 62 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index b22df9410dce..ccda007ba40f 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -13,6 +13,7 @@ config M68K | |||
13 | select FPU if MMU | 13 | select FPU if MMU |
14 | select ARCH_WANT_IPC_PARSE_VERSION | 14 | select ARCH_WANT_IPC_PARSE_VERSION |
15 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE | 15 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE |
16 | select GENERIC_KERNEL_THREAD | ||
16 | 17 | ||
17 | config RWSEM_GENERIC_SPINLOCK | 18 | config RWSEM_GENERIC_SPINLOCK |
18 | bool | 19 | bool |
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index 9b4c82c1ef47..ae700f49e51d 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h | |||
@@ -154,8 +154,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
154 | { | 154 | { |
155 | } | 155 | } |
156 | 156 | ||
157 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
158 | |||
159 | /* | 157 | /* |
160 | * Free current thread data structures etc.. | 158 | * Free current thread data structures etc.. |
161 | */ | 159 | */ |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 165ee9f9d5c9..8a01f580a024 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -111,6 +111,17 @@ ENTRY(ret_from_fork) | |||
111 | addql #4,%sp | 111 | addql #4,%sp |
112 | jra ret_from_exception | 112 | jra ret_from_exception |
113 | 113 | ||
114 | ENTRY(ret_from_kernel_thread) | ||
115 | | a3 contains the kernel thread payload, d7 - its argument | ||
116 | movel %d1,%sp@- | ||
117 | jsr schedule_tail | ||
118 | GET_CURRENT(%d0) | ||
119 | movel %d7,(%sp) | ||
120 | jsr %a3@ | ||
121 | addql #4,%sp | ||
122 | movel %d0,(%sp) | ||
123 | jra sys_exit | ||
124 | |||
114 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) | 125 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) |
115 | 126 | ||
116 | #ifdef TRAP_DBG_INTERRUPT | 127 | #ifdef TRAP_DBG_INTERRUPT |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c488e3cfab53..b3d4760c9750 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | 35 | ||
36 | asmlinkage void ret_from_fork(void); | 36 | asmlinkage void ret_from_fork(void); |
37 | asmlinkage void ret_from_kernel_thread(void); | ||
37 | 38 | ||
38 | 39 | ||
39 | /* | 40 | /* |
@@ -120,51 +121,6 @@ void show_regs(struct pt_regs * regs) | |||
120 | printk("USP: %08lx\n", rdusp()); | 121 | printk("USP: %08lx\n", rdusp()); |
121 | } | 122 | } |
122 | 123 | ||
123 | /* | ||
124 | * Create a kernel thread | ||
125 | */ | ||
126 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
127 | { | ||
128 | int pid; | ||
129 | mm_segment_t fs; | ||
130 | |||
131 | fs = get_fs(); | ||
132 | set_fs (KERNEL_DS); | ||
133 | |||
134 | { | ||
135 | register long retval __asm__ ("d0"); | ||
136 | register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; | ||
137 | |||
138 | retval = __NR_clone; | ||
139 | __asm__ __volatile__ | ||
140 | ("clrl %%d2\n\t" | ||
141 | "trap #0\n\t" /* Linux/m68k system call */ | ||
142 | "tstl %0\n\t" /* child or parent */ | ||
143 | "jne 1f\n\t" /* parent - jump */ | ||
144 | #ifdef CONFIG_MMU | ||
145 | "lea %%sp@(%c7),%6\n\t" /* reload current */ | ||
146 | "movel %6@,%6\n\t" | ||
147 | #endif | ||
148 | "movel %3,%%sp@-\n\t" /* push argument */ | ||
149 | "jsr %4@\n\t" /* call fn */ | ||
150 | "movel %0,%%d1\n\t" /* pass exit value */ | ||
151 | "movel %2,%%d0\n\t" /* exit */ | ||
152 | "trap #0\n" | ||
153 | "1:" | ||
154 | : "+d" (retval) | ||
155 | : "i" (__NR_clone), "i" (__NR_exit), | ||
156 | "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), | ||
157 | "i" (-THREAD_SIZE) | ||
158 | : "d2"); | ||
159 | |||
160 | pid = retval; | ||
161 | } | ||
162 | |||
163 | set_fs (fs); | ||
164 | return pid; | ||
165 | } | ||
166 | EXPORT_SYMBOL(kernel_thread); | ||
167 | |||
168 | void flush_thread(void) | 124 | void flush_thread(void) |
169 | { | 125 | { |
170 | current->thread.fs = __USER_DS; | 126 | current->thread.fs = __USER_DS; |
@@ -216,30 +172,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs) | |||
216 | } | 172 | } |
217 | 173 | ||
218 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 174 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
219 | unsigned long unused, | 175 | unsigned long arg, |
220 | struct task_struct * p, struct pt_regs * regs) | 176 | struct task_struct * p, struct pt_regs * regs) |
221 | { | 177 | { |
222 | struct pt_regs * childregs; | 178 | struct pt_regs * childregs; |
223 | struct switch_stack * childstack, *stack; | 179 | struct switch_stack *childstack; |
224 | unsigned long *retp; | ||
225 | 180 | ||
226 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 181 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; |
227 | |||
228 | *childregs = *regs; | ||
229 | childregs->d0 = 0; | ||
230 | |||
231 | retp = ((unsigned long *) regs); | ||
232 | stack = ((struct switch_stack *) retp) - 1; | ||
233 | |||
234 | childstack = ((struct switch_stack *) childregs) - 1; | 182 | childstack = ((struct switch_stack *) childregs) - 1; |
235 | *childstack = *stack; | ||
236 | childstack->retpc = (unsigned long)ret_from_fork; | ||
237 | 183 | ||
238 | p->thread.usp = usp; | 184 | p->thread.usp = usp; |
239 | p->thread.ksp = (unsigned long)childstack; | 185 | p->thread.ksp = (unsigned long)childstack; |
240 | 186 | p->thread.esp0 = (unsigned long)childregs; | |
241 | if (clone_flags & CLONE_SETTLS) | ||
242 | task_thread_info(p)->tp_value = regs->d5; | ||
243 | 187 | ||
244 | /* | 188 | /* |
245 | * Must save the current SFC/DFC value, NOT the value when | 189 | * Must save the current SFC/DFC value, NOT the value when |
@@ -247,6 +191,26 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
247 | */ | 191 | */ |
248 | p->thread.fs = get_fs().seg; | 192 | p->thread.fs = get_fs().seg; |
249 | 193 | ||
194 | if (unlikely(!regs)) { | ||
195 | /* kernel thread */ | ||
196 | memset(childstack, 0, | ||
197 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | ||
198 | childregs->sr = PS_S; | ||
199 | childstack->a3 = usp; /* function */ | ||
200 | childstack->d7 = arg; | ||
201 | childstack->retpc = (unsigned long)ret_from_kernel_thread; | ||
202 | p->thread.usp = 0; | ||
203 | return 0; | ||
204 | } | ||
205 | *childregs = *regs; | ||
206 | childregs->d0 = 0; | ||
207 | |||
208 | *childstack = ((struct switch_stack *) regs)[-1]; | ||
209 | childstack->retpc = (unsigned long)ret_from_fork; | ||
210 | |||
211 | if (clone_flags & CLONE_SETTLS) | ||
212 | task_thread_info(p)->tp_value = regs->d5; | ||
213 | |||
250 | #ifdef CONFIG_FPU | 214 | #ifdef CONFIG_FPU |
251 | if (!FPU_IS_EMU) { | 215 | if (!FPU_IS_EMU) { |
252 | /* Copy the current fpu state */ | 216 | /* Copy the current fpu state */ |