diff options
Diffstat (limited to 'arch/m68k/kernel/process.c')
-rw-r--r-- | arch/m68k/kernel/process.c | 84 |
1 files changed, 24 insertions, 60 deletions
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 */ |