aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/process_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/process_64.c')
-rw-r--r--arch/sh/kernel/process_64.c85
1 files changed, 16 insertions, 69 deletions
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 98a709f0c3c4..3a0f3fd3bb58 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -285,39 +285,6 @@ void show_regs(struct pt_regs *regs)
285} 285}
286 286
287/* 287/*
288 * Create a kernel thread
289 */
290__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
291{
292 do_exit(fn(arg));
293}
294
295/*
296 * This is the mechanism for creating a new kernel thread.
297 *
298 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
299 * who haven't done an "execve()") should use this: it will work within
300 * a system call from a "real" process, but the process memory space will
301 * not be freed until both the parent and the child have exited.
302 */
303int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
304{
305 struct pt_regs regs;
306
307 memset(&regs, 0, sizeof(regs));
308 regs.regs[2] = (unsigned long)arg;
309 regs.regs[3] = (unsigned long)fn;
310
311 regs.pc = (unsigned long)kernel_thread_helper;
312 regs.sr = (1 << 30);
313
314 /* Ok, create the new process.. */
315 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
316 &regs, 0, NULL, NULL);
317}
318EXPORT_SYMBOL(kernel_thread);
319
320/*
321 * Free current thread data structures etc.. 288 * Free current thread data structures etc..
322 */ 289 */
323void exit_thread(void) 290void exit_thread(void)
@@ -401,15 +368,17 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
401EXPORT_SYMBOL(dump_fpu); 368EXPORT_SYMBOL(dump_fpu);
402 369
403asmlinkage void ret_from_fork(void); 370asmlinkage void ret_from_fork(void);
371asmlinkage void ret_from_kernel_thread(void);
404 372
405int copy_thread(unsigned long clone_flags, unsigned long usp, 373int copy_thread(unsigned long clone_flags, unsigned long usp,
406 unsigned long unused, 374 unsigned long arg,
407 struct task_struct *p, struct pt_regs *regs) 375 struct task_struct *p, struct pt_regs *regs)
408{ 376{
409 struct pt_regs *childregs; 377 struct pt_regs *childregs;
410 378
411#ifdef CONFIG_SH_FPU 379#ifdef CONFIG_SH_FPU
412 if(last_task_used_math == current) { 380 /* can't happen for a kernel thread */
381 if (last_task_used_math == current) {
413 enable_fpu(); 382 enable_fpu();
414 save_fpu(current); 383 save_fpu(current);
415 disable_fpu(); 384 disable_fpu();
@@ -419,7 +388,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
419#endif 388#endif
420 /* Copy from sh version */ 389 /* Copy from sh version */
421 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; 390 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;
391 p->thread.sp = (unsigned long) childregs;
422 392
393 if (unlikely(p->flags & PF_KTHREAD)) {
394 memset(childregs, 0, sizeof(struct pt_regs));
395 childregs->regs[2] = (unsigned long)arg;
396 childregs->regs[3] = (unsigned long)fn;
397 childregs->sr = (1 << 30); /* not user_mode */
398 childregs->sr |= SR_FD; /* Invalidate FPU flag */
399 p->thread.pc = (unsigned long) ret_from_kernel_thread;
400 return 0;
401 }
423 *childregs = *regs; 402 *childregs = *regs;
424 403
425 /* 404 /*
@@ -428,19 +407,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
428 * 32-bit wide and context switch must take care 407 * 32-bit wide and context switch must take care
429 * of NEFF sign extension. 408 * of NEFF sign extension.
430 */ 409 */
431 if (user_mode(regs)) { 410 childregs->regs[15] = neff_sign_extend(usp);
432 childregs->regs[15] = neff_sign_extend(usp); 411 p->thread.uregs = childregs;
433 p->thread.uregs = childregs;
434 } else {
435 childregs->regs[15] =
436 neff_sign_extend((unsigned long)task_stack_page(p) +
437 THREAD_SIZE);
438 }
439 412
440 childregs->regs[9] = 0; /* Set return value for child */ 413 childregs->regs[9] = 0; /* Set return value for child */
441 childregs->sr |= SR_FD; /* Invalidate FPU flag */ 414 childregs->sr |= SR_FD; /* Invalidate FPU flag */
442 415
443 p->thread.sp = (unsigned long) childregs;
444 p->thread.pc = (unsigned long) ret_from_fork; 416 p->thread.pc = (unsigned long) ret_from_fork;
445 417
446 return 0; 418 return 0;
@@ -482,31 +454,6 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
482 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); 454 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
483} 455}
484 456
485/*
486 * sys_execve() executes a new program.
487 */
488asmlinkage int sys_execve(const char *ufilename, char **uargv,
489 char **uenvp, unsigned long r5,
490 unsigned long r6, unsigned long r7,
491 struct pt_regs *pregs)
492{
493 int error;
494 struct filename *filename;
495
496 filename = getname((char __user *)ufilename);
497 error = PTR_ERR(filename);
498 if (IS_ERR(filename))
499 goto out;
500
501 error = do_execve(filename->name,
502 (const char __user *const __user *)uargv,
503 (const char __user *const __user *)uenvp,
504 pregs);
505 putname(filename);
506out:
507 return error;
508}
509
510#ifdef CONFIG_FRAME_POINTER 457#ifdef CONFIG_FRAME_POINTER
511static int in_sh64_switch_to(unsigned long pc) 458static int in_sh64_switch_to(unsigned long pc)
512{ 459{