From 4f86bb49e1f15e6331d6f0ba84cac12e69a7c559 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 11 Oct 2012 17:32:41 -0400 Subject: [PATCH] --- yaml --- r: 340308 b: refs/heads/master c: ddf23e87a804cbf6fa3818076b33fe023cce09fd h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/m32r/Kconfig | 2 - trunk/arch/m32r/include/asm/processor.h | 5 ++ trunk/arch/m32r/include/asm/ptrace.h | 2 - trunk/arch/m32r/include/asm/unistd.h | 1 - trunk/arch/m32r/kernel/entry.S | 9 -- trunk/arch/m32r/kernel/process.c | 106 ++++++++++++++++++------ trunk/arch/m32r/kernel/sys_m32r.c | 21 +++++ trunk/arch/mn10300/Kconfig | 1 + trunk/arch/mn10300/include/asm/unistd.h | 1 - trunk/arch/mn10300/kernel/entry.S | 7 +- 11 files changed, 109 insertions(+), 48 deletions(-) diff --git a/[refs] b/[refs] index 523ff15f4b8e..9ff7ec4b82b0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8eae10e86c57b6be5e4842b34ea541efbca28bf8 +refs/heads/master: ddf23e87a804cbf6fa3818076b33fe023cce09fd diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index 5183f43a2cf7..f807721e19a5 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -15,8 +15,6 @@ 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/trunk/arch/m32r/include/asm/processor.h b/trunk/arch/m32r/include/asm/processor.h index 5767367550c6..da17253b5735 100644 --- a/trunk/arch/m32r/include/asm/processor.h +++ b/trunk/arch/m32r/include/asm/processor.h @@ -118,6 +118,11 @@ 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/trunk/arch/m32r/include/asm/ptrace.h b/trunk/arch/m32r/include/asm/ptrace.h index c4432f1fb2cf..4313aa62b51b 100644 --- a/trunk/arch/m32r/include/asm/ptrace.h +++ b/trunk/arch/m32r/include/asm/ptrace.h @@ -139,8 +139,6 @@ extern void withdraw_debug_trap(struct pt_regs *regs); #define task_pt_regs(task) \ ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) -#define current_pt_regs() ((struct pt_regs *) \ - ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) #endif /* __KERNEL */ diff --git a/trunk/arch/m32r/include/asm/unistd.h b/trunk/arch/m32r/include/asm/unistd.h index b27bdcbc7c2c..d5e66a480782 100644 --- a/trunk/arch/m32r/include/asm/unistd.h +++ b/trunk/arch/m32r/include/asm/unistd.h @@ -352,7 +352,6 @@ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_SYS_EXECVE #define __IGNORE_lchown #define __IGNORE_setuid diff --git a/trunk/arch/m32r/kernel/entry.S b/trunk/arch/m32r/kernel/entry.S index 0c01543f10cd..225412bc227e 100644 --- a/trunk/arch/m32r/kernel/entry.S +++ b/trunk/arch/m32r/kernel/entry.S @@ -125,15 +125,6 @@ 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/trunk/arch/m32r/kernel/process.c b/trunk/arch/m32r/kernel/process.c index 62c713f5694a..e7366276ef30 100644 --- a/trunk/arch/m32r/kernel/process.c +++ b/trunk/arch/m32r/kernel/process.c @@ -164,6 +164,41 @@ 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(®s, 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, ®s, 0, NULL, + NULL); +} + /* * Free current thread data structures etc.. */ @@ -192,35 +227,29 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } int copy_thread(unsigned long clone_flags, unsigned long spu, - unsigned long arg, struct task_struct *tsk, struct pt_regs *regs) + unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) { struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); - 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; - } + + /* Copy registers */ + *childregs = *regs; + + childregs->spu = spu; + childregs->r0 = 0; /* Child gets zero as return value */ + regs->r0 = tsk->pid; tsk->thread.sp = (unsigned long)childregs; + tsk->thread.lr = (unsigned long)ret_from_fork; return 0; } -asmlinkage int sys_fork(void) +asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, + unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, + struct pt_regs regs) { #ifdef CONFIG_MMU - struct pt_regs *regs = current_pt_regs(); - return do_fork(SIGCHLD, regs->spu, regs, 0, NULL, NULL); + return do_fork(SIGCHLD, regs.spu, ®s, 0, NULL, NULL); #else return -EINVAL; #endif /* CONFIG_MMU */ @@ -228,13 +257,14 @@ asmlinkage int sys_fork(void) asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, - unsigned long child_tidptr) + unsigned long child_tidptr, + unsigned long r4, unsigned long r5, unsigned long r6, + struct pt_regs regs) { - struct pt_regs *regs = current_pt_regs(); if (!newsp) - newsp = regs->spu; + newsp = regs.spu; - return do_fork(clone_flags, newsp, regs, 0, + return do_fork(clone_flags, newsp, ®s, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -248,13 +278,37 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage int sys_vfork(void) +asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2, + unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, + struct pt_regs regs) { - struct pt_regs *regs = current_pt_regs(); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->spu, regs, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, ®s, 0, NULL, NULL); } +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(const char __user *ufilename, + const char __user *const __user *uargv, + const char __user *const __user *uenvp, + unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, struct pt_regs regs) +{ + int error; + struct filename *filename; + + filename = getname(ufilename); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + + error = do_execve(filename->name, uargv, uenvp, ®s); + putname(filename); +out: + return error; +} + /* * These bracket the sleeping functions.. */ diff --git a/trunk/arch/m32r/kernel/sys_m32r.c b/trunk/arch/m32r/kernel/sys_m32r.c index c3fdd632fba7..d841fb6cc703 100644 --- a/trunk/arch/m32r/kernel/sys_m32r.c +++ b/trunk/arch/m32r/kernel/sys_m32r.c @@ -88,3 +88,24 @@ 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; +} diff --git a/trunk/arch/mn10300/Kconfig b/trunk/arch/mn10300/Kconfig index 04669fac117b..72471744a912 100644 --- a/trunk/arch/mn10300/Kconfig +++ b/trunk/arch/mn10300/Kconfig @@ -9,6 +9,7 @@ config MN10300 select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER select GENERIC_CLOCKEVENTS select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select MODULES_USE_ELF_RELA config AM33_2 diff --git a/trunk/arch/mn10300/include/asm/unistd.h b/trunk/arch/mn10300/include/asm/unistd.h index 55bbec1887e9..9711d51b0212 100644 --- a/trunk/arch/mn10300/include/asm/unistd.h +++ b/trunk/arch/mn10300/include/asm/unistd.h @@ -44,7 +44,6 @@ #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/trunk/arch/mn10300/kernel/entry.S b/trunk/arch/mn10300/kernel/entry.S index 0c631d34c8d7..68fcab8f8f6f 100644 --- a/trunk/arch/mn10300/kernel/entry.S +++ b/trunk/arch/mn10300/kernel/entry.S @@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread) mov (REG_D0,fp),d0 mov (REG_A0,fp),a0 calls (a0) - jmp sys_exit - -ENTRY(ret_from_kernel_execve) - add -12,d0 /* pt_regs -> frame */ - mov d0,sp - GET_THREAD_INFO a2 clr d0 + mov d0,(REG_D0,fp) jmp syscall_exit ###############################################################################