summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-16 00:26:03 +0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-11-01 06:59:31 +0400
commitea4a1da9b2e6f419526b5fde15cd5563096368eb (patch)
tree470d747b0ea28293467292ac88f083e6b2370a29
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
downloadlinux-ea4a1da9b2e6f419526b5fde15cd5563096368eb.tar.xz
m32r: switch to generic kernel_thread()/kernel_execve()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/m32r/Kconfig2
-rw-r--r--arch/m32r/include/asm/processor.h5
-rw-r--r--arch/m32r/kernel/entry.S9
-rw-r--r--arch/m32r/kernel/process.c60
-rw-r--r--arch/m32r/kernel/sys_m32r.c21
5 files changed, 27 insertions, 70 deletions
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index f807721e19a5..5183f43a2cf7 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -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
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h
index da17253b5735..5767367550c6 100644
--- a/arch/m32r/include/asm/processor.h
+++ b/arch/m32r/include/asm/processor.h
@@ -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);
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 225412bc227e..0c01543f10cd 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 e7366276ef30..fa89f027c04a 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs)
}
/*
- * 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 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;
}
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index d841fb6cc703..c3fdd632fba7 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -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;
-}