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/kernel | |
parent | 0973c687e05a802a757664722678d2b5016f1c1c (diff) | |
download | lwn-533e6903bea0440816a0f517b0845ccea4cc7917.tar.gz lwn-533e6903bea0440816a0f517b0845ccea4cc7917.zip |
m68k: split ret_from_fork(), simplify kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r-- | arch/m68k/kernel/entry.S | 11 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 84 |
2 files changed, 35 insertions, 60 deletions
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) addql #4,%sp jra ret_from_exception +ENTRY(ret_from_kernel_thread) + | a3 contains the kernel thread payload, d7 - its argument + movel %d1,%sp@- + jsr schedule_tail + GET_CURRENT(%d0) + movel %d7,(%sp) + jsr %a3@ + addql #4,%sp + movel %d0,(%sp) + jra sys_exit + #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) #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 @@ asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); /* @@ -120,51 +121,6 @@ void show_regs(struct pt_regs * regs) printk("USP: %08lx\n", rdusp()); } -/* - * Create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - int pid; - mm_segment_t fs; - - fs = get_fs(); - set_fs (KERNEL_DS); - - { - register long retval __asm__ ("d0"); - register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; - - retval = __NR_clone; - __asm__ __volatile__ - ("clrl %%d2\n\t" - "trap #0\n\t" /* Linux/m68k system call */ - "tstl %0\n\t" /* child or parent */ - "jne 1f\n\t" /* parent - jump */ -#ifdef CONFIG_MMU - "lea %%sp@(%c7),%6\n\t" /* reload current */ - "movel %6@,%6\n\t" -#endif - "movel %3,%%sp@-\n\t" /* push argument */ - "jsr %4@\n\t" /* call fn */ - "movel %0,%%d1\n\t" /* pass exit value */ - "movel %2,%%d0\n\t" /* exit */ - "trap #0\n" - "1:" - : "+d" (retval) - : "i" (__NR_clone), "i" (__NR_exit), - "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), - "i" (-THREAD_SIZE) - : "d2"); - - pid = retval; - } - - set_fs (fs); - return pid; -} -EXPORT_SYMBOL(kernel_thread); - void flush_thread(void) { current->thread.fs = __USER_DS; @@ -216,30 +172,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; - struct switch_stack * childstack, *stack; - unsigned long *retp; + struct switch_stack *childstack; childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; - - *childregs = *regs; - childregs->d0 = 0; - - retp = ((unsigned long *) regs); - stack = ((struct switch_stack *) retp) - 1; - childstack = ((struct switch_stack *) childregs) - 1; - *childstack = *stack; - childstack->retpc = (unsigned long)ret_from_fork; p->thread.usp = usp; p->thread.ksp = (unsigned long)childstack; - - if (clone_flags & CLONE_SETTLS) - task_thread_info(p)->tp_value = regs->d5; + p->thread.esp0 = (unsigned long)childregs; /* * 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, */ p->thread.fs = get_fs().seg; + if (unlikely(!regs)) { + /* kernel thread */ + memset(childstack, 0, + sizeof(struct switch_stack) + sizeof(struct pt_regs)); + childregs->sr = PS_S; + childstack->a3 = usp; /* function */ + childstack->d7 = arg; + childstack->retpc = (unsigned long)ret_from_kernel_thread; + p->thread.usp = 0; + return 0; + } + *childregs = *regs; + childregs->d0 = 0; + + *childstack = ((struct switch_stack *) regs)[-1]; + childstack->retpc = (unsigned long)ret_from_fork; + + if (clone_flags & CLONE_SETTLS) + task_thread_info(p)->tp_value = regs->d5; + #ifdef CONFIG_FPU if (!FPU_IS_EMU) { /* Copy the current fpu state */ |