aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m32r/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m32r/kernel/process.c')
-rw-r--r--arch/m32r/kernel/process.c126
1 files changed, 17 insertions, 109 deletions
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index e7366276ef30..765d0f57c787 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs)
165} 165}
166 166
167/* 167/*
168 * Create a kernel thread
169 */
170
171/*
172 * This is the mechanism for creating a new kernel thread.
173 *
174 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
175 * who haven't done an "execve()") should use this: it will work within
176 * a system call from a "real" process, but the process memory space will
177 * not be free'd until both the parent and the child have exited.
178 */
179static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg)
180{
181 fn(arg);
182 do_exit(-1);
183}
184
185int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
186{
187 struct pt_regs regs;
188
189 memset(&regs, 0, sizeof (regs));
190 regs.r1 = (unsigned long)fn;
191 regs.r2 = (unsigned long)arg;
192
193 regs.bpc = (unsigned long)kernel_thread_helper;
194
195 regs.psw = M32R_PSW_BIE;
196
197 /* Ok, create the new process. */
198 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
199 NULL);
200}
201
202/*
203 * Free current thread data structures etc.. 168 * Free current thread data structures etc..
204 */ 169 */
205void exit_thread(void) 170void exit_thread(void)
@@ -227,88 +192,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
227} 192}
228 193
229int copy_thread(unsigned long clone_flags, unsigned long spu, 194int copy_thread(unsigned long clone_flags, unsigned long spu,
230 unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) 195 unsigned long arg, struct task_struct *tsk)
231{ 196{
232 struct pt_regs *childregs = task_pt_regs(tsk); 197 struct pt_regs *childregs = task_pt_regs(tsk);
233 extern void ret_from_fork(void); 198 extern void ret_from_fork(void);
234 199 extern void ret_from_kernel_thread(void);
235 /* Copy registers */ 200
236 *childregs = *regs; 201 if (unlikely(tsk->flags & PF_KTHREAD)) {
237 202 memset(childregs, 0, sizeof(struct pt_regs));
238 childregs->spu = spu; 203 childregs->psw = M32R_PSW_BIE;
239 childregs->r0 = 0; /* Child gets zero as return value */ 204 childregs->r1 = spu; /* fn */
240 regs->r0 = tsk->pid; 205 childregs->r0 = arg;
206 tsk->thread.lr = (unsigned long)ret_from_kernel_thread;
207 } else {
208 /* Copy registers */
209 *childregs = *current_pt_regs();
210 if (spu)
211 childregs->spu = spu;
212 childregs->r0 = 0; /* Child gets zero as return value */
213 tsk->thread.lr = (unsigned long)ret_from_fork;
214 }
241 tsk->thread.sp = (unsigned long)childregs; 215 tsk->thread.sp = (unsigned long)childregs;
242 tsk->thread.lr = (unsigned long)ret_from_fork;
243 216
244 return 0; 217 return 0;
245} 218}
246 219
247asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
248 unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
249 struct pt_regs regs)
250{
251#ifdef CONFIG_MMU
252 return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
253#else
254 return -EINVAL;
255#endif /* CONFIG_MMU */
256}
257
258asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
259 unsigned long parent_tidptr,
260 unsigned long child_tidptr,
261 unsigned long r4, unsigned long r5, unsigned long r6,
262 struct pt_regs regs)
263{
264 if (!newsp)
265 newsp = regs.spu;
266
267 return do_fork(clone_flags, newsp, &regs, 0,
268 (int __user *)parent_tidptr, (int __user *)child_tidptr);
269}
270
271/*
272 * This is trivial, and on the face of it looks like it
273 * could equally well be done in user mode.
274 *
275 * Not so, for quite unobvious reasons - register pressure.
276 * In user mode vfork() cannot have a stack frame, and if
277 * done by calling the "clone()" system call directly, you
278 * do not have enough call-clobbered registers to hold all
279 * the information you need.
280 */
281asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,
282 unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,
283 struct pt_regs regs)
284{
285 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
286 NULL, NULL);
287}
288
289/*
290 * sys_execve() executes a new program.
291 */
292asmlinkage int sys_execve(const char __user *ufilename,
293 const char __user *const __user *uargv,
294 const char __user *const __user *uenvp,
295 unsigned long r3, unsigned long r4, unsigned long r5,
296 unsigned long r6, struct pt_regs regs)
297{
298 int error;
299 struct filename *filename;
300
301 filename = getname(ufilename);
302 error = PTR_ERR(filename);
303 if (IS_ERR(filename))
304 goto out;
305
306 error = do_execve(filename->name, uargv, uenvp, &regs);
307 putname(filename);
308out:
309 return error;
310}
311
312/* 220/*
313 * These bracket the sleeping functions.. 221 * These bracket the sleeping functions..
314 */ 222 */