From ea4a1da9b2e6f419526b5fde15cd5563096368eb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 15 Oct 2012 16:26:03 -0400 Subject: [PATCH] m32r: switch to generic kernel_thread()/kernel_execve() Signed-off-by: Al Viro --- arch/m32r/Kconfig | 2 ++ arch/m32r/include/asm/processor.h | 5 --- arch/m32r/kernel/entry.S | 9 +++++ arch/m32r/kernel/process.c | 60 +++++++++---------------------- arch/m32r/kernel/sys_m32r.c | 21 ----------- 5 files changed, 27 insertions(+), 70 deletions(-) diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index f807721e19a5..5183f43a2cf7 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -15,6 +15,8 @@ config M32R select GENERIC_ATOMIC64 select ARCH_USES_GETTIMEOFFSET select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config SBUS bool diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h index da17253b5735..5767367550c6 100644 --- a/arch/m32r/include/asm/processor.h +++ b/arch/m32r/include/asm/processor.h @@ -118,11 +118,6 @@ struct mm_struct; /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - /* Copy and release all segment info associated with a VM */ extern void copy_segments(struct task_struct *p, struct mm_struct * mm); extern void release_segments(struct mm_struct * mm); diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 225412bc227e..0c01543f10cd 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -125,6 +125,15 @@ and \reg, sp .endm +ENTRY(ret_from_kernel_thread) + pop r0 + bl schedule_tail + GET_THREAD_INFO(r8) + ld r0, R0(r8) + ld r1, R1(r8) + jl r1 + bra syscall_exit + ENTRY(ret_from_fork) pop r0 bl schedule_tail diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index e7366276ef30..fa89f027c04a 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -164,41 +164,6 @@ void show_regs(struct pt_regs * regs) #endif } -/* - * Create a kernel thread - */ - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg) -{ - fn(arg); - do_exit(-1); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof (regs)); - regs.r1 = (unsigned long)fn; - regs.r2 = (unsigned long)arg; - - regs.bpc = (unsigned long)kernel_thread_helper; - - regs.psw = M32R_PSW_BIE; - - /* Ok, create the new process. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, - NULL); -} - /* * Free current thread data structures etc.. */ @@ -227,19 +192,26 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } int copy_thread(unsigned long clone_flags, unsigned long spu, - unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) + unsigned long arg, struct task_struct *tsk, struct pt_regs *regs) { struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); - - /* Copy registers */ - *childregs = *regs; - - childregs->spu = spu; - childregs->r0 = 0; /* Child gets zero as return value */ - regs->r0 = tsk->pid; + extern void ret_from_kernel_thread(void); + + if (unlikely(tsk->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + childregs->psw = M32R_PSW_BIE; + childregs->r1 = spu; /* fn */ + childregs->r0 = arg; + tsk->thread.lr = (unsigned long)ret_from_kernel_thread; + } else { + /* Copy registers */ + *childregs = *regs; + childregs->spu = spu; + childregs->r0 = 0; /* Child gets zero as return value */ + tsk->thread.lr = (unsigned long)ret_from_fork; + } tsk->thread.sp = (unsigned long)childregs; - tsk->thread.lr = (unsigned long)ret_from_fork; return 0; } diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index d841fb6cc703..c3fdd632fba7 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -88,24 +88,3 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op) /* Not implemented yet. */ return -ENOSYS; } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register long __scno __asm__ ("r7") = __NR_execve; - register long __arg3 __asm__ ("r2") = (long)(envp); - register long __arg2 __asm__ ("r1") = (long)(argv); - register long __res __asm__ ("r0") = (long)(filename); - __asm__ __volatile__ ( - "trap #" SYSCALL_VECTOR "|| nop" - : "=r" (__res) - : "r" (__scno), "0" (__res), "r" (__arg2), - "r" (__arg3) - : "memory"); - return __res; -} -- 2.39.5