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.c60
1 files changed, 16 insertions, 44 deletions
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 98a709f0c3c4..fd338b030fd9 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;