diff --git a/[refs] b/[refs] index 1d85df82223e..80d10b8c420c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 71915d21e59c153c1202e3198916817c2d18da32 +refs/heads/master: ea4a1da9b2e6f419526b5fde15cd5563096368eb diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index 04bef4d25b4a..98fabd10e95f 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -8,8 +8,6 @@ config H8300 select GENERIC_IRQ_SHOW select GENERIC_CPU_DEVICES select MODULES_USE_ELF_RELA - select GENERIC_KERNEL_THREAD - select GENERIC_KERNEL_EXECVE config SYMBOL_PREFIX string diff --git a/trunk/arch/h8300/include/asm/processor.h b/trunk/arch/h8300/include/asm/processor.h index 4b0ca49bb463..4c9f6f87b617 100644 --- a/trunk/arch/h8300/include/asm/processor.h +++ b/trunk/arch/h8300/include/asm/processor.h @@ -107,6 +107,8 @@ static inline void release_thread(struct task_struct *dead_task) { } +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + /* * Free current thread data structures etc.. */ diff --git a/trunk/arch/h8300/include/asm/ptrace.h b/trunk/arch/h8300/include/asm/ptrace.h index 00502a61bf0a..d09c440bdba7 100644 --- a/trunk/arch/h8300/include/asm/ptrace.h +++ b/trunk/arch/h8300/include/asm/ptrace.h @@ -60,8 +60,6 @@ struct pt_regs { #define user_mode(regs) (!((regs)->ccr & PS_S)) #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) -#define current_pt_regs() ((struct pt_regs *) \ - (THREAD_SIZE + (unsigned long)current_thread_info()) - 1) #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ #endif /* _H8300_PTRACE_H */ diff --git a/trunk/arch/h8300/include/asm/unistd.h b/trunk/arch/h8300/include/asm/unistd.h index 07afcfaec995..5cd882801d79 100644 --- a/trunk/arch/h8300/include/asm/unistd.h +++ b/trunk/arch/h8300/include/asm/unistd.h @@ -356,7 +356,6 @@ #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND -#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/trunk/arch/h8300/kernel/entry.S b/trunk/arch/h8300/kernel/entry.S index 617a6878787f..ca7431690300 100644 --- a/trunk/arch/h8300/kernel/entry.S +++ b/trunk/arch/h8300/kernel/entry.S @@ -158,7 +158,6 @@ INTERRUPTS = 128 .globl SYMBOL_NAME(system_call) .globl SYMBOL_NAME(ret_from_exception) .globl SYMBOL_NAME(ret_from_fork) -.globl SYMBOL_NAME(ret_from_kernel_thread) .globl SYMBOL_NAME(ret_from_interrupt) .globl SYMBOL_NAME(interrupt_redirect_table) .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) @@ -331,14 +330,6 @@ SYMBOL_NAME_LABEL(ret_from_fork) jsr @SYMBOL_NAME(schedule_tail) jmp @SYMBOL_NAME(ret_from_exception) -SYMBOL_NAME_LABEL(ret_from_kernel_thread) - mov.l er2,er0 - jsr @SYMBOL_NAME(schedule_tail) - mov.l @(LER4:16,sp),er0 - mov.l @(LER5:16,sp),er1 - jsr @er1 - jmp @SYMBOL_NAME(ret_from_exception) - SYMBOL_NAME_LABEL(resume) /* * Beware - when entering resume, offset of tss is in d1, diff --git a/trunk/arch/h8300/kernel/h8300_ksyms.c b/trunk/arch/h8300/kernel/h8300_ksyms.c index 53d7c0e4bd83..6866bd9c7fb4 100644 --- a/trunk/arch/h8300/kernel/h8300_ksyms.c +++ b/trunk/arch/h8300/kernel/h8300_ksyms.c @@ -33,6 +33,7 @@ EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(ip_fast_csum); +EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); diff --git a/trunk/arch/h8300/kernel/process.c b/trunk/arch/h8300/kernel/process.c index 2a45718cc5e8..e8dc1393a13a 100644 --- a/trunk/arch/h8300/kernel/process.c +++ b/trunk/arch/h8300/kernel/process.c @@ -47,7 +47,6 @@ void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); /* * The idle loop on an H8/300.. @@ -123,6 +122,39 @@ void show_regs(struct pt_regs * regs) printk("\n"); } +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + long clone_arg; + mm_segment_t fs; + + fs = get_fs(); + set_fs (KERNEL_DS); + clone_arg = flags | CLONE_VM; + __asm__("mov.l sp,er3\n\t" + "sub.l er2,er2\n\t" + "mov.l %2,er1\n\t" + "mov.l %1,er0\n\t" + "trapa #0\n\t" + "cmp.l sp,er3\n\t" + "beq 1f\n\t" + "mov.l %4,er0\n\t" + "mov.l %3,er1\n\t" + "jsr @er1\n\t" + "mov.l %5,er0\n\t" + "trapa #0\n" + "1:\n\t" + "mov.l er0,%0" + :"=r"(retval) + :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit) + :"er0","er1","er2","er3"); + set_fs (fs); + return retval; +} + void flush_thread(void) { } @@ -166,13 +198,6 @@ int copy_thread(unsigned long clone_flags, childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; - if (unlikely(p->flags & PF_KTHREAD)) { - memset(childregs, 0, sizeof(struct pt_regs)); - childregs->retpc = (unsigned long) ret_from_kernel_thread; - childregs->er4 = topstk; /* arg */ - childregs->er5 = usp; /* fn */ - p->thread.ksp = (unsigned long)childregs; - } *childregs = *regs; childregs->retpc = (unsigned long) ret_from_fork; childregs->er0 = 0; @@ -183,6 +208,27 @@ int copy_thread(unsigned long clone_flags, return 0; } +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(const char *name, + const char *const *argv, + const char *const *envp, + int dummy, ...) +{ + int error; + struct filename *filename; + struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); + + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + return error; + error = do_execve(filename->name, argv, envp, regs); + putname(filename); + return error; +} + unsigned long thread_saved_pc(struct task_struct *tsk) { return ((struct pt_regs *)tsk->thread.esp0)->pc; diff --git a/trunk/arch/h8300/kernel/sys_h8300.c b/trunk/arch/h8300/kernel/sys_h8300.c index bf350cb7f597..4bdc7311784e 100644 --- a/trunk/arch/h8300/kernel/sys_h8300.c +++ b/trunk/arch/h8300/kernel/sys_h8300.c @@ -46,3 +46,29 @@ asmlinkage void syscall_print(void *dummy,...) ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); } #endif + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +asmlinkage +int kernel_execve(const char *filename, + const char *const argv[], + const char *const envp[]) +{ + register long res __asm__("er0"); + register const char *const *_c __asm__("er3") = envp; + register const char *const *_b __asm__("er2") = argv; + register const char * _a __asm__("er1") = filename; + __asm__ __volatile__ ("mov.l %1,er0\n\t" + "trapa #0\n\t" + : "=r" (res) + : "g" (__NR_execve), + "g" (_a), + "g" (_b), + "g" (_c) + : "cc", "memory"); + return res; +} + + diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index f807721e19a5..5183f43a2cf7 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/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/trunk/arch/m32r/include/asm/processor.h b/trunk/arch/m32r/include/asm/processor.h index da17253b5735..5767367550c6 100644 --- a/trunk/arch/m32r/include/asm/processor.h +++ b/trunk/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/trunk/arch/m32r/kernel/entry.S b/trunk/arch/m32r/kernel/entry.S index 225412bc227e..0c01543f10cd 100644 --- a/trunk/arch/m32r/kernel/entry.S +++ b/trunk/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/trunk/arch/m32r/kernel/process.c b/trunk/arch/m32r/kernel/process.c index e7366276ef30..fa89f027c04a 100644 --- a/trunk/arch/m32r/kernel/process.c +++ b/trunk/arch/m32r/kernel/process.c @@ -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(®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.. */ @@ -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/trunk/arch/m32r/kernel/sys_m32r.c b/trunk/arch/m32r/kernel/sys_m32r.c index d841fb6cc703..c3fdd632fba7 100644 --- a/trunk/arch/m32r/kernel/sys_m32r.c +++ b/trunk/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; -}