s390: switch to generic kernel_thread()
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 22 Sep 2012 00:48:32 +0000 (20:48 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 1 Oct 2012 03:03:03 +0000 (23:03 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/s390/Kconfig
arch/s390/include/asm/processor.h
arch/s390/kernel/process.c

index 107610e..5744239 100644 (file)
@@ -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
index 0bc7761..da6f5ba 100644 (file)
@@ -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.
index 2868a36..bab088d 100644 (file)
@@ -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;
 }