From 533e6903bea0440816a0f517b0845ccea4cc7917 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 16 Sep 2012 12:05:09 -0400
Subject: m68k: split ret_from_fork(), simplify kernel_thread()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 arch/m68k/kernel/process.c | 84 +++++++++++++---------------------------------
 1 file changed, 24 insertions(+), 60 deletions(-)

(limited to 'arch/m68k/kernel/process.c')

diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c488e3cfab5..b3d4760c975 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 */
-- 
cgit v1.2.3-70-g09d2


From d878d6dacee2c862f02da20f7fa3e2c0e8820e71 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sun, 16 Sep 2012 12:06:34 -0400
Subject: m68k: switch to generic sys_execve()/kernel_execve()

The tricky part here is that task_pt_regs() on m68k works *only* for
process inside do_signal().  However, we need something much simpler -
pt_regs of a process inside do_signal() may be at different offsets
from the stack bottom, depending on the way we'd entered the kernel,
but for a task inside sys_execve() it *is* at constant offset.
Moreover, for a kernel thread about to become a userland process the
same location is also fine - setting sp to that will leave the kernel
stack pointer at the very bottom of the kernel stack when we finally
switch to userland.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 arch/m68k/include/asm/ptrace.h |  2 ++
 arch/m68k/include/asm/unistd.h |  2 ++
 arch/m68k/kernel/entry.S       |  5 +++++
 arch/m68k/kernel/process.c     | 20 --------------------
 arch/m68k/kernel/sys_m68k.c    | 17 -----------------
 5 files changed, 9 insertions(+), 37 deletions(-)

(limited to 'arch/m68k/kernel/process.c')

diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index 65322b17b6c..5e08b597f01 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -85,6 +85,8 @@ struct switch_stack {
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_pt_regs() \
+	(struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 045cfd6a9e3..c702ad71679 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -382,6 +382,8 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 8a01f580a02..946cb018775 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -122,6 +122,11 @@ ENTRY(ret_from_kernel_thread)
 	movel	%d0,(%sp)
 	jra	sys_exit
 
+ENTRY(ret_from_kernel_execve)
+	movel	4(%sp), %sp
+	GET_CURRENT(%d0)
+	jra	ret_from_exception
+
 #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 b3d4760c975..4e54b4c0308 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -298,26 +298,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 EXPORT_SYMBOL(dump_fpu);
 #endif /* CONFIG_FPU */
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	int error;
-	char * filename;
-	struct pt_regs *regs = (struct pt_regs *) &name;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long fp, pc;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 9a5932ec368..3a480b3df0d 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -549,23 +549,6 @@ asmlinkage int sys_getpagesize(void)
 	return PAGE_SIZE;
 }
 
-/*
- * 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 __res asm ("%d0") = __NR_execve;
-	register long __a asm ("%d1") = (long)(filename);
-	register long __b asm ("%d2") = (long)(argv);
-	register long __c asm ("%d3") = (long)(envp);
-	asm volatile ("trap  #0" : "+d" (__res)
-			: "d" (__a), "d" (__b), "d" (__c));
-	return __res;
-}
-
 asmlinkage unsigned long sys_get_thread_area(void)
 {
 	return current_thread_info()->tp_value;
-- 
cgit v1.2.3-70-g09d2