From 65f22a906e154e8086ed561904d09c3586de85f4 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Thu, 6 Sep 2012 15:48:11 -0400
Subject: s390: fold execve_tail() into start_thread(), convert to generic
 sys_execve()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 arch/s390/include/asm/processor.h | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'arch/s390/include/asm/processor.h')

diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 11e4e3236937..0bc77619c3a3 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -32,6 +32,7 @@ static inline void get_cpu_id(struct cpuid *ptr)
 extern void s390_adjust_jiffies(void);
 extern const struct seq_operations cpuinfo_op;
 extern int sysctl_ieee_emulation_warnings;
+extern void execve_tail(void);
 
 /*
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -114,6 +115,7 @@ struct stack_frame {
 	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
 	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
 	regs->gprs[15]	= new_stackp;					\
+	execve_tail();							\
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {			\
@@ -123,6 +125,7 @@ struct stack_frame {
 	__tlb_flush_mm(current->mm);					\
 	crst_table_downgrade(current->mm, 1UL << 31);			\
 	update_mm(current->mm, current);				\
+	execve_tail();							\
 } while (0)
 
 /* Forward declaration, a strange C thing */
-- 
cgit v1.2.3


From f9a7e025dfc28783fd2b05812e663251acf4bf21 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Fri, 21 Sep 2012 20:48:32 -0400
Subject: s390: switch to generic kernel_thread()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 arch/s390/Kconfig                 |  1 +
 arch/s390/include/asm/processor.h |  1 -
 arch/s390/kernel/process.c        | 72 ++++++++++++++++++---------------------
 3 files changed, 34 insertions(+), 40 deletions(-)

(limited to 'arch/s390/include/asm/processor.h')

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 107610e01a29..57442393bac7 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -125,6 +125,7 @@ config S390
 	select GENERIC_CLOCKEVENTS
 	select KTIME_SCALAR if 32BIT
 	select HAVE_ARCH_SECCOMP_FILTER
+	select GENERIC_KERNEL_THREAD
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 0bc77619c3a3..da6f5baeee5c 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -135,7 +135,6 @@ struct seq_file;
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
  * Return saved PC of a blocked thread.
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 2868a364ff94..bab088de4569 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -98,25 +98,6 @@ void cpu_idle(void)
 
 extern void __kprobes kernel_thread_starter(void);
 
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = psw_kernel_bits |
-		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
-	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-	regs.gprs[9] = (unsigned long) fn;
-	regs.gprs[10] = (unsigned long) arg;
-	regs.gprs[11] = (unsigned long) do_exit;
-	regs.orig_gpr2 = -1;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-		       0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Free current thread data structures etc..
  */
@@ -133,7 +114,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
-		unsigned long unused,
+		unsigned long arg,
 		struct task_struct *p, struct pt_regs *regs)
 {
 	struct thread_info *ti;
@@ -145,20 +126,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
 	frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
 	p->thread.ksp = (unsigned long) frame;
-	/* Store access registers to kernel stack of new process. */
-	frame->childregs = *regs;
-	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
-	frame->childregs.gprs[15] = new_stackp;
-	frame->sf.back_chain = 0;
+	/* Save access registers to new thread structure. */
+	save_access_regs(&p->thread.acrs[0]);
+	/* start new process with ar4 pointing to the correct address space */
+	p->thread.mm_segment = get_fs();
+	/* Don't copy debug registers */
+	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
+	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
+	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
+	clear_tsk_thread_flag(p, TIF_PER_TRAP);
+	/* Initialize per thread user and system timer values */
+	ti = task_thread_info(p);
+	ti->user_timer = 0;
+	ti->system_timer = 0;
 
+	frame->sf.back_chain = 0;
 	/* new return point is ret_from_fork */
 	frame->sf.gprs[8] = (unsigned long) ret_from_fork;
-
 	/* fake return stack for resume(), don't go back to schedule */
 	frame->sf.gprs[9] = (unsigned long) frame;
 
-	/* Save access registers to new thread structure. */
-	save_access_regs(&p->thread.acrs[0]);
+	/* Store access registers to kernel stack of new process. */
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(&frame->childregs, 0, sizeof(struct pt_regs));
+		frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
+				PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+		frame->childregs.psw.addr = PSW_ADDR_AMODE |
+				(unsigned long) kernel_thread_starter;
+		frame->childregs.gprs[9] = new_stackp; /* function */
+		frame->childregs.gprs[10] = arg;
+		frame->childregs.gprs[11] = (unsigned long) do_exit;
+		frame->childregs.orig_gpr2 = -1;
+
+		return 0;
+	}
+	frame->childregs = *regs;
+	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
+	frame->childregs.gprs[15] = new_stackp;
 
 #ifndef CONFIG_64BIT
 	/*
@@ -184,17 +189,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 		}
 	}
 #endif /* CONFIG_64BIT */
-	/* start new process with ar4 pointing to the correct address space */
-	p->thread.mm_segment = get_fs();
-	/* Don't copy debug registers */
-	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
-	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
-	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
-	clear_tsk_thread_flag(p, TIF_PER_TRAP);
-	/* Initialize per thread user and system timer values */
-	ti = task_thread_info(p);
-	ti->user_timer = 0;
-	ti->system_timer = 0;
 	return 0;
 }
 
-- 
cgit v1.2.3