m32r: switch to generic kernel_thread()/kernel_execve()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 225412b..0c01543 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 e736627..fa89f02 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -165,41 +165,6 @@
 }
 
 /*
- * 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(&regs, 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, &regs, 0, NULL,
-		NULL);
-}
-
-/*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
@@ -227,19 +192,26 @@
 }
 
 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);
+	extern void ret_from_kernel_thread(void);
 
-	/* Copy registers */
-	*childregs = *regs;
-
-	childregs->spu = spu;
-	childregs->r0 = 0;	/* Child gets zero as return value */
-	regs->r0 = tsk->pid;
+	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 d841fb6..c3fdd63 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -88,24 +88,3 @@
 	/* 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;
-}