m32r: switch to generic kernel_thread()/kernel_execve()
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 15 Oct 2012 20:26:03 +0000 (16:26 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 1 Nov 2012 02:59:31 +0000 (22:59 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/m32r/Kconfig
arch/m32r/include/asm/processor.h
arch/m32r/kernel/entry.S
arch/m32r/kernel/process.c
arch/m32r/kernel/sys_m32r.c

index f807721e19a52ee1f5b619cd0a742328e4515f46..5183f43a2cf7c3efd720a82d38312bc7b49422c7 100644 (file)
@@ -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
index da17253b5735ba2d81b37e929f59126628449da7..5767367550c69637a0b51c7a037b7a5e0c4fbfb4 100644 (file)
@@ -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);
index 225412bc227e690bcb313743dd16f58fca5c4115..0c01543f10cd9c1ad53c9453294d185fc18730cd 100644 (file)
        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
index e7366276ef30067ad22f9fd4b9db3252d69f8b66..fa89f027c04a2a8e5f6b506e5806139b7a0163a8 100644 (file)
@@ -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(&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..
  */
@@ -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;
 }
index d841fb6cc70325a23c25e71f3552b14751284b56..c3fdd632fba70cf99f142e959fa63b65be1155a8 100644 (file)
@@ -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;
-}