]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge branches 'no-rebases', 'arch-avr32', 'arch-blackfin', 'arch-cris', 'arch-h8300...
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 29 Nov 2012 02:52:07 +0000 (21:52 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 29 Nov 2012 02:52:07 +0000 (21:52 -0500)
165 files changed:
arch/arm64/Kconfig
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/syscalls.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/process.c
arch/arm64/kernel/sys.c
arch/arm64/kernel/sys32.S
arch/arm64/kernel/sys_compat.c
arch/avr32/Kconfig
arch/avr32/include/asm/processor.h
arch/avr32/include/asm/unistd.h
arch/avr32/kernel/Makefile
arch/avr32/kernel/entry-avr32b.S
arch/avr32/kernel/process.c
arch/avr32/kernel/sys_avr32.c [deleted file]
arch/avr32/kernel/syscall-stubs.S
arch/avr32/kernel/syscall_table.S
arch/blackfin/Kconfig
arch/blackfin/include/asm/processor.h
arch/blackfin/include/asm/unistd.h
arch/blackfin/kernel/entry.S
arch/blackfin/kernel/process.c
arch/blackfin/mach-common/entry.S
arch/c6x/Kconfig
arch/c6x/include/uapi/asm/unistd.h
arch/c6x/kernel/entry.S
arch/cris/Kconfig
arch/cris/arch-v10/kernel/entry.S
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v32/kernel/entry.S
arch/cris/arch-v32/kernel/process.c
arch/cris/include/asm/processor.h
arch/cris/include/asm/unistd.h
arch/cris/kernel/crisksyms.c
arch/h8300/Kconfig
arch/h8300/include/asm/processor.h
arch/h8300/include/asm/ptrace.h
arch/h8300/include/asm/unistd.h
arch/h8300/kernel/entry.S
arch/h8300/kernel/h8300_ksyms.c
arch/h8300/kernel/process.c
arch/h8300/kernel/sys_h8300.c
arch/hexagon/Kconfig
arch/hexagon/include/asm/processor.h
arch/hexagon/include/uapi/asm/ptrace.h
arch/hexagon/include/uapi/asm/unistd.h
arch/hexagon/kernel/process.c
arch/hexagon/kernel/signal.c
arch/hexagon/kernel/syscall.c
arch/hexagon/kernel/vm_entry.S
arch/ia64/Kconfig
arch/ia64/include/asm/processor.h
arch/ia64/include/asm/unistd.h
arch/ia64/kernel/entry.S
arch/ia64/kernel/head.S
arch/ia64/kernel/process.c
arch/m32r/Kconfig
arch/m32r/include/asm/processor.h
arch/m32r/include/asm/ptrace.h
arch/m32r/include/asm/unistd.h
arch/m32r/kernel/entry.S
arch/m32r/kernel/process.c
arch/m32r/kernel/sys_m32r.c
arch/m68k/Kconfig
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/entry.S
arch/microblaze/Kconfig
arch/microblaze/include/asm/processor.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/process.c
arch/microblaze/kernel/sys_microblaze.c
arch/mips/Kconfig
arch/mips/include/asm/processor.h
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/unistd.h
arch/mips/kernel/entry.S
arch/mips/kernel/linux32.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/process.c
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/syscall.c
arch/mn10300/Kconfig
arch/mn10300/include/asm/unistd.h
arch/mn10300/kernel/entry.S
arch/openrisc/Kconfig
arch/openrisc/include/uapi/asm/unistd.h
arch/openrisc/kernel/entry.S
arch/openrisc/kernel/process.c
arch/parisc/Kconfig
arch/parisc/include/asm/unistd.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/process.c
arch/parisc/kernel/sys_parisc32.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/Kconfig
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/process.c
arch/s390/Kconfig
arch/s390/include/asm/unistd.h
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/score/Kconfig
arch/score/include/asm/processor.h
arch/score/include/asm/syscalls.h
arch/score/include/asm/unistd.h
arch/score/kernel/entry.S
arch/score/kernel/process.c
arch/score/kernel/sys_score.c
arch/sh/Kconfig
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/sh/include/asm/syscalls_32.h
arch/sh/include/asm/syscalls_64.h
arch/sh/include/asm/unistd.h
arch/sh/kernel/Makefile
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/entry-common.S
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/sys_sh32.c
arch/sh/kernel/sys_sh64.c [deleted file]
arch/sparc/Kconfig
arch/sparc/include/asm/processor_32.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/switch_to_64.h
arch/sparc/include/asm/syscalls.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/uaccess_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/kernel/entry.S
arch/sparc/kernel/etrap_64.S
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/sys_sparc32.c
arch/sparc/kernel/sys_sparc_32.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/traps_64.c
arch/sparc/mm/init_64.c
arch/tile/Kconfig
arch/tile/include/asm/compat.h
arch/tile/include/asm/elf.h
arch/tile/include/asm/processor.h
arch/tile/include/asm/switch_to.h
arch/tile/include/asm/syscalls.h
arch/tile/include/asm/unistd.h
arch/tile/kernel/compat.c
arch/tile/kernel/compat_signal.c
arch/tile/kernel/entry.S
arch/tile/kernel/intvec_32.S
arch/tile/kernel/intvec_64.S
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/tile/kernel/sys.c
arch/tile/mm/fault.c
include/linux/compat.h

index 15ac18a56c93b78a2d3972e7196ce89875c2135c..20b688c81956149cfe8e93a540b9b40c42ff2ac3 100644 (file)
@@ -7,6 +7,8 @@ config ARM64
        select GENERIC_IOMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
+       select GENERIC_KERNEL_EXECVE
+       select GENERIC_KERNEL_THREAD
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL
        select HARDIRQS_SW_RESEND
index 77f696c143396d9bf93521d6444bf12dd4b82c01..ab239b2c456fa7c0e5950f92490166f0c38de9cf 100644 (file)
@@ -128,11 +128,6 @@ unsigned long get_wchan(struct task_struct *p);
 extern struct task_struct *cpu_switch_to(struct task_struct *prev,
                                         struct task_struct *next);
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index 09ff33572aab0eb41efbc409173abce71eb2c5f9..a1b00cd6f78635b3babdab3d499a5e44e9320504 100644 (file)
 /*
  * System call wrappers implemented in kernel/entry.S.
  */
-asmlinkage long sys_execve_wrapper(const char __user *filename,
-                                  const char __user *const __user *argv,
-                                  const char __user *const __user *envp);
-asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
-                                 unsigned long newsp,
-                                 void __user *parent_tid,
-                                 unsigned long tls_val,
-                                 void __user *child_tid);
 asmlinkage long sys_rt_sigreturn_wrapper(void);
 asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
                                        stack_t __user *uoss);
 
+/*
+ * AArch64 sys_clone implementation has a different prototype than the generic
+ * one (additional TLS value argument).
+ */
+#define sys_clone      sys_clone
+
 #include <asm-generic/syscalls.h>
 
 #endif /* __ASM_SYSCALLS_H */
index 68aff2816e8605113945a66e60e1dd2f5b5c2ade..43064a8bd99e4df93f6211fe3774e52c4e55fb5b 100644 (file)
@@ -25,4 +25,5 @@
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
+#define __ARCH_WANT_SYS_EXECVE
 #include <uapi/asm/unistd.h>
index 6d909faebf28d155020ef96e17654d5ae74bed6f..d9850cf9870ded8f0fa945f1d3d543ba939579e1 100644 (file)
@@ -23,7 +23,7 @@
 
 __SYSCALL(0,   sys_restart_syscall)
 __SYSCALL(1,   sys_exit)
-__SYSCALL(2,   compat_sys_fork_wrapper)
+__SYSCALL(2,   compat_sys_fork)
 __SYSCALL(3,   sys_read)
 __SYSCALL(4,   sys_write)
 __SYSCALL(5,   compat_sys_open)
@@ -32,7 +32,7 @@ __SYSCALL(7,   sys_ni_syscall)                        /* 7 was sys_waitpid */
 __SYSCALL(8,   sys_creat)
 __SYSCALL(9,   sys_link)
 __SYSCALL(10,  sys_unlink)
-__SYSCALL(11,  compat_sys_execve_wrapper)
+__SYSCALL(11,  compat_sys_execve)
 __SYSCALL(12,  sys_chdir)
 __SYSCALL(13,  sys_ni_syscall)                 /* 13 was sys_time */
 __SYSCALL(14,  sys_mknod)
@@ -141,7 +141,7 @@ __SYSCALL(116, compat_sys_sysinfo)
 __SYSCALL(117, sys_ni_syscall)                 /* 117 was sys_ipc */
 __SYSCALL(118, sys_fsync)
 __SYSCALL(119, compat_sys_sigreturn_wrapper)
-__SYSCALL(120, compat_sys_clone_wrapper)
+__SYSCALL(120, sys_clone)
 __SYSCALL(121, sys_setdomainname)
 __SYSCALL(122, sys_newuname)
 __SYSCALL(123, sys_ni_syscall)                 /* 123 was sys_modify_ldt */
@@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper)
 __SYSCALL(187, compat_sys_sendfile)
 __SYSCALL(188, sys_ni_syscall)                 /* 188 reserved */
 __SYSCALL(189, sys_ni_syscall)                 /* 189 reserved */
-__SYSCALL(190, compat_sys_vfork_wrapper)
+__SYSCALL(190, compat_sys_vfork)
 __SYSCALL(191, compat_sys_getrlimit)           /* SuS compliant getrlimit */
 __SYSCALL(192, sys_mmap_pgoff)
 __SYSCALL(193, compat_sys_truncate64_wrapper)
index a6f3f7da6880bbcfc8ef307206421cf85540d7da..cbfa4d28100ed0033f7755735d90657133327ca5 100644 (file)
@@ -594,7 +594,7 @@ work_resched:
 /*
  * "slow" syscall return path.
  */
-ENTRY(ret_to_user)
+ret_to_user:
        disable_irq                             // disable interrupts
        ldr     x1, [tsk, #TI_FLAGS]
        and     x2, x1, #_TIF_WORK_MASK
@@ -611,7 +611,10 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        bl      schedule_tail
-       get_thread_info tsk
+       cbz     x19, 1f                         // not a kernel thread
+       mov     x0, x20
+       blr     x19
+1:     get_thread_info tsk
        b       ret_to_user
 ENDPROC(ret_from_fork)
 
@@ -673,16 +676,6 @@ __sys_trace_return:
 /*
  * Special system call wrappers.
  */
-ENTRY(sys_execve_wrapper)
-       mov     x3, sp
-       b       sys_execve
-ENDPROC(sys_execve_wrapper)
-
-ENTRY(sys_clone_wrapper)
-       mov     x5, sp
-       b       sys_clone
-ENDPROC(sys_clone_wrapper)
-
 ENTRY(sys_rt_sigreturn_wrapper)
        mov     x0, sp
        b       sys_rt_sigreturn
index e04cebdbb47fc5a82ae6042169b098b8fae13d54..8a5f3341861e579bd7434393b23b82b6291bb19a 100644 (file)
@@ -240,27 +240,41 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct pt_regs *childregs = task_pt_regs(p);
        unsigned long tls = p->thread.tp_value;
 
-       *childregs = *regs;
-       childregs->regs[0] = 0;
+       memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
 
-       if (is_compat_thread(task_thread_info(p)))
-               childregs->compat_sp = stack_start;
-       else {
+       if (likely(regs)) {
+               *childregs = *regs;
+               childregs->regs[0] = 0;
+               if (is_compat_thread(task_thread_info(p))) {
+                       if (stack_start)
+                               childregs->compat_sp = stack_start;
+               } else {
+                       /*
+                        * Read the current TLS pointer from tpidr_el0 as it may be
+                        * out-of-sync with the saved value.
+                        */
+                       asm("mrs %0, tpidr_el0" : "=r" (tls));
+                       if (stack_start) {
+                               /* 16-byte aligned stack mandatory on AArch64 */
+                               if (stack_start & 15)
+                                       return -EINVAL;
+                               childregs->sp = stack_start;
+                       }
+               }
                /*
-                * Read the current TLS pointer from tpidr_el0 as it may be
-                * out-of-sync with the saved value.
+                * If a TLS pointer was passed to clone (4th argument), use it
+                * for the new thread.
                 */
-               asm("mrs %0, tpidr_el0" : "=r" (tls));
-               childregs->sp = stack_start;
+               if (clone_flags & CLONE_SETTLS)
+                       tls = regs->regs[3];
+       } else {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               childregs->pstate = PSR_MODE_EL1h;
+               p->thread.cpu_context.x19 = stack_start;
+               p->thread.cpu_context.x20 = stk_sz;
        }
-
-       memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
-       p->thread.cpu_context.sp = (unsigned long)childregs;
        p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
-
-       /* If a TLS pointer was passed to clone, use that for the new thread. */
-       if (clone_flags & CLONE_SETTLS)
-               tls = regs->regs[3];
+       p->thread.cpu_context.sp = (unsigned long)childregs;
        p->thread.tp_value = tls;
 
        ptrace_hw_copy_thread(p);
@@ -309,43 +323,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
        return last;
 }
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  x1 is the thread argument, x2 is the pointer to
- * the thread function, and x3 points to the exit function.
- */
-extern void kernel_thread_helper(void);
-asm(   ".section .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"      mov     x0, x1\n"
-"      mov     x30, x3\n"
-"      br      x2\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .previous");
-
-#define kernel_thread_exit     do_exit
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.regs[1] = (unsigned long)arg;
-       regs.regs[2] = (unsigned long)fn;
-       regs.regs[3] = (unsigned long)kernel_thread_exit;
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.pstate = PSR_MODE_EL1h;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index b120df37de3552e5a68479294ef9e6b037ea97fb..4364df85050e79f7e838745531f01d7b30a82b8c 100644 (file)
  */
 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
                          int __user *parent_tidptr, unsigned long tls_val,
-                         int __user *child_tidptr, struct pt_regs *regs)
+                         int __user *child_tidptr)
 {
-       if (!newsp)
-               newsp = regs->sp;
-       /* 16-byte aligned stack mandatory on AArch64 */
-       if (newsp & 15)
-               return -EINVAL;
-       return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage long sys_execve(const char __user *filenamei,
-                          const char __user *const __user *argv,
-                          const char __user *const __user *envp,
-                          struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(filenamei);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.regs[0] = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm(    "add    x0, %0, %1\n\t"
-               "mov    x1, %2\n\t"
-               "mov    x2, %3\n\t"
-               "bl     memmove\n\t"    /* copy regs to top of stack */
-               "mov    x27, #0\n\t"    /* not a syscall */
-               "mov    x28, %0\n\t"    /* thread structure */
-               "mov    sp, x0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "x0", "x1", "x2", "x27", "x28", "x30", "memory");
-
- out:
-       return ret;
+       return do_fork(clone_flags, newsp, current_pt_regs(), 0,
+                       parent_tidptr, child_tidptr);
 }
-EXPORT_SYMBOL(kernel_execve);
 
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                         unsigned long prot, unsigned long flags,
@@ -118,8 +50,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 /*
  * Wrappers to pass the pt_regs argument.
  */
-#define sys_execve             sys_execve_wrapper
-#define sys_clone              sys_clone_wrapper
 #define sys_rt_sigreturn       sys_rt_sigreturn_wrapper
 #define sys_sigaltstack                sys_sigaltstack_wrapper
 
index 54c4aec47a088f9d32382980011b3cab6336fb80..7ef59e9245effa59f360c097bcdd300fa2e0e334 100644 (file)
 /*
  * System call wrappers for the AArch32 compatibility layer.
  */
-compat_sys_fork_wrapper:
-       mov     x0, sp
-       b       compat_sys_fork
-ENDPROC(compat_sys_fork_wrapper)
-
-compat_sys_vfork_wrapper:
-       mov     x0, sp
-       b       compat_sys_vfork
-ENDPROC(compat_sys_vfork_wrapper)
-
-compat_sys_execve_wrapper:
-       mov     x3, sp
-       b       compat_sys_execve
-ENDPROC(compat_sys_execve_wrapper)
-
-compat_sys_clone_wrapper:
-       mov     x5, sp
-       b       compat_sys_clone
-ENDPROC(compat_sys_clone_wrapper)
 
 compat_sys_sigreturn_wrapper:
        mov     x0, sp
index 906e3bd270b06de91bbab8505df7877ca0300922..6fabc1912da0eaf6b3b0c9f0cbad4cf98fca9c74 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/unistd32.h>
 
-asmlinkage int compat_sys_fork(struct pt_regs *regs)
+asmlinkage int compat_sys_fork(void)
 {
-       return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL);
 }
 
-asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,
-                         int __user *parent_tidptr, int tls_val,
-                         int __user *child_tidptr, struct pt_regs *regs)
+asmlinkage int compat_sys_vfork(void)
 {
-       if (!newsp)
-               newsp = regs->compat_sp;
-
-       return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-asmlinkage int compat_sys_vfork(struct pt_regs *regs)
-{
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,
-                      regs, 0, NULL, NULL);
-}
-
-asmlinkage int compat_sys_execve(const char __user *filenamei,
-                                compat_uptr_t argv, compat_uptr_t envp,
-                                struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname(filenamei);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = compat_do_execve(filename->name, compat_ptr(argv),
-                                       compat_ptr(envp), regs);
-       putname(filename);
-out:
-       return error;
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
+                      current_pt_regs(), 0, NULL, NULL);
 }
 
 asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
index 06e73bf665e92cba042590dbe68a50a463d50f76..649aeb9acecb4d0f3f5267038501e2822b10cf7e 100644 (file)
@@ -17,6 +17,8 @@ config AVR32
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          AVR32 is a high-performance 32-bit RISC microprocessor core,
          designed for cost-sensitive embedded applications, with particular
index 87d8baccc60e908c475c72dff993e4f5ec79a817..48d71c5c898a18d083f8a55da807c103d7515458 100644 (file)
@@ -142,9 +142,6 @@ struct task_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);
-
 /* Return saved PC of a blocked thread */
 #define thread_saved_pc(tsk)    ((tsk)->thread.cpu_context.pc)
 
index 157b4bd3d5e50aa23942f5b63640f40c3133d966..641023d1bcb5eb000e7932d72d50a9a8da987f9f 100644 (file)
@@ -39,6 +39,7 @@
 #define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 9e2c465ef3a6fd692a70115dc53eb2b366edcedb..119a2e41defe46557fa0d33c1d8320ca61bc6de0 100644 (file)
@@ -7,7 +7,7 @@ extra-y                         := head.o vmlinux.lds
 obj-$(CONFIG_SUBARCH_AVR32B)   += entry-avr32b.o
 obj-y                          += syscall_table.o syscall-stubs.o irq.o
 obj-y                          += setup.o traps.o ocd.o ptrace.o
-obj-y                          += signal.o sys_avr32.o process.o time.o
+obj-y                          += signal.o process.o time.o
 obj-y                          += switch_to.o cpu.o
 obj-$(CONFIG_MODULES)          += module.o avr32_ksyms.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
index df28841813139f658a3511daaacb5aa14012dd80..9899d3cc6f03b109f352faa9ac51387f96497cf7 100644 (file)
@@ -251,13 +251,15 @@ syscall_badsys:
        .global ret_from_fork
 ret_from_fork:
        call   schedule_tail
+       mov     r12, 0
+       rjmp    syscall_return
 
-       /* check for syscall tracing */
-       get_thread_info r0
-       ld.w    r1, r0[TI_flags]
-       andl    r1, _TIF_ALLWORK_MASK, COH
-       brne    syscall_exit_work
-       rjmp    syscall_exit_cont
+       .global ret_from_kernel_thread
+ret_from_kernel_thread:
+       call   schedule_tail
+       mov     r12, r0
+       mov     lr, r2  /* syscall_return */
+       mov     pc, r1
 
 syscall_trace_enter:
        pushm   r8-r12
index 1bb0a8abd79b5078267ad4e6c9c84832033d0e92..09b894d96d6e21aefadab9283a480e0b724f01e9 100644 (file)
@@ -68,44 +68,6 @@ void machine_restart(char *cmd)
        while (1) ;
 }
 
-/*
- * PC is actually discarded when returning from a system call -- the
- * return address must be stored in LR. This function will make sure
- * LR points to do_exit before starting the thread.
- *
- * Also, when returning from fork(), r12 is 0, so we must copy the
- * argument as well.
- *
- *  r0 : The argument to the main thread function
- *  r1 : The address of do_exit
- *  r2 : The address of the main thread function
- */
-asmlinkage extern void kernel_thread_helper(void);
-__asm__("      .type   kernel_thread_helper, @function\n"
-       "kernel_thread_helper:\n"
-       "       mov     r12, r0\n"
-       "       mov     lr, r2\n"
-       "       mov     pc, r1\n"
-       "       .size   kernel_thread_helper, . - kernel_thread_helper");
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.r0 = (unsigned long)arg;
-       regs.r1 = (unsigned long)fn;
-       regs.r2 = (unsigned long)do_exit;
-       regs.lr = (unsigned long)kernel_thread_helper;
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.sr = MODE_SUPERVISOR;
-
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-                      0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Free current thread data structures etc
  */
@@ -332,26 +294,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 }
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
+asmlinkage void syscall_return(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs *childregs;
-
-       childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;
-       *childregs = *regs;
-
-       if (user_mode(regs))
+       struct pt_regs *childregs = task_pt_regs(p);
+
+       if (unlikely(!regs)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               p->thread.cpu_context.r0 = arg;
+               p->thread.cpu_context.r1 = usp; /* fn */
+               p->thread.cpu_context.r2 = syscall_return;
+               p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+               childregs->sr = MODE_SUPERVISOR;
+       } else {
+               *childregs = *regs;
                childregs->sp = usp;
-       else
-               childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-
-       childregs->r12 = 0; /* Set return value for child */
+               childregs->r12 = 0; /* Set return value for child */
+               p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+       }
 
        p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;
        p->thread.cpu_context.ksp = (unsigned long)childregs;
-       p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
 
        clear_tsk_thread_flag(p, TIF_DEBUG);
        if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))
@@ -382,27 +349,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
                       0, NULL, NULL);
 }
 
-asmlinkage int sys_execve(const char __user *ufilename,
-                         const char __user *const __user *uargv,
-                         const char __user *const __user *uenvp,
-                         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, regs);
-       putname(filename);
-
-out:
-       return error;
-}
-
-
 /*
  * This function is supposed to answer the question "who called
  * schedule()?"
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c
deleted file mode 100644 (file)
index 62635a0..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/unistd.h>
-
-int kernel_execve(const char *file,
-                 const char *const *argv,
-                 const char *const *envp)
-{
-       register long scno asm("r8") = __NR_execve;
-       register long sc1 asm("r12") = (long)file;
-       register long sc2 asm("r11") = (long)argv;
-       register long sc3 asm("r10") = (long)envp;
-
-       asm volatile("scall"
-                    : "=r"(sc1)
-                    : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3)
-                    : "cc", "memory");
-       return sc1;
-}
index 0447a3e2ba64b773c108fb7f5db9935329fcbc21..285a61b9194e05cdbc8c750b4662b37c72f737aa 100644 (file)
@@ -50,12 +50,6 @@ __sys_vfork:
        mov     r12, sp
        rjmp    sys_vfork
 
-       .global __sys_execve
-       .type   __sys_execve,@function
-__sys_execve:
-       mov     r9, sp
-       rjmp    sys_execve
-
        .global __sys_mmap2
        .type   __sys_mmap2,@function
 __sys_mmap2:
index 6eba53530d1c552ea9813a16419a679c27075415..fc649770681998f72f03d0a302cb8d898224a2cd 100644 (file)
@@ -24,7 +24,7 @@ sys_call_table:
        .long   sys_creat
        .long   sys_link
        .long   sys_unlink              /* 10 */
-       .long   __sys_execve
+       .long   sys_execve
        .long   sys_chdir
        .long   sys_time
        .long   sys_mknod
index b6f3ad5441c5f33f27c44850ca8d19c9898001b7..ab9ff4075f4d3b075692882234bb118a9d9b0349 100644 (file)
@@ -45,6 +45,8 @@ config BLACKFIN
        select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config GENERIC_CSUM
        def_bool y
index 4ef7cfe43cebce8441a88c5dc876f980760e65ef..d0e72e9475a6ba3627fcad60ff3f6e3f34cdc15d 100644 (file)
@@ -75,8 +75,6 @@ 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..
  */
index 5b2a0748d7d3e8b215c0d2aba4a3df3319743858..b4ec1bb3d5d461539704a88eff322b001e9260a1 100644 (file)
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index f33792cc1a0d8a9b9cd553d379726886f5c3c22e..78f4f637e155a50afec8b3134522ce0844f13cee 100644 (file)
@@ -46,22 +46,16 @@ ENTRY(_ret_from_fork)
        SP += -12;
        pseudo_long_call _schedule_tail, p5;
        SP += 12;
-       r0 = [sp + PT_IPEND];
-       cc = bittst(r0,1);
-       if cc jump .Lin_kernel;
+       p1 = [sp++];
+       r0 = [sp++];
+       cc = p1 == 0;
+       if cc jump .Lfork;
+       sp += -12;
+       call (p1);
+       sp += 12;
+.Lfork:
        RESTORE_CONTEXT
        rti;
-.Lin_kernel:
-       bitclr(r0,1);
-       [sp + PT_IPEND] = r0;
-       /* do a 'fake' RTI by jumping to [RETI]
-        * to avoid clearing supervisor mode in child
-        */
-       r0 = [sp + PT_PC];
-       [sp + PT_P0] = r0;
-
-       RESTORE_ALL_SYS
-       jump (p0);
 ENDPROC(_ret_from_fork)
 
 ENTRY(_sys_vfork)
index bb1cc721fcf7e18ee26b5bf7a7bc0b2912815ad6..da8df0e504ac6ef4e6529f7d128437724d6572af 100644 (file)
@@ -101,40 +101,6 @@ void cpu_idle(void)
        }
 }
 
-/*
- * This gets run with P1 containing the
- * function to call, and R1 containing
- * the "args".  Note P0 is clobbered on the way here.
- */
-void kernel_thread_helper(void);
-__asm__(".section .text\n"
-       ".align 4\n"
-       "_kernel_thread_helper:\n\t"
-       "\tsp += -12;\n\t"
-       "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.r1 = (unsigned long)arg;
-       regs.p1 = (unsigned long)fn;
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.orig_p0 = -1;
-       /* Set bit 2 to tell ret_from_fork we should be returning to kernel
-          mode.  */
-       regs.ipend = 0x8002;
-       __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
-                      NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Do necessary setup to start up a newly executed thread.
  *
@@ -193,38 +159,31 @@ copy_thread(unsigned long clone_flags,
            struct task_struct *p, struct pt_regs *regs)
 {
        struct pt_regs *childregs;
+       unsigned long *v;
 
        childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-       *childregs = *regs;
-       childregs->r0 = 0;
+       v = ((unsigned long *)childregs) - 2;
+       if (unlikely(!regs)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               v[0] = usp;
+               v[1] = topstk;
+               childregs->orig_p0 = -1;
+               childregs->ipend = 0x8000;
+               __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):);
+               p->thread.usp = 0;
+       } else {
+               *childregs = *regs;
+               childregs->r0 = 0;
+               p->thread.usp = usp;
+               v[0] = v[1] = 0;
+       }
 
-       p->thread.usp = usp;
-       p->thread.ksp = (unsigned long)childregs;
+       p->thread.ksp = (unsigned long)v;
        p->thread.pc = (unsigned long)ret_from_fork;
 
        return 0;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp)
-{
-       int error;
-       struct filename *filename;
-       struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
-
-       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 get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
index 1c3d2c5bb0bb873fcec8f65eb48379279e479c65..4a38c68e2ddee43486160a505a97f28c6dee5d44 100644 (file)
@@ -530,61 +530,6 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
        jump .Lsyscall_really_exit;
 ENDPROC(_trap)
 
-ENTRY(_kernel_execve)
-       link SIZEOF_PTREGS;
-       p0 = sp;
-       r3 = SIZEOF_PTREGS / 4;
-       r4 = 0(x);
-.Lclear_regs:
-       [p0++] = r4;
-       r3 += -1;
-       cc = r3 == 0;
-       if !cc jump .Lclear_regs (bp);
-
-       p0 = sp;
-       sp += -16;
-       [sp + 12] = p0;
-       pseudo_long_call _do_execve, p5;
-       SP += 16;
-       cc = r0 == 0;
-       if ! cc jump .Lexecve_failed;
-       /* Success.  Copy our temporary pt_regs to the top of the kernel
-        * stack and do a normal exception return.
-        */
-       r1 = sp;
-       r0 = (-KERNEL_STACK_SIZE) (x);
-       r1 = r1 & r0;
-       p2 = r1;
-       p3 = [p2];
-       r0 = KERNEL_STACK_SIZE - 4 (z);
-       p1 = r0;
-       p1 = p1 + p2;
-
-       p0 = fp;
-       r4 = [p0--];
-       r3 = SIZEOF_PTREGS / 4;
-.Lcopy_regs:
-       r4 = [p0--];
-       [p1--] = r4;
-       r3 += -1;
-       cc = r3 == 0;
-       if ! cc jump .Lcopy_regs (bp);
-
-       r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
-       p1 = r0;
-       p1 = p1 + p2;
-       sp = p1;
-       r0 = syscfg;
-       [SP + PT_SYSCFG] = r0;
-       [p3 + (TASK_THREAD + THREAD_KSP)] = sp;
-
-       RESTORE_CONTEXT;
-       rti;
-.Lexecve_failed:
-       unlink;
-       rts;
-ENDPROC(_kernel_execve)
-
 ENTRY(_system_call)
        /* Store IPEND */
        p2.l = lo(IPEND);
index aee1b569ee6e56c5aa8fa1ee609e91dcff6632f9..66eab3703c7571e77d608609c4e401ffce0ffd77 100644 (file)
@@ -18,6 +18,7 @@ config C6X
        select OF_EARLY_FLATTREE
        select GENERIC_CLOCKEVENTS
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select MODULES_USE_ELF_RELA
 
 config MMU
index 4ff747d12dad317e408c86bf8df6285bb31d980b..625beafb9cd152f1d0489beaa1edf57464b1887a 100644 (file)
@@ -14,7 +14,6 @@
  *   more details.
  */
 
-#define __ARCH_WANT_KERNEL_EXECVE
 #define __ARCH_WANT_SYS_EXECVE
 
 /* Use the standard ABI for syscalls. */
index 5449c36018fe2d269b2daaa162a25a39bfa53c9b..75f6f36472cfa8cd5bdb29057d0d2b1b904ef70f 100644 (file)
@@ -413,19 +413,9 @@ ENTRY(ret_from_kernel_thread)
 0:
        B       .S2     B10                /* call fn */
        LDW     .D2T1   *+SP(REGS_A1+8),A4 /* get arg */
-       MVKL    .S2     sys_exit,B11
-       MVKH    .S2     sys_exit,B11
-       ADDKPC  .S2     0f,B3,1
-0:
-       BNOP    .S2     B11,5   /* jump to sys_exit */
+       ADDKPC  .S2     ret_from_fork_2,B3,3
 ENDPROC(ret_from_kernel_thread)
 
-ENTRY(ret_from_kernel_execve)
-       GET_THREAD_INFO A12
-       BNOP    .S2     syscall_exit,4
-       ADD     .D2X    A4,-8,SP
-ENDPROC(ret_from_kernel_execve)
-
        ;;
        ;; These are the interrupt handlers, responsible for calling __do_IRQ()
        ;; int6 is used for syscalls (see _system_call entry)
index a67244473a39fb78948b97fa5b4c8f3ff2551d60..81b59d18867ec68be4995bb00adf1b8c1e37f65a 100644 (file)
@@ -49,6 +49,8 @@ config CRIS
        select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
        select GENERIC_CMOS_UPDATE
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config HZ
        int
index 592fbe9dfb629cc84bf126855fd80df16aa53bff..897bba67bf7afed9a0b392db5d652349ae352f6c 100644 (file)
@@ -35,6 +35,7 @@
        .globl system_call
        .globl ret_from_intr
        .globl ret_from_fork
+       .globl ret_from_kernel_thread
        .globl resume
        .globl multiple_interrupt
        .globl hwbreakpoint
@@ -81,7 +82,14 @@ ret_from_fork:
        jsr schedule_tail
        ba  ret_from_sys_call
        nop
-               
+
+ret_from_kernel_thread:
+       jsr schedule_tail
+       move.d  $r2, $r10       ; argument is here
+       jsr     $r1             ; call the payload
+       moveq   0, $r9          ; no syscall restarts, TYVM...
+       ba  ret_from_sys_call
+
 ret_from_intr:
        ;; check for resched if preemptive kernel or if we're going back to user-mode 
        ;; this test matches the user_regs(regs) macro
@@ -586,13 +594,6 @@ _ugdb_handle_breakpoint:
        ba      do_sigtrap              ; SIGTRAP the offending process. 
        pop     $dccr                   ; Restore dccr in delay slot.
 
-       .global kernel_execve
-kernel_execve:
-       move.d __NR_execve, $r9
-       break 13
-       ret
-       nop
-
        .data
 
 hw_bp_trigs:
index 15ac7150371f719965479c9447a4bfd70b600512..1d6458287f380ea8979b93b1fdf3539ec5346720 100644 (file)
@@ -17,6 +17,7 @@
 #include <arch/svinto.h>
 #include <linux/init.h>
 #include <arch/system.h>
+#include <asm/ptrace.h>
 
 #ifdef CONFIG_ETRAX_GPIO
 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
@@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
        return task_pt_regs(t)->irp;
 }
 
-static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
-{
-  fn(arg);
-  do_exit(-1); /* Should never be called, return bad exit value */
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-        /* Don't use r10 since that is set to 0 in copy_thread */
-       regs.r11 = (unsigned long)fn;
-       regs.r12 = (unsigned long)arg;
-       regs.irp = (unsigned long)kernel_thread_helper;
-       regs.dccr = 1 << I_DCCR_BITNR;
-
-       /* Ok, create the new process.. */
-        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
 /* setup the child's kernel stack with a pt_regs and switch_stack on it.
  * it will be un-nested during _resume and _ret_from_sys_call when the
  * new thread is scheduled.
@@ -115,29 +91,35 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  *
  */
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs * childregs;
-       struct switch_stack *swstack;
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1;
        
        /* put the pt_regs structure at the end of the new kernel stack page and fix it up
         * remember that the task_struct doubles as the kernel stack for the task
         */
 
-       childregs = task_pt_regs(p);
-        
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(swstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               swstack->r1 = usp;
+               swstack->r2 = arg;
+               childregs->dccr = 1 << I_DCCR_BITNR;
+               swstack->return_ip = (unsigned long) ret_from_kernel_thread;
+               p->thread.ksp = (unsigned long) swstack;
+               p->thread.usp = 0;
+               return 0;
+       }
        *childregs = *regs;  /* struct copy of pt_regs */
-        
-        p->set_child_tid = p->clear_child_tid = NULL;
 
         childregs->r10 = 0;  /* child returns 0 after a fork/clone */
-       
-       /* put the switch stack right below the pt_regs */
 
-       swstack = ((struct switch_stack *)childregs) - 1;
+       /* put the switch stack right below the pt_regs */
 
        swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */
 
@@ -147,7 +129,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        
        /* fix the user-mode stackpointer */
 
-       p->thread.usp = usp;    
+       p->thread.usp = usp;
 
        /* and the kernel-mode one */
 
@@ -161,68 +143,28 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-/* 
- * Be aware of the "magic" 7th argument in the four system-calls below.
- * They need the latest stackframe, which is put as the 7th argument by
- * entry.S. The previous arguments are dummies or actually used, but need
- * to be defined to reach the 7th argument.
- *
- * N.B.: Another method to get the stackframe is to use current_regs(). But
- * it returns the latest stack-frame stacked when going from _user mode_ and
- * some of these (at least sys_clone) are called from kernel-mode sometimes
- * (for example during kernel_thread, above) and thus cannot use it. Thus,
- * to be sure not to get any surprises, we use the method for the other calls
- * as well.
- */
-
-asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
-                       struct pt_regs *regs)
+asmlinkage int sys_fork(void)
 {
-       return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);
 }
 
 /* if newusp is 0, we just grab the old usp */
 /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
 asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
-                        int* parent_tid, int* child_tid, long mof, long srp,
-                        struct pt_regs *regs)
+                        int* parent_tid, int* child_tid)
 {
        if (!newusp)
                newusp = rdusp();
-       return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
+       return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid);
 }
 
 /* vfork is a system call in i386 because of register-pressure - maybe
  * we can remove it and handle it in libc but we put it here until then.
  */
 
-asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
-                        struct pt_regs *regs)
-{
-        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *fname,
-                         const char *const *argv,
-                         const char *const *envp,
-                         long r13, long mof, long srp, 
-                         struct pt_regs *regs)
+asmlinkage int sys_vfork(void)
 {
-       int error;
-       struct filename *filename;
-
-       filename = getname(fname);
-       error = PTR_ERR(filename);
-
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
- out:
-       return error;
+        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);
 }
 
 unsigned long get_wchan(struct task_struct *p)
index c3ea4694fbaf879c5b83e20b286e22587361dd22..faa644111feb7f4acb1eb87929177fdc3cdc3dc6 100644 (file)
@@ -31,6 +31,7 @@
        .globl system_call
        .globl ret_from_intr
        .globl ret_from_fork
+       .globl ret_from_kernel_thread
        .globl resume
        .globl multiple_interrupt
        .globl nmi_interrupt
@@ -84,6 +85,18 @@ ret_from_fork:
        nop
        .size   ret_from_fork, . - ret_from_fork
 
+       .type   ret_from_kernel_thread,@function
+ret_from_kernel_thread:
+       jsr schedule_tail
+       nop
+       move.d  $r2, $r10
+       jsr     $r1
+       nop
+       moveq   0, $r9                  ; no syscall restarts, TYVM...
+       ba  ret_from_sys_call
+       nop
+       .size   ret_from_kernel_thread, . - ret_from_kernel_thread
+
        .type   ret_from_intr,@function
 ret_from_intr:
        ;; Check for resched if preemptive kernel, or if we're going back to
@@ -531,15 +544,6 @@ _ugdb_handle_exception:
        ba      do_sigtrap              ; SIGTRAP the offending process.
        move.d  [$sp+], $r0             ; Restore R0 in delay slot.
 
-       .global kernel_execve
-       .type   kernel_execve,@function
-kernel_execve:
-       move.d __NR_execve, $r9
-       break 13
-       ret
-       nop
-       .size   kernel_execve, . - kernel_execve
-
        .data
 
        .section .rodata,"a"
index 4e9992246359ee7a21e9052f56f60e589b8c72a8..fe465401b6eca41bcc3a0cbd60fe6dea0ba149dd 100644 (file)
@@ -16,6 +16,7 @@
 #include <hwregs/reg_map.h>
 #include <hwregs/timer_defs.h>
 #include <hwregs/intr_vect_defs.h>
+#include <asm/ptrace.h>
 
 extern void stop_watchdog(void);
 
@@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
        return task_pt_regs(t)->erp;
 }
 
-static void
-kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
-{
-       fn(arg);
-       do_exit(-1); /* Should never be called, return bad exit value. */
-}
-
-/* Create a kernel thread. */
-int
-kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-        /* Don't use r10 since that is set to 0 in copy_thread. */
-       regs.r11 = (unsigned long) fn;
-       regs.r12 = (unsigned long) arg;
-       regs.erp = (unsigned long) kernel_thread_helper;
-       regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
-
-       /* Create the new process. */
-        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.
  * It will be unnested during _resume and _ret_from_sys_call when the new thread
@@ -129,23 +105,33 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
  */
 
 extern asmlinkage void ret_from_fork(void);
+extern asmlinkage void ret_from_kernel_thread(void);
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-       unsigned long unused,
+       unsigned long arg,
        struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs *childregs;
-       struct switch_stack *swstack;
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1;
 
        /*
         * Put the pt_regs structure at the end of the new kernel stack page and
         * fix it up. Note: the task_struct doubles as the kernel stack for the
         * task.
         */
-       childregs = task_pt_regs(p);
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(swstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               swstack->r1 = usp;
+               swstack->r2 = arg;
+               childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);
+               swstack->return_ip = (unsigned long) ret_from_kernel_thread;
+               p->thread.ksp = (unsigned long) swstack;
+               p->thread.usp = 0;
+               return 0;
+       }
        *childregs = *regs;     /* Struct copy of pt_regs. */
-        p->set_child_tid = p->clear_child_tid = NULL;
         childregs->r10 = 0;    /* Child returns 0 after a fork/clone. */
 
        /* Set a new TLS ?
@@ -156,7 +142,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        }
 
        /* Put the switch stack right below the pt_regs. */
-       swstack = ((struct switch_stack *) childregs) - 1;
 
        /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */
        swstack->r9 = 0;
@@ -174,35 +159,21 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-/*
- * Be aware of the "magic" 7th argument in the four system-calls below.
- * They need the latest stackframe, which is put as the 7th argument by
- * entry.S. The previous arguments are dummies or actually used, but need
- * to be defined to reach the 7th argument.
- *
- * N.B.: Another method to get the stackframe is to use current_regs(). But
- * it returns the latest stack-frame stacked when going from _user mode_ and
- * some of these (at least sys_clone) are called from kernel-mode sometimes
- * (for example during kernel_thread, above) and thus cannot use it. Thus,
- * to be sure not to get any surprises, we use the method for the other calls
- * as well.
- */
 asmlinkage int
-sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,
-       struct pt_regs *regs)
+sys_fork(void)
 {
-       return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);
 }
 
 /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */
 asmlinkage int
 sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid,
-       unsigned long tls, long srp, struct pt_regs *regs)
+       unsigned long tls)
 {
        if (!newusp)
                newusp = rdusp();
 
-       return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
+       return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid);
 }
 
 /*
@@ -210,32 +181,9 @@ sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child
  * we can remove it and handle it in libc but we put it here until then.
  */
 asmlinkage int
-sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,
-       struct pt_regs *regs)
-{
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-/* sys_execve() executes a new program. */
-asmlinkage int
-sys_execve(const char *fname,
-          const char *const *argv,
-          const char *const *envp, long r13, long mof, long srp,
-          struct pt_regs *regs)
+sys_vfork(void)
 {
-       int error;
-       struct filename *filename;
-
-       filename = getname(fname);
-       error = PTR_ERR(filename);
-
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
- out:
-       return error;
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);
 }
 
 unsigned long
index ef4e1bc3efc88686fbc4092f1e3661adffa285dc..675823f70c0f0222f51f69fc2c9aaea92ce0e9eb 100644 (file)
@@ -49,8 +49,6 @@ struct task_struct;
 #define task_pt_regs(task) user_regs(task_thread_info(task))
 #define current_regs() task_pt_regs(current)
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
index 51873a446f87e870f44db25c3dcfd2d1522eb0d2..f181d1fc76326e0846fe2c2f584e41e5f3e16b81 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 7ac000f6a888d0d368468f38bee411877ad9034a..5868cee20ebd8bdb3940ba14ce55982ca8961e9a 100644 (file)
@@ -30,7 +30,6 @@ extern void __negdi2(void);
 extern void iounmap(volatile void * __iomem);
 
 /* Platform dependent support */
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(get_cmos_time);
 EXPORT_SYMBOL(loops_per_usec);
 
index 98fabd10e95fbb6f9a6b2d44700e0ae68fda3b68..04bef4d25b4aa0d6e2032794227865abc1b0e947 100644 (file)
@@ -8,6 +8,8 @@ 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
index 4c9f6f87b6179f1c493ee3f2ed289dcda0a46bdc..4b0ca49bb463ef65f497213df54b1fea6e970af8 100644 (file)
@@ -107,8 +107,6 @@ 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..
  */
index d09c440bdba7a79eaf58bc17fc3537c273fd8b9d..00502a61bf0a428c4e050bdbd5ddac413013e4b2 100644 (file)
@@ -60,6 +60,8 @@ 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 */
index 5cd882801d7980ae47455febe80b30a8cd4b27b0..07afcfaec9951317b30491383787ec3158965b15 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index ca7431690300a15fe5dc3ed0b61ad35756d363fd..617a6878787fa69571b91ebcb54d84cd6262c3c4 100644 (file)
@@ -158,6 +158,7 @@ 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)
@@ -330,6 +331,14 @@ 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,
index 6866bd9c7fb4e4a6a198d2a6af94be950d5f51fb..53d7c0e4bd83720d9dec8849a9b37b53d845f963 100644 (file)
@@ -33,7 +33,6 @@ EXPORT_SYMBOL(strncmp);
 
 EXPORT_SYMBOL(ip_fast_csum);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 
index e8dc1393a13a9c646f382b02d6111e085442012b..2a45718cc5e8e062ef880df8afcdcd6cf9e79295 100644 (file)
@@ -47,6 +47,7 @@ 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..
@@ -122,39 +123,6 @@ 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)
 {
 }
@@ -198,6 +166,13 @@ 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;
@@ -208,27 +183,6 @@ 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;
index 4bdc7311784e7297ac6f0bbb67073bd2e41d1ae5..bf350cb7f597907ac9846a39a24514c6a2d304c7 100644 (file)
@@ -46,29 +46,3 @@ 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;
-}
-
-
index 0744f7d7b1fd096b5ccbc71cab7305ea997fb3c3..e418803b6c8eb71dcf838829b4beebbea835819a 100644 (file)
@@ -31,6 +31,8 @@ config HEXAGON
        select GENERIC_CLOCKEVENTS
        select GENERIC_CLOCKEVENTS_BROADCAST
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        ---help---
          Qualcomm Hexagon is a processor architecture designed for high
          performance and low power across a wide variety of applications.
index a03323ab9d44040a3db7902b1215615ff9fc5ef2..6dd5d37068698bd4bcb161f50dac5dcf9de93658 100644 (file)
@@ -34,7 +34,6 @@
 struct task_struct;
 
 /*  this is defined in arch/process.c  */
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
index 8ef784047a740248cdbca67377a656721b6b0769..1ffce0c6ee07559082fa475271e7656c2bbe3f9c 100644 (file)
@@ -32,4 +32,8 @@
 extern int regs_query_register_offset(const char *name);
 extern const char *regs_query_register_name(unsigned int offset);
 
+#define current_pt_regs() \
+       ((struct pt_regs *) \
+        ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 #endif
index 81312d6a52e687d1a3f75f22997ce09cd261610a..26b2e0f909c8664d3c6e342db44cc5ad4954aece 100644 (file)
@@ -27,5 +27,6 @@
  */
 
 #define sys_mmap2 sys_mmap_pgoff
+#define __ARCH_WANT_SYS_EXECVE
 
 #include <asm-generic/unistd.h>
index 9f6d7411b5747d87901e59733c1d1646ec72d631..cfbc52bd522747e6a4413a3895d9c580d81fb3a4 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 
-/*
- * Kernel thread creation.  The desired kernel function is "wrapped"
- * in the kernel_thread_helper function, which does cleanup
- * afterwards.
- */
-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-       do_exit(fn(arg));
-}
-
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-       /*
-        * Yes, we're exploting illicit knowledge of the ABI here.
-        */
-       regs.r00 = (unsigned long) arg;
-       regs.r01 = (unsigned long) fn;
-       pt_set_elr(&regs, (unsigned long)kernel_thread_helper);
-       pt_set_kmode(&regs);
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Program thread launch.  Often defined as a macro in processor.h,
  * but we're shooting for a small footprint and it's not an inner-loop
@@ -114,7 +87,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
  * Copy architecture-specific thread state
  */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused, struct task_struct *p,
+               unsigned long arg, struct task_struct *p,
                struct pt_regs *regs)
 {
        struct thread_info *ti = task_thread_info(p);
@@ -125,61 +98,50 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -
                                        sizeof(*childregs));
 
-       memcpy(childregs, regs, sizeof(*childregs));
        ti->regs = childregs;
 
        /*
         * Establish kernel stack pointer and initial PC for new thread
+        * Note that unlike the usual situation, we do not copy the
+        * parent's callee-saved here; those are in pt_regs and whatever
+        * we leave here will be overridden on return to userland.
         */
        ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -
                                                    sizeof(*ss));
        ss->lr = (unsigned long)ret_from_fork;
        p->thread.switch_sp = ss;
-
-       /* If User mode thread, set pt_reg stack pointer as per parameter */
-       if (user_mode(childregs)) {
-               pt_set_rte_sp(childregs, usp);
-
-               /* Child sees zero return value */
-               childregs->r00 = 0;
-
-               /*
-                * The clone syscall has the C signature:
-                * int [r0] clone(int flags [r0],
-                *           void *child_frame [r1],
-                *           void *parent_tid [r2],
-                *           void *child_tid [r3],
-                *           void *thread_control_block [r4]);
-                * ugp is used to provide TLS support.
-                */
-               if (clone_flags & CLONE_SETTLS)
-                       childregs->ugp = childregs->r04;
-
-               /*
-                * Parent sees new pid -- not necessary, not even possible at
-                * this point in the fork process
-                * Might also want to set things like ti->addr_limit
-                */
-       } else {
-               /*
-                * If kernel thread, resume stack is kernel stack base.
-                * Note that this is pointer arithmetic on pt_regs *
-                */
-               pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));
-               /*
-                * We need the current thread_info fast path pointer
-                * set up in pt_regs.  The register to be used is
-                * parametric for assembler code, but the mechanism
-                * doesn't drop neatly into C.  Needs to be fixed.
-                */
-               childregs->THREADINFO_REG = (unsigned long) ti;
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               /* r24 <- fn, r25 <- arg */
+               ss->r2524 = usp | ((u64)arg << 32);
+               pt_set_kmode(childregs);
+               return 0;
        }
+       memcpy(childregs, regs, sizeof(*childregs));
+       ss->r2524 = 0;
+
+       pt_set_rte_sp(childregs, usp);
+
+       /* Child sees zero return value */
+       childregs->r00 = 0;
+
+       /*
+        * The clone syscall has the C signature:
+        * int [r0] clone(int flags [r0],
+        *           void *child_frame [r1],
+        *           void *parent_tid [r2],
+        *           void *child_tid [r3],
+        *           void *thread_control_block [r4]);
+        * ugp is used to provide TLS support.
+        */
+       if (clone_flags & CLONE_SETTLS)
+               childregs->ugp = childregs->r04;
 
        /*
-        * thread_info pointer is pulled out of task_struct "stack"
-        * field on switch_to.
+        * Parent sees new pid -- not necessary, not even possible at
+        * this point in the fork process
+        * Might also want to set things like ti->addr_limit
         */
-       p->stack = (void *)ti;
 
        return 0;
 }
index 5047b8b879c02376f44c9b06114ce1facde7b013..fe0d1373165d403e1c983626145fcf23c292cf5e 100644 (file)
@@ -249,14 +249,14 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
  */
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
 {
-       struct pt_regs *regs = current_thread_info()->regs;
+       struct pt_regs *regs = current_pt_regs();
 
        return do_sigaltstack(uss, uoss, regs->r29);
 }
 
 asmlinkage int sys_rt_sigreturn(void)
 {
-       struct pt_regs *regs = current_thread_info()->regs;
+       struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe __user *frame;
        sigset_t blocked;
 
index 319fa6494f58cd70c8823619fce09972e9846af3..d2cc3270af3eaad394ba7cca3c09c55a94d0e5e1 100644 (file)
  * See signal.c for signal-related system call wrappers.
  */
 
-asmlinkage int sys_execve(char __user *ufilename,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp)
-{
-       struct pt_regs *pregs = current_thread_info()->regs;
-       struct filename *filename;
-       int retval;
-
-       filename = getname(ufilename);
-       retval = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return retval;
-
-       retval = do_execve(filename->name, argv, envp, pregs);
-       putname(filename);
-
-       return retval;
-}
-
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
                         unsigned long parent_tidp, unsigned long child_tidp)
 {
-       struct pt_regs *pregs = current_thread_info()->regs;
+       struct pt_regs *pregs = current_pt_regs();
 
        if (!newsp)
                newsp = pregs->SP;
        return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp,
                       (int __user *)child_tidp);
 }
-
-/*
- * Do a system call from the kernel, so as to have a proper pt_regs
- * and recycle the sys_execvpe infrustructure.
- */
-int kernel_execve(const char *filename,
-                 const char *const argv[], const char *const envp[])
-{
-       register unsigned long __a0 asm("r0") = (unsigned long) filename;
-       register unsigned long __a1 asm("r1") = (unsigned long) argv;
-       register unsigned long __a2 asm("r2") = (unsigned long) envp;
-       int retval;
-
-       __asm__ volatile(
-               "       R6 = #%4;\n"
-               "       trap0(#1);\n"
-               "       %0 = R0;\n"
-               : "=r" (retval)
-               : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
-       );
-
-       return retval;
-}
index cd71673ac25983cebe108f19a58efd656a523b03..425e50c694f7d8a453d6ee82134c2669b8dbd6f5 100644 (file)
@@ -266,4 +266,8 @@ _K_enter_machcheck:
        .globl ret_from_fork
 ret_from_fork:
        call schedule_tail
+       P0 = cmp.eq(R24, #0);
+       if P0 jump return_from_syscall
+       R0 = R25;
+       callr R24
        jump return_from_syscall
index 3279646120e3be5bdbc970ca5297b5fce30011ee..6706004681280ab211e11a8836f71535d4c1bd9f 100644 (file)
@@ -42,6 +42,8 @@ config IA64
        select GENERIC_TIME_VSYSCALL_OLD
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
index 944152a5091223798fb3427b2dc5bb56ecaef4be..e0a899a1a8a665c140dba6255dbbde7528a16c79 100644 (file)
@@ -340,22 +340,6 @@ struct task_struct;
  */
 #define release_thread(dead_task)
 
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE 1: 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.
- *
- * NOTE 2: This MUST NOT be an inlined function.  Otherwise, we get
- * into trouble in init/main.c when the child thread returns to
- * do_basic_setup() and the timing is such that free_initmem() has
- * been called already.
- */
-extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Get wait channel for task P.  */
 extern unsigned long get_wchan (struct task_struct *p);
 
index 8b3ff2f5b86167eda40544dbda0099c568eaaf0e..1574bca86138c317ab70fa75d5e19fa3911ae6d9 100644 (file)
@@ -29,6 +29,7 @@
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
index 1ccbe12a4d84fe6585455a45b367647b1fa2c240..940a67263629177f7a3e66a129acc5cee4157abd 100644 (file)
@@ -61,14 +61,13 @@ ENTRY(ia64_execve)
         * Allocate 8 input registers since ptrace() may clobber them
         */
        .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
-       alloc loc1=ar.pfs,8,2,4,0
+       alloc loc1=ar.pfs,8,2,3,0
        mov loc0=rp
        .body
        mov out0=in0                    // filename
        ;;                              // stop bit between alloc and call
        mov out1=in1                    // argv
        mov out2=in2                    // envp
-       add out3=16,sp                  // regs
        br.call.sptk.many rp=sys_execve
 .ret0:
        cmp4.ge p6,p7=r8,r0
@@ -76,7 +75,6 @@ ENTRY(ia64_execve)
        sxt4 r8=r8                      // return 64-bit result
        ;;
        stf.spill [sp]=f0
-(p6)   cmp.ne pKStk,pUStk=r0,r0        // a successful execve() lands us in user-mode...
        mov rp=loc0
 (p6)   mov ar.pfs=r0                   // clear ar.pfs on success
 (p7)   br.ret.sptk.many rp
@@ -484,19 +482,6 @@ GLOBAL_ENTRY(prefetch_stack)
        br.ret.sptk.many rp
 END(prefetch_stack)
 
-GLOBAL_ENTRY(kernel_execve)
-       rum psr.ac
-       mov r15=__NR_execve                     // put syscall number in place
-       break __BREAK_SYSCALL
-       br.ret.sptk.many rp
-END(kernel_execve)
-
-GLOBAL_ENTRY(clone)
-       mov r15=__NR_clone                      // put syscall number in place
-       break __BREAK_SYSCALL
-       br.ret.sptk.many rp
-END(clone)
-
        /*
         * Invoke a system call, but do some tracing before and after the call.
         * We MUST preserve the current register frame throughout this routine
@@ -600,6 +585,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel)
 .ret4: br.cond.sptk ia64_leave_kernel
 END(ia64_strace_leave_kernel)
 
+ENTRY(call_payload)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0)
+       /* call the kernel_thread payload; fn is in r4, arg - in r5 */
+       alloc loc1=ar.pfs,0,3,1,0
+       mov loc0=rp
+       mov loc2=gp
+       mov out0=r5             // arg
+       ld8 r14 = [r4], 8       // fn.address
+       ;;
+       mov b6 = r14
+       ld8 gp = [r4]           // fn.gp
+       ;;
+       br.call.sptk.many rp=b6 // fn(arg)
+.ret12:        mov gp=loc2
+       mov rp=loc0
+       mov ar.pfs=loc1
+       /* ... and if it has returned, we are going to userland */
+       cmp.ne pKStk,pUStk=r0,r0
+       br.ret.sptk.many rp
+END(call_payload)
+
 GLOBAL_ENTRY(ia64_ret_from_clone)
        PT_REGS_UNWIND_INFO(0)
 {      /*
@@ -616,6 +622,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone)
        br.call.sptk.many rp=ia64_invoke_schedule_tail
 }
 .ret8:
+(pKStk)        br.call.sptk.many rp=call_payload
        adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
        ;;
        ld4 r2=[r2]
index 629a250f7c190376c6976d679f427044a0209eda..4738ff7bd66a28e35b260ea3706058fbf56adbda 100644 (file)
@@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime)
 END(cycle_to_cputime)
 #endif /* CONFIG_VIRT_CPU_ACCOUNTING */
 
-GLOBAL_ENTRY(start_kernel_thread)
-       .prologue
-       .save rp, r0                            // this is the end of the call-chain
-       .body
-       alloc r2 = ar.pfs, 0, 0, 2, 0
-       mov out0 = r9
-       mov out1 = r11;;
-       br.call.sptk.many rp = kernel_thread_helper;;
-       mov out0 = r8
-       br.call.sptk.many rp = sys_exit;;
-1:     br.sptk.few 1b                          // not reached
-END(start_kernel_thread)
-
 #ifdef CONFIG_IA64_BRL_EMU
 
 /*
index 35e106f2ed13e81a8509d9db0d0285cba10a0e8f..25543a295ad926fa03a80683a800a23c9a9d2fc8 100644 (file)
@@ -401,64 +401,15 @@ copy_thread(unsigned long clone_flags,
        struct pt_regs *child_ptregs;
        int retval = 0;
 
-#ifdef CONFIG_SMP
-       /*
-        * For SMP idle threads, fork_by_hand() calls do_fork with
-        * NULL regs.
-        */
-       if (!regs)
-               return 0;
-#endif
-
-       stack = ((struct switch_stack *) regs) - 1;
-
        child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
        child_stack = (struct switch_stack *) child_ptregs - 1;
 
-       /* copy parent's switch_stack & pt_regs to child: */
-       memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
-
        rbs = (unsigned long) current + IA64_RBS_OFFSET;
        child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
-       rbs_size = stack->ar_bspstore - rbs;
-
-       /* copy the parent's register backing store to the child: */
-       memcpy((void *) child_rbs, (void *) rbs, rbs_size);
-
-       if (likely(user_mode(child_ptregs))) {
-               if (clone_flags & CLONE_SETTLS)
-                       child_ptregs->r13 = regs->r16;  /* see sys_clone2() in entry.S */
-               if (user_stack_base) {
-                       child_ptregs->r12 = user_stack_base + user_stack_size - 16;
-                       child_ptregs->ar_bspstore = user_stack_base;
-                       child_ptregs->ar_rnat = 0;
-                       child_ptregs->loadrs = 0;
-               }
-       } else {
-               /*
-                * Note: we simply preserve the relative position of
-                * the stack pointer here.  There is no need to
-                * allocate a scratch area here, since that will have
-                * been taken care of by the caller of sys_clone()
-                * already.
-                */
-               child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
-               child_ptregs->r13 = (unsigned long) p;          /* set `current' pointer */
-       }
-       child_stack->ar_bspstore = child_rbs + rbs_size;
-       child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
 
        /* copy parts of thread_struct: */
        p->thread.ksp = (unsigned long) child_stack - 16;
 
-       /* stop some PSR bits from being inherited.
-        * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
-        * therefore we must specify them explicitly here and not include them in
-        * IA64_PSR_BITS_TO_CLEAR.
-        */
-       child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
-                                & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
-
        /*
         * NOTE: The calling convention considers all floating point
         * registers in the high partition (fph) to be scratch.  Since
@@ -480,8 +431,66 @@ copy_thread(unsigned long clone_flags,
 #      define THREAD_FLAGS_TO_SET      0
        p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
                           | THREAD_FLAGS_TO_SET);
+
        ia64_drop_fpu(p);       /* don't pick up stale state from a CPU's fph */
 
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               if (unlikely(!user_stack_base)) {
+                       /* fork_idle() called us */
+                       return 0;
+               }
+               memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack));
+               child_stack->r4 = user_stack_base;      /* payload */
+               child_stack->r5 = user_stack_size;      /* argument */
+               /*
+                * Preserve PSR bits, except for bits 32-34 and 37-45,
+                * which we can't read.
+                */
+               child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
+               /* mark as valid, empty frame */
+               child_ptregs->cr_ifs = 1UL << 63;
+               child_stack->ar_fpsr = child_ptregs->ar_fpsr
+                       = ia64_getreg(_IA64_REG_AR_FPSR);
+               child_stack->pr = (1 << PRED_KERNEL_STACK);
+               child_stack->ar_bspstore = child_rbs;
+               child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+
+               /* stop some PSR bits from being inherited.
+                * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
+                * therefore we must specify them explicitly here and not include them in
+                * IA64_PSR_BITS_TO_CLEAR.
+                */
+               child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+                                & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
+
+               return 0;
+       }
+       stack = ((struct switch_stack *) regs) - 1;
+       /* copy parent's switch_stack & pt_regs to child: */
+       memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
+
+       /* copy the parent's register backing store to the child: */
+       rbs_size = stack->ar_bspstore - rbs;
+       memcpy((void *) child_rbs, (void *) rbs, rbs_size);
+       if (clone_flags & CLONE_SETTLS)
+               child_ptregs->r13 = regs->r16;  /* see sys_clone2() in entry.S */
+       if (user_stack_base) {
+               child_ptregs->r12 = user_stack_base + user_stack_size - 16;
+               child_ptregs->ar_bspstore = user_stack_base;
+               child_ptregs->ar_rnat = 0;
+               child_ptregs->loadrs = 0;
+       }
+       child_stack->ar_bspstore = child_rbs + rbs_size;
+       child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+
+       /* stop some PSR bits from being inherited.
+        * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
+        * therefore we must specify them explicitly here and not include them in
+        * IA64_PSR_BITS_TO_CLEAR.
+        */
+       child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+                                & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
+
 #ifdef CONFIG_PERFMON
        if (current->thread.pfm_context)
                pfm_inherit(p, child_ptregs);
@@ -608,57 +617,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
        return 1;       /* f0-f31 are always valid so we always return 1 */
 }
 
-long
-sys_execve (const char __user *filename,
-           const char __user *const __user *argv,
-           const char __user *const __user *envp,
-           struct pt_regs *regs)
-{
-       struct filename *fname;
-       int error;
-
-       fname = getname(filename);
-       error = PTR_ERR(fname);
-       if (IS_ERR(fname))
-               goto out;
-       error = do_execve(fname->name, argv, envp, regs);
-       putname(fname);
-out:
-       return error;
-}
-
-pid_t
-kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
-{
-       extern void start_kernel_thread (void);
-       unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
-       struct {
-               struct switch_stack sw;
-               struct pt_regs pt;
-       } regs;
-
-       memset(&regs, 0, sizeof(regs));
-       regs.pt.cr_iip = helper_fptr[0];        /* set entry point (IP) */
-       regs.pt.r1 = helper_fptr[1];            /* set GP */
-       regs.pt.r9 = (unsigned long) fn;        /* 1st argument */
-       regs.pt.r11 = (unsigned long) arg;      /* 2nd argument */
-       /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read.  */
-       regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
-       regs.pt.cr_ifs = 1UL << 63;             /* mark as valid, empty frame */
-       regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
-       regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
-       regs.sw.pr = (1 << PRED_KERNEL_STACK);
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/* This gets called from kernel_thread() via ia64_invoke_thread_helper().  */
-int
-kernel_thread_helper (int (*fn)(void *), void *arg)
-{
-       return (*fn)(arg);
-}
-
 /*
  * Flush thread state.  This is called when a thread does an execve().
  */
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 4313aa62b51b76746b4b800a592b3f55899c395e..c4432f1fb2cfacc75978459d3b7c74b652a3d484 100644 (file)
@@ -139,6 +139,8 @@ 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 */
 
index d5e66a480782e0c121da54bceef6e58a57d12337..b27bdcbc7c2c9b1d6ccaa70da70b204823479d8d 100644 (file)
 #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
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..62c713f5694a3ebcbabcd93104cb5a9ac5d608af 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,29 +192,35 @@ 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;
 }
 
-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)
+asmlinkage int sys_fork(void)
 {
 #ifdef CONFIG_MMU
-       return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);
+       struct pt_regs *regs = current_pt_regs();
+       return do_fork(SIGCHLD, regs->spu, regs, 0, NULL, NULL);
 #else
        return -EINVAL;
 #endif /* CONFIG_MMU */
@@ -257,14 +228,13 @@ asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,
 
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
                         unsigned long parent_tidptr,
-                        unsigned long child_tidptr,
-                        unsigned long r4, unsigned long r5, unsigned long r6,
-                        struct pt_regs regs)
+                        unsigned long child_tidptr)
 {
+       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, regs, 0,
                       (int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
@@ -278,37 +248,13 @@ 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(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)
+asmlinkage int sys_vfork(void)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,
+       struct pt_regs *regs = current_pt_regs();
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->spu, regs, 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, &regs);
-       putname(filename);
-out:
-       return error;
-}
-
 /*
  * These bracket the sleeping functions..
  */
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;
-}
index e7c161433eae320adde6503722d35652f9c3956d..953a7ba5d05025a776e5114b20acfbc56231bd3c 100644 (file)
@@ -16,6 +16,7 @@ config M68K
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
        select MODULES_USE_ELF_RELA
index 5fc7f7bec1c807ced0c300d5f6f4747cf781c024..0aa165405966bf73b93db896e252afab1b3ed2a8 100644 (file)
@@ -32,7 +32,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
index 946cb0187751caf241a0f2f4e1b5b9ebe3c535a0..45b2f293f8cf0deda26ea3d0fa72afa1e2c67459 100644 (file)
@@ -115,16 +115,9 @@ ENTRY(ret_from_kernel_thread)
        | a3 contains the kernel thread payload, d7 - its argument
        movel   %d1,%sp@-
        jsr     schedule_tail
-       GET_CURRENT(%d0)
        movel   %d7,(%sp)
        jsr     %a3@
        addql   #4,%sp
-       movel   %d0,(%sp)
-       jra     sys_exit
-
-ENTRY(ret_from_kernel_execve)
-       movel   4(%sp), %sp
-       GET_CURRENT(%d0)
        jra     ret_from_exception
 
 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
index 4cba7439f9de897a9de9abb91ab2c3596e4fa8a1..198abf6d41c479ab119f02ad855a68a27bdbf2ce 100644 (file)
@@ -26,6 +26,8 @@ config MICROBLAZE
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config SWAP
        def_bool n
index af2bb9652392e9ecb80980c51a0ebf2b3390e526..0759153e81179b7a68909b9154d52afa1c2732c7 100644 (file)
@@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op;
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 # endif /* __ASSEMBLY__ */
 
@@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern unsigned long get_wchan(struct task_struct *p);
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 # define KSTK_EIP(tsk) (0)
 # define KSTK_ESP(tsk) (0)
 
@@ -131,8 +127,6 @@ extern 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.  */
 static inline void exit_thread(void)
 {
index 6985e6e9d826a689e6049308e663d06dcfdf070f..ea74428342948e6bdbe2e7d21b1c22ef2430a615 100644 (file)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 75c3ea1f48a123e07aeaf97481ed81ad204670ab..673a49c04a028ef5433a0aea8e4879569ad7befe 100644 (file)
@@ -474,6 +474,14 @@ ENTRY(ret_from_fork)
        brid    ret_to_user
        nop
 
+ENTRY(ret_from_kernel_thread)
+       brlid   r15, schedule_tail
+       addk    r5, r0, r3
+       brald   r15, r20
+       addk    r5, r0, r19
+       brid    ret_to_user
+       addk    r3, r0, r0
+
 work_pending:
        enable_irq
 
@@ -559,10 +567,6 @@ sys_clone:
        brid    microblaze_clone
        addk    r7, r1, r0
 
-sys_execve:
-       brid    microblaze_execve
-       addk    r8, r1, r0
-
 sys_rt_sigreturn_wrapper:
        brid    sys_rt_sigreturn
        addk    r5, r1, r0
index 03f7b8ce6b6bcc6968816b1ef09d50401a35ee21..10f360ed82b4038115ed8d6eb9a6faa3460fb382 100644 (file)
@@ -293,24 +293,6 @@ C_ENTRY(_user_exception):
        swi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
        addi    r14, r14, 4     /* return address is 4 byte after call */
 
-       mfs     r1, rmsr
-       nop
-       andi    r1, r1, MSR_UMS
-       bnei    r1, 1f
-
-/* Kernel-mode state save - kernel execve */
-       lwi     r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
-       tophys(r1,r1);
-
-       addik   r1, r1, -PT_SIZE; /* Make room on the stack. */
-       SAVE_REGS
-
-       swi     r1, r1, PT_MODE; /* pt_regs -> kernel mode */
-       brid    2f;
-       nop;                            /* Fill delay slot */
-
-/* User-mode state save.  */
-1:
        lwi     r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
        tophys(r1,r1);
        lwi     r1, r1, TS_THREAD_INFO; /* get stack from task_struct */
@@ -479,11 +461,20 @@ C_ENTRY(sys_fork_wrapper):
    saved context).  */
 C_ENTRY(ret_from_fork):
        bralid  r15, schedule_tail; /* ...which is schedule_tail's arg */
-       add     r3, r5, r0;     /* switch_thread returns the prev task */
+       add     r5, r3, r0;     /* switch_thread returns the prev task */
                                /* ( in the delay slot ) */
        brid    ret_from_trap;  /* Do normal trap return */
        add     r3, r0, r0;     /* Child's fork call should return 0. */
 
+C_ENTRY(ret_from_kernel_thread):
+       bralid  r15, schedule_tail; /* ...which is schedule_tail's arg */
+       add     r5, r3, r0;     /* switch_thread returns the prev task */
+                               /* ( in the delay slot ) */
+       brald   r15, r20        /* fn was left in r20 */
+       addk    r5, r0, r19     /* ... and argument - in r19 */
+       brid    ret_from_trap
+       add     r3, r0, r0
+
 C_ENTRY(sys_vfork):
        brid    microblaze_vfork        /* Do real work (tail-call) */
        addik   r5, r1, 0
@@ -498,10 +489,6 @@ C_ENTRY(sys_clone):
        brid    do_fork         /* Do real work (tail-call) */
        add     r8, r0, r0;             /* Arg 3: (unused) */
 
-C_ENTRY(sys_execve):
-       brid    microblaze_execve;      /* Do real work (tail-call).*/
-       addik   r8, r1, 0;              /* add user context as 4th arg */
-
 C_ENTRY(sys_rt_sigreturn_wrapper):
        brid    sys_rt_sigreturn        /* Do real work */
        addik   r5, r1, 0;              /* add user context as 1st arg */
index 1944e00f07e1d4185cbf8bbdf894591192ef6abd..29768c3dc358a1c6719c1e90e26b9c08a2db4eed 100644 (file)
@@ -119,46 +119,38 @@ void flush_thread(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct pt_regs *childregs = task_pt_regs(p);
        struct thread_info *ti = task_thread_info(p);
 
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               /* if we're creating a new kernel thread then just zeroing all
+                * the registers. That's OK for a brand new thread.*/
+               memset(childregs, 0, sizeof(struct pt_regs));
+               memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
+               ti->cpu_context.r1  = (unsigned long)childregs;
+               ti->cpu_context.r20 = (unsigned long)usp; /* fn */
+               ti->cpu_context.r19 = (unsigned long)arg;
+               childregs->pt_mode = 1;
+               local_save_flags(childregs->msr);
+#ifdef CONFIG_MMU
+               ti->cpu_context.msr = childregs->msr & ~MSR_IE;
+#endif
+               ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8;
+               return 0;
+       }
        *childregs = *regs;
-       if (user_mode(regs))
-               childregs->r1 = usp;
-       else
-               childregs->r1 = ((unsigned long) ti) + THREAD_SIZE;
+       childregs->r1 = usp;
 
-#ifndef CONFIG_MMU
        memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
        ti->cpu_context.r1 = (unsigned long)childregs;
+#ifndef CONFIG_MMU
        ti->cpu_context.msr = (unsigned long)childregs->msr;
 #else
+       childregs->msr |= MSR_UMS;
 
-       /* if creating a kernel thread then update the current reg (we don't
-        * want to use the parent's value when restoring by POP_STATE) */
-       if (kernel_mode(regs))
-               /* save new current on stack to use POP_STATE */
-               childregs->CURRENT_TASK = (unsigned long)p;
-       /* if returning to user then use the parent's value of this register */
-
-       /* if we're creating a new kernel thread then just zeroing all
-        * the registers. That's OK for a brand new thread.*/
-       /* Pls. note that some of them will be restored in POP_STATE */
-       if (kernel_mode(regs))
-               memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
-       /* if this thread is created for fork/vfork/clone, then we want to
-        * restore all the parent's context */
-       /* in addition to the registers which will be restored by POP_STATE */
-       else {
-               ti->cpu_context = *(struct cpu_context *)regs;
-               childregs->msr |= MSR_UMS;
-       }
-
-       /* FIXME STATE_SAVE_PT_OFFSET; */
-       ti->cpu_context.r1  = (unsigned long)childregs;
        /* we should consider the fact that childregs is a copy of the parent
         * regs which were saved immediately after entering the kernel state
         * before enabling VM. This MSR will be restored in switch_to and
@@ -209,29 +201,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 }
 #endif
 
-static void kernel_thread_helper(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));
-       /* store them in non-volatile registers */
-       regs.r5 = (unsigned long)fn;
-       regs.r6 = (unsigned long)arg;
-       local_save_flags(regs.msr);
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.pt_mode = 1;
-
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-                       &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL_GPL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
 /* TBD (used by procfs) */
@@ -246,6 +215,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
        regs->pt_mode = 0;
 #ifdef CONFIG_MMU
        regs->msr |= MSR_UMS;
+       regs->msr &= ~MSR_VM;
 #endif
 }
 
index 404c0f24bd41a7acaf5496e86120b15f9e715cd8..a6a7bae9f5c6497ea1d38a97ee700fe9eef39028 100644 (file)
@@ -48,24 +48,6 @@ asmlinkage long microblaze_clone(int flags, unsigned long stack,
        return do_fork(flags, stack, regs, 0, NULL, NULL);
 }
 
-asmlinkage long microblaze_execve(const char __user *filenamei,
-                                 const char __user *const __user *argv,
-                                 const char __user *const __user *envp,
-                                 struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname(filenamei);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                        unsigned long prot, unsigned long flags,
                        unsigned long fd, off_t pgoff)
@@ -75,24 +57,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 
        return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 }
-
-/*
- * 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 const char *__a __asm__("r5") = filename;
-       register const void *__b __asm__("r6") = argv;
-       register const void *__c __asm__("r7") = envp;
-       register unsigned long __syscall __asm__("r12") = __NR_execve;
-       register unsigned long __ret __asm__("r3");
-       __asm__ __volatile__ ("brki r14, 0x8"
-                       : "=r" (__ret), "=r" (__syscall)
-                       : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
-                       : "r4", "r8", "r9",
-                       "r10", "r11", "r14", "cc", "memory");
-       return __ret;
-}
index dba9390d37cf2c0d1672ca6dfb2b1453fb4294cf..4183e62f178cd9d85027c32e95392f2f51f409ad 100644 (file)
@@ -40,6 +40,8 @@ config MIPS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
        select MODULES_USE_ELF_RELA if 64BIT
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 menu "Machine selection"
 
index 5e33fabe354de7e12e11dc4f64aa5d0be7464090..d28c41e0887c584a8c869eb266138d3545bad157 100644 (file)
@@ -310,8 +310,6 @@ struct task_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 /*
index 4f5da948a777c91e9223d94991f76fbfad6f6f30..cec5e125f7e466fceb8680f029de9ad040b9c4a3 100644 (file)
@@ -61,4 +61,10 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
                die(str, regs);
 }
 
+#define current_pt_regs()                                              \
+({                                                                     \
+       unsigned long sp = (unsigned long)__builtin_frame_address(0);   \
+       (struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1;      \
+})
+
 #endif /* _ASM_PTRACE_H */
index 9e47cc11aa263ba3991d680736bce6aeea41447e..b306e2081cad9a4c03a66d9c82595e96581140da 100644 (file)
@@ -20,6 +20,7 @@
 #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
index a6c133212003ed96537e6f950ec71c59d98559fb..3320cb4ac1d485b1ab42bc3da9e6346a0f62b9ff 100644 (file)
@@ -65,6 +65,12 @@ need_resched:
        b       need_resched
 #endif
 
+FEXPORT(ret_from_kernel_thread)
+       jal     schedule_tail           # a0 = struct task_struct *prev
+       move    a0, s1
+       jal     s0
+       j       syscall_exit
+
 FEXPORT(ret_from_fork)
        jal     schedule_tail           # a0 = struct task_struct *prev
 
index 3a21acedf88231403703c3ca842916f325f88a6f..8796dbc7e3585ca1193e29fd967158efc2029157 100644 (file)
@@ -3,7 +3,6 @@
  *
  * Copyright (C) 2000 Silicon Graphics, Inc.
  * Written by Ulf Carlsson (ulfc@engr.sgi.com)
- * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
  */
 #include <linux/compiler.h>
 #include <linux/mm.h>
@@ -77,26 +76,6 @@ out:
        return error;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname(compat_ptr(regs.regs[4]));
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),
-                                compat_ptr(regs.regs[6]), &regs);
-       putname(filename);
-
-out:
-       return error;
-}
-
 #define RLIM_INFINITY32        0x7fffffff
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
index 3fc1691110dc52f82e8ec1271054c1411c122658..2d9304c2b54cb0e8508e3a9dd397486ac977d1bb 100644 (file)
@@ -32,8 +32,6 @@ EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Functions that operate on entire pages.  Mostly used by memory management.
  */
index e9a5fd7277f4fd580172a5630d604e443c60513d..d13720ac656f40d4cb71a71da54e15aba56c2b22 100644 (file)
@@ -84,6 +84,7 @@ void __noreturn cpu_idle(void)
 }
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 {
@@ -113,7 +114,7 @@ void flush_thread(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-       unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+       unsigned long arg, struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs;
@@ -136,19 +137,30 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs = (struct pt_regs *) childksp - 1;
        /*  Put the stack after the struct pt_regs.  */
        childksp = (unsigned long) childregs;
+       p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               unsigned long status = p->thread.cp0_status;
+               memset(childregs, 0, sizeof(struct pt_regs));
+               ti->addr_limit = KERNEL_DS;
+               p->thread.reg16 = usp; /* fn */
+               p->thread.reg17 = arg;
+               p->thread.reg29 = childksp;
+               p->thread.reg31 = (unsigned long) ret_from_kernel_thread;
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+               status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |
+                        ((status & (ST0_KUC | ST0_IEC)) << 2);
+#else
+               status |= ST0_EXL;
+#endif
+               childregs->cp0_status = status;
+               return 0;
+       }
        *childregs = *regs;
        childregs->regs[7] = 0; /* Clear error flag */
-
        childregs->regs[2] = 0; /* Child gets zero as return value */
+       childregs->regs[29] = usp;
+       ti->addr_limit = USER_DS;
 
-       if (childregs->cp0_status & ST0_CU0) {
-               childregs->regs[28] = (unsigned long) ti;
-               childregs->regs[29] = childksp;
-               ti->addr_limit = KERNEL_DS;
-       } else {
-               childregs->regs[29] = usp;
-               ti->addr_limit = USER_DS;
-       }
        p->thread.reg29 = (unsigned long) childregs;
        p->thread.reg31 = (unsigned long) ret_from_fork;
 
@@ -156,7 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
         * New tasks lose permission to use the fpu. This accelerates context
         * switching for most programs since they don't use the fpu.
         */
-       p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
        childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -221,35 +232,6 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
        return 1;
 }
 
-/*
- * Create a kernel thread
- */
-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-       do_exit(fn(arg));
-}
-
-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.regs[4] = (unsigned long) arg;
-       regs.regs[5] = (unsigned long) fn;
-       regs.cp0_epc = (unsigned long) kernel_thread_helper;
-       regs.cp0_status = read_c0_status();
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-       regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |
-                         ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2);
-#else
-       regs.cp0_status |= ST0_EXL;
-#endif
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  *
  */
index f6ba8381ee0186c5dfc1f19879ae4c39d15d52e9..d27ca340d46dcbe6cb680f24b8c4e49e0bad1ebc 100644 (file)
@@ -167,7 +167,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_getsockopt
        PTR     sys_clone                       /* 6055 */
        PTR     sys_fork
-       PTR     sys32_execve
+       PTR     compat_sys_execve
        PTR     sys_exit
        PTR     compat_sys_wait4
        PTR     sys_kill                        /* 6060 */
index 53c2d72457649f74f211ca894662dccabee470da..9601be6afa3de3b9571215bf75d2fe6c55392a60 100644 (file)
@@ -203,7 +203,7 @@ sys_call_table:
        PTR     sys_creat
        PTR     sys_link
        PTR     sys_unlink                      /* 4010 */
-       PTR     sys32_execve
+       PTR     compat_sys_execve
        PTR     sys_chdir
        PTR     compat_sys_time
        PTR     sys_mknod
index 2bd561bc05ae2b4e7b814ac866d21faaddd046a2..c611e2df7767e81550f89d645fe1025fcf281c1e 100644 (file)
@@ -127,28 +127,6 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
                       parent_tidptr, child_tidptr);
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname((const char __user *) (long)regs.regs[4]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name,
-                         (const char __user *const __user *) (long)regs.regs[5],
-                         (const char __user *const __user *) (long)regs.regs[6],
-                         &regs);
-       putname(filename);
-
-out:
-       return error;
-}
-
 SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
        struct thread_info *ti = task_thread_info(current);
@@ -313,34 +291,3 @@ asmlinkage void bad_stack(void)
 {
        do_exit(SIGSEGV);
 }
-
-/*
- * 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 unsigned long __a0 asm("$4") = (unsigned long) filename;
-       register unsigned long __a1 asm("$5") = (unsigned long) argv;
-       register unsigned long __a2 asm("$6") = (unsigned long) envp;
-       register unsigned long __a3 asm("$7");
-       unsigned long __v0;
-
-       __asm__ volatile ("                                     \n"
-       "       .set    noreorder                               \n"
-       "       li      $2, %5          # __NR_execve           \n"
-       "       syscall                                         \n"
-       "       move    %0, $2                                  \n"
-       "       .set    reorder                                 \n"
-       : "=&r" (__v0), "=r" (__a3)
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
-       : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
-         "memory");
-
-       if (__a3 == 0)
-               return __v0;
-
-       return -__v0;
-}
index 04669fac117b34b9e35bc73d10428efa45561d36..72471744a9124f36ca33b9f4bbd583fd96f88c2a 100644 (file)
@@ -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
index 55bbec1887e980d5036ede2d847a9a607d90198b..9711d51b0212d56d8e594ea7e7fd4d6dbaa8c43f 100644 (file)
@@ -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
index 0c631d34c8d7f1f73807b4f46c8114ea430a3154..68fcab8f8f6f5eadebd5a18715034d6b33c8d781 100644 (file)
@@ -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
 
 ###############################################################################
index 05f2ba41ff1aadd52634a136b0f4450bba2970cc..e7f1a2993f780ab89795a73c8b2e9bd71bdd2ed6 100644 (file)
@@ -22,6 +22,8 @@ config OPENRISC
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config MMU
        def_bool y
index 437bdbb61b14ce58372710d7177a8e1ba2fd9bb0..5db7bc0fa5a76fcb931cbbb87b86ec1fb40cecff 100644 (file)
@@ -20,6 +20,8 @@
 
 #define sys_mmap2 sys_mmap_pgoff
 
+#define __ARCH_WANT_SYS_EXECVE
+
 #include <asm-generic/unistd.h>
 
 #define __NR_or1k_atomic __NR_arch_specific_syscall
index ddfcaa828b0e97daf804355ab4f9744e7e87dc93..c60a09df323f3710f1d386afa5d8d4f38dd0beb7 100644 (file)
@@ -894,6 +894,16 @@ ENTRY(ret_from_fork)
        l.jal   schedule_tail
         l.nop
 
+       /* Check if we are a kernel thread */
+       l.sfeqi r20,0
+       l.bf    1f
+        l.nop
+
+       /* ...we are a kernel thread so invoke the requested callback */
+       l.jalr  r20
+        l.or   r3,r22,r0
+
+1:
        /* _syscall_returns expect r11 to contain return value */
        l.lwz   r11,PT_GPR11(r1)
 
@@ -915,26 +925,6 @@ ENTRY(ret_from_fork)
        l.j     _syscall_return
         l.nop
 
-/* Since syscalls don't save call-clobbered registers, the args to
- * kernel_thread_helper will need to be passed through callee-saved
- * registers and copied to the parameter registers when the thread
- * begins running.
- *
- * See arch/openrisc/kernel/process.c:
- * The args are passed as follows:
- *   arg1 (r3) : passed in r20
- *   arg2 (r4) : passed in r22
- */
-
-ENTRY(_kernel_thread_helper)
-       l.or    r3,r20,r0
-       l.or    r4,r22,r0
-       l.movhi r31,hi(kernel_thread_helper)
-       l.ori   r31,r31,lo(kernel_thread_helper)
-       l.jr    r31
-        l.nop
-
-
 /* ========================================================[ switch ] === */
 
 /*
@@ -1044,8 +1034,13 @@ ENTRY(_switch)
        /* Unwind stack to pre-switch state */
        l.addi  r1,r1,(INT_FRAME_SIZE)
 
-       /* Return via the link-register back to where we 'came from', where that can be
-        * either schedule() or return_from_fork()... */
+       /* Return via the link-register back to where we 'came from', where
+        * that may be either schedule(), ret_from_fork(), or
+        * ret_from_kernel_thread().  If we are returning to a new thread,
+        * we are expected to have set up the arg to schedule_tail already,
+        * hence we do so here unconditionally:
+        */
+       l.lwz   r3,TI_STACK(r3)         /* Load 'prev' as schedule_tail arg */
        l.jr    r9
         l.nop
 
@@ -1088,10 +1083,6 @@ ENTRY(sys_fork)
        l.j     _fork_save_extra_regs_and_call
         l.addi r3,r1,0
 
-ENTRY(sys_execve)
-       l.j     _sys_execve
-        l.addi r6,r1,0
-
 ENTRY(sys_sigaltstack)
        l.j     _sys_sigaltstack
         l.addi r5,r1,0
index c35f3ab1a8d34749d3f32648e82d826f27f350e1..e0874b8e09e498f1d95813f49ab03f2c743d08fa 100644 (file)
@@ -109,66 +109,82 @@ void release_thread(struct task_struct *dead_task)
  */
 extern asmlinkage void ret_from_fork(void);
 
+/*
+ * copy_thread
+ * @clone_flags: flags
+ * @usp: user stack pointer or fn for kernel thread
+ * @arg: arg to fn for kernel thread; always NULL for userspace thread
+ * @p: the newly created task
+ * @regs: CPU context to copy for userspace thread; always NULL for kthread
+ *
+ * At the top of a newly initialized kernel stack are two stacked pt_reg
+ * structures.  The first (topmost) is the userspace context of the thread.
+ * The second is the kernelspace context of the thread.
+ *
+ * A kernel thread will not be returning to userspace, so the topmost pt_regs
+ * struct can be uninitialized; it _does_ need to exist, though, because
+ * a kernel thread can become a userspace thread by doing a kernel_execve, in
+ * which case the topmost context will be initialized and used for 'returning'
+ * to userspace.
+ *
+ * The second pt_reg struct needs to be initialized to 'return' to
+ * ret_from_fork.  A kernel thread will need to set r20 to the address of
+ * a function to call into (with arg in r22); userspace threads need to set
+ * r20 to NULL in which case ret_from_fork will just continue a return to
+ * userspace.
+ *
+ * A kernel thread 'fn' may return; this is effectively what happens when
+ * kernel_execve is called.  In that case, the userspace pt_regs must have
+ * been initialized (which kernel_execve takes care of, see start_thread
+ * below); ret_from_fork will then continue its execution causing the
+ * 'kernel thread' to return to userspace as a userspace thread.
+ */
+
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long unused, struct task_struct *p, struct pt_regs *regs)
+           unsigned long arg, struct task_struct *p, struct pt_regs *regs)
 {
-       struct pt_regs *childregs;
+       struct pt_regs *userregs;
        struct pt_regs *kregs;
        unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-       struct thread_info *ti;
        unsigned long top_of_kernel_stack;
 
        top_of_kernel_stack = sp;
 
        p->set_child_tid = p->clear_child_tid = NULL;
 
-       /* Copy registers */
-       /* redzone */
-       sp -= STACK_FRAME_OVERHEAD;
+       /* Locate userspace context on stack... */
+       sp -= STACK_FRAME_OVERHEAD;     /* redzone */
        sp -= sizeof(struct pt_regs);
-       childregs = (struct pt_regs *)sp;
+       userregs = (struct pt_regs *) sp;
 
-       /* Copy parent registers */
-       *childregs = *regs;
+       /* ...and kernel context */
+       sp -= STACK_FRAME_OVERHEAD;     /* redzone */
+       sp -= sizeof(struct pt_regs);
+       kregs = (struct pt_regs *)sp;
 
-       if ((childregs->sr & SPR_SR_SM) == 1) {
-               /* for kernel thread, set `current_thread_info'
-                * and stackptr in new task
-                */
-               childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-               childregs->gpr[10] = (unsigned long)task_thread_info(p);
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(kregs, 0, sizeof(struct pt_regs));
+               kregs->gpr[20] = usp; /* fn, kernel thread */
+               kregs->gpr[22] = arg;
        } else {
-               childregs->sp = usp;
-       }
-
-       childregs->gpr[11] = 0; /* Result from fork() */
+               *userregs = *regs;
 
-       /*
-        * The way this works is that at some point in the future
-        * some task will call _switch to switch to the new task.
-        * That will pop off the stack frame created below and start
-        * the new task running at ret_from_fork.  The new task will
-        * do some house keeping and then return from the fork or clone
-        * system call, using the stack frame created above.
-        */
-       /* redzone */
-       sp -= STACK_FRAME_OVERHEAD;
-       sp -= sizeof(struct pt_regs);
-       kregs = (struct pt_regs *)sp;
+               userregs->sp = usp;
+               userregs->gpr[11] = 0;  /* Result from fork() */
 
-       ti = task_thread_info(p);
-       ti->ksp = sp;
+               kregs->gpr[20] = 0;     /* Userspace thread */
+       }
 
-       /* kregs->sp must store the location of the 'pre-switch' kernel stack
-        * pointer... for a newly forked process, this is simply the top of
-        * the kernel stack.
+       /*
+        * _switch wants the kernel stack page in pt_regs->sp so that it
+        * can restore it to thread_info->ksp... see _switch for details.
         */
        kregs->sp = top_of_kernel_stack;
-       kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */
-       kregs->gpr[10] = (unsigned long)task_thread_info(p);
        kregs->gpr[9] = (unsigned long)ret_from_fork;
 
+       task_thread_info(p)->ksp = (unsigned long)kregs;
+
        return 0;
 }
 
@@ -177,16 +193,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
  */
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
-       unsigned long sr = regs->sr & ~SPR_SR_SM;
+       unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM;
 
        set_fs(USER_DS);
-       memset(regs->gpr, 0, sizeof(regs->gpr));
+       memset(regs, 0, sizeof(struct pt_regs));
 
        regs->pc = pc;
        regs->sr = sr;
        regs->sp = sp;
-
-/*     printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/
 }
 
 /* Fill in the fpu structure for a core dump.  */
@@ -237,74 +251,9 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
        dest[35] = 0;
 }
 
-extern void _kernel_thread_helper(void);
-
-void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)
-{
-       do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread.
- */
-int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.gpr[20] = (unsigned long)fn;
-       regs.gpr[22] = (unsigned long)arg;
-       regs.sr = mfspr(SPR_SR);
-       regs.pc = (unsigned long)_kernel_thread_helper;
-
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-                      0, &regs, 0, NULL, NULL);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage long _sys_execve(const char __user *name,
-                           const char __user * const __user *argv,
-                           const char __user * const __user *envp,
-                           struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-
-out:
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        /* TODO */
 
        return 0;
 }
-
-int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-{
-       register long __res asm("r11") = __NR_execve;
-       register long __a asm("r3") = (long)(filename);
-       register long __b asm("r4") = (long)(argv);
-       register long __c asm("r5") = (long)(envp);
-       __asm__ volatile ("l.sys 1"
-                         : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)
-                         : "0"(__res), "1"(__a), "2"(__b), "3"(__c)
-                         : "r6", "r7", "r8", "r12", "r13", "r15",
-                           "r17", "r19", "r21", "r23", "r25", "r27",
-                           "r29", "r31");
-       __asm__ volatile ("l.nop");
-       return __res;
-}
index 11def45b98c5ee04f356890a8396b8d970624524..0aec70c3561403d15a046ea4212f41259dd4f67b 100644 (file)
@@ -22,6 +22,8 @@ config PARISC
        select GENERIC_STRNCPY_FROM_USER
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index 541639c3f60717487015518a5336475346ff5639..55512e26b0c20a9921c6165e387b6f988afdd6c9 100644 (file)
@@ -163,6 +163,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
 
 #endif /* __ASSEMBLY__ */
 
index 18670a078849b96d92d4dd4ff406a79c2caa28a4..c9a9abd4bc587df2e4d1e3fba13057d8be3b9489 100644 (file)
@@ -707,60 +707,10 @@ ENTRY(end_fault_vector)
        .import         handle_interruption,code
        .import         do_cpu_irq_mask,code
 
-       /*
-        * r26 = function to be called
-        * r25 = argument to pass in
-        * r24 = flags for do_fork()
-        *
-        * Kernel threads don't ever return, so they don't need
-        * a true register context. We just save away the arguments
-        * for copy_thread/ret_ to properly set up the child.
-        */
-
-#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
-#define CLONE_UNTRACED 0x00800000
-
-       .import do_fork
-ENTRY(__kernel_thread)
-       STREG   %r2, -RP_OFFSET(%r30)
-
-       copy    %r30, %r1
-       ldo     PT_SZ_ALGN(%r30),%r30
-#ifdef CONFIG_64BIT
-       /* Yo, function pointers in wide mode are little structs... -PB */
-       ldd     24(%r26), %r2
-       STREG   %r2, PT_GR27(%r1)       /* Store childs %dp */
-       ldd     16(%r26), %r26
-
-       STREG   %r22, PT_GR22(%r1)      /* save r22 (arg5) */
-       copy    %r0, %r22               /* user_tid */
-#endif
-       STREG   %r26, PT_GR26(%r1)  /* Store function & argument for child */
-       STREG   %r25, PT_GR25(%r1)
-       ldil    L%CLONE_UNTRACED, %r26
-       ldo     CLONE_VM(%r26), %r26   /* Force CLONE_VM since only init_mm */
-       or      %r26, %r24, %r26      /* will have kernel mappings.      */
-       ldi     1, %r25                 /* stack_start, signals kernel thread */
-       stw     %r0, -52(%r30)          /* user_tid */
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-       BL      do_fork, %r2
-       copy    %r1, %r24               /* pt_regs */
-
-       /* Parent Returns here */
-
-       LDREG   -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
-       ldo     -PT_SZ_ALGN(%r30), %r30
-       bv      %r0(%r2)
-       nop
-ENDPROC(__kernel_thread)
-
        /*
         * Child Returns here
         *
-        * copy_thread moved args from temp save area set up above
-        * into task save area.
+        * copy_thread moved args into task save area.
         */
 
 ENTRY(ret_from_kernel_thread)
@@ -769,51 +719,17 @@ ENTRY(ret_from_kernel_thread)
        BL      schedule_tail, %r2
        nop
 
-       LDREG   TI_TASK-THREAD_SZ_ALGN(%r30), %r1
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
        LDREG   TASK_PT_GR25(%r1), %r26
 #ifdef CONFIG_64BIT
        LDREG   TASK_PT_GR27(%r1), %r27
-       LDREG   TASK_PT_GR22(%r1), %r22
 #endif
        LDREG   TASK_PT_GR26(%r1), %r1
        ble     0(%sr7, %r1)
        copy    %r31, %r2
-
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-       loadgp                          /* Thread could have been in a module */
-#endif
-#ifndef CONFIG_64BIT
-       b       sys_exit
-#else
-       load32  sys_exit, %r1
-       bv      %r0(%r1)
-#endif
-       ldi     0, %r26
-ENDPROC(ret_from_kernel_thread)
-
-       .import sys_execve, code
-ENTRY(__execve)
-       copy    %r2, %r15
-       copy    %r30, %r16
-       ldo     PT_SZ_ALGN(%r30), %r30
-       STREG   %r26, PT_GR26(%r16)
-       STREG   %r25, PT_GR25(%r16)
-       STREG   %r24, PT_GR24(%r16)
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-       BL      sys_execve, %r2
-       copy    %r16, %r26
-
-       cmpib,=,n 0,%r28,intr_return    /* forward */
-
-       /* yes, this will trap and die. */
-       copy    %r15, %r2
-       copy    %r16, %r30
-       bv      %r0(%r2)
+       b       finish_child_return
        nop
-ENDPROC(__execve)
+ENDPROC(ret_from_kernel_thread)
 
 
        /*
@@ -1776,49 +1692,27 @@ ENTRY(sys_fork_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
        ldo     TASK_REGS(%r1),%r1
        reg_save %r1
-       mfctl   %cr27, %r3
-       STREG   %r3, PT_CR27(%r1)
-
-       STREG   %r2,-RP_OFFSET(%r30)
-       ldo     FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-
-       /* These are call-clobbered registers and therefore
-          also syscall-clobbered (we hope). */
-       STREG   %r2,PT_GR19(%r1)        /* save for child */
-       STREG   %r30,PT_GR21(%r1)
+       mfctl   %cr27, %r28
+       STREG   %r28, PT_CR27(%r1)
 
        LDREG   PT_GR30(%r1),%r25
        copy    %r1,%r24
-       BL      sys_clone,%r2
+       b       sys_clone
        ldi     SIGCHLD,%r26
-
-       LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
-wrapper_exit:
-       ldo     -FRAME_SIZE(%r30),%r30          /* get the stackframe */
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-       ldo     TASK_REGS(%r1),%r1       /* get pt regs */
-
-       LDREG   PT_CR27(%r1), %r3
-       mtctl   %r3, %cr27
-       reg_restore %r1
-
-       /* strace expects syscall # to be preserved in r20 */
-       ldi     __NR_fork,%r20
-       bv %r0(%r2)
-       STREG   %r20,PT_GR20(%r1)
 ENDPROC(sys_fork_wrapper)
 
        /* Set the return value for the child */
 ENTRY(child_return)
        BL      schedule_tail, %r2
        nop
+finish_child_return:
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
+       ldo     TASK_REGS(%r1),%r1       /* get pt regs */
 
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
-       LDREG   TASK_PT_GR19(%r1),%r2
-       b       wrapper_exit
+       LDREG   PT_CR27(%r1), %r3
+       mtctl   %r3, %cr27
+       reg_restore %r1
+       b       syscall_exit
        copy    %r0,%r28
 ENDPROC(child_return)
 
@@ -1827,23 +1721,10 @@ ENTRY(sys_clone_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
        ldo     TASK_REGS(%r1),%r1      /* get pt regs */
        reg_save %r1
-       mfctl   %cr27, %r3
-       STREG   %r3, PT_CR27(%r1)
-
-       STREG   %r2,-RP_OFFSET(%r30)
-       ldo     FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-
-       /* WARNING - Clobbers r19 and r21, userspace must save these! */
-       STREG   %r2,PT_GR19(%r1)        /* save for child */
-       STREG   %r30,PT_GR21(%r1)
-       BL      sys_clone,%r2
+       mfctl   %cr27, %r28
+       STREG   %r28, PT_CR27(%r1)
+       b       sys_clone
        copy    %r1,%r24
-
-       b       wrapper_exit
-       LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
 ENDPROC(sys_clone_wrapper)
 
 
@@ -1851,72 +1732,14 @@ ENTRY(sys_vfork_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
        ldo     TASK_REGS(%r1),%r1      /* get pt regs */
        reg_save %r1
-       mfctl   %cr27, %r3
-       STREG   %r3, PT_CR27(%r1)
+       mfctl   %cr27, %r28
+       STREG   %r28, PT_CR27(%r1)
 
-       STREG   %r2,-RP_OFFSET(%r30)
-       ldo     FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-
-       STREG   %r2,PT_GR19(%r1)        /* save for child */
-       STREG   %r30,PT_GR21(%r1)
-
-       BL      sys_vfork,%r2
+       b       sys_vfork
        copy    %r1,%r26
-
-       b       wrapper_exit
-       LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
 ENDPROC(sys_vfork_wrapper)
 
        
-       .macro  execve_wrapper execve
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-       ldo     TASK_REGS(%r1),%r1      /* get pt regs */
-
-       /*
-        * Do we need to save/restore r3-r18 here?
-        * I don't think so. why would new thread need old
-        * threads registers?
-        */
-
-       /* %arg0 - %arg3 are already saved for us. */
-
-       STREG %r2,-RP_OFFSET(%r30)
-       ldo FRAME_SIZE(%r30),%r30
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#endif
-       BL \execve,%r2
-       copy %r1,%arg0
-
-       ldo -FRAME_SIZE(%r30),%r30
-       LDREG -RP_OFFSET(%r30),%r2
-
-       /* If exec succeeded we need to load the args */
-
-       ldo -1024(%r0),%r1
-       cmpb,>>= %r28,%r1,error_\execve
-       copy %r2,%r19
-
-error_\execve:
-       bv %r0(%r19)
-       nop
-       .endm
-
-       .import sys_execve
-ENTRY(sys_execve_wrapper)
-       execve_wrapper sys_execve
-ENDPROC(sys_execve_wrapper)
-
-#ifdef CONFIG_64BIT
-       .import sys32_execve
-ENTRY(sys32_execve_wrapper)
-       execve_wrapper sys32_execve
-ENDPROC(sys32_execve_wrapper)
-#endif
-
 ENTRY(sys_rt_sigreturn_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
        ldo     TASK_REGS(%r26),%r26    /* get pt regs */
index cbc37216bf90f2fa5c64b5b1956272b9db237b8f..38db36f64307a9bafa8db66db12e8403fc873f97 100644 (file)
@@ -52,6 +52,7 @@
 
 #include <asm/io.h>
 #include <asm/asm-offsets.h>
+#include <asm/assembly.h>
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
 #include <asm/pgalloc.h>
@@ -164,23 +165,6 @@ void machine_power_off(void)
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-/*
- * Create a kernel thread
- */
-
-extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-
-       /*
-        * FIXME: Once we are sure we don't need any debug here,
-        *        kernel_thread can become a #define.
-        */
-
-       return __kernel_thread(fn, arg, flags);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Free current thread data structures etc..
  */
@@ -256,8 +240,8 @@ sys_vfork(struct pt_regs *regs)
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long unused,       /* in ia64 this is "user_stack_size" */
-           struct task_struct * p, struct pt_regs * pregs)
+           unsigned long arg,
+           struct task_struct *p, struct pt_regs *pregs)
 {
        struct pt_regs * cregs = &(p->thread.regs);
        void *stack = task_stack_page(p);
@@ -270,48 +254,32 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 #ifdef CONFIG_HPUX
        extern void * const hpux_child_return;
 #endif
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(cregs, 0, sizeof(struct pt_regs));
+               if (!usp) /* idle thread */
+                       return 0;
 
-       *cregs = *pregs;
-
-       /* Set the return value for the child.  Note that this is not
-           actually restored by the syscall exit path, but we put it
-           here for consistency in case of signals. */
-       cregs->gr[28] = 0; /* child */
-
-       /*
-        * We need to differentiate between a user fork and a
-        * kernel fork. We can't use user_mode, because the
-        * the syscall path doesn't save iaoq. Right now
-        * We rely on the fact that kernel_thread passes
-        * in zero for usp.
-        */
-       if (usp == 1) {
                /* kernel thread */
-               cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
                /* Must exit via ret_from_kernel_thread in order
                 * to call schedule_tail()
                 */
+               cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
                cregs->kpc = (unsigned long) &ret_from_kernel_thread;
                /*
                 * Copy function and argument to be called from
                 * ret_from_kernel_thread.
                 */
 #ifdef CONFIG_64BIT
-               cregs->gr[27] = pregs->gr[27];
+               cregs->gr[27] = ((unsigned long *)usp)[3];
+               cregs->gr[26] = ((unsigned long *)usp)[2];
+#else
+               cregs->gr[26] = usp;
 #endif
-               cregs->gr[26] = pregs->gr[26];
-               cregs->gr[25] = pregs->gr[25];
+               cregs->gr[25] = arg;
        } else {
                /* user thread */
-               /*
-                * Note that the fork wrappers are responsible
-                * for setting gr[21].
-                */
-
-               /* Use same stack depth as parent */
-               cregs->ksp = (unsigned long)stack
-                       + (pregs->gr[21] & (THREAD_SIZE - 1));
                cregs->gr[30] = usp;
+               cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
                if (personality(p->personality) == PER_HPUX) {
 #ifdef CONFIG_HPUX
                        cregs->kpc = (unsigned long) &hpux_child_return;
@@ -323,8 +291,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                }
                /* Setup thread TLS area from the 4th parameter in clone */
                if (clone_flags & CLONE_SETTLS)
-                 cregs->cr27 = pregs->gr[23];
-       
+                       cregs->cr27 = pregs->gr[23];
        }
 
        return 0;
@@ -335,39 +302,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
        return t->thread.regs.kpc;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-
-asmlinkage int sys_execve(struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname((const char __user *) regs->gr[26]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name,
-                         (const char __user *const __user *) regs->gr[25],
-                         (const char __user *const __user *) regs->gr[24],
-                         regs);
-       putname(filename);
-out:
-
-       return error;
-}
-
-extern int __execve(const char *filename,
-                   const char *const argv[],
-                   const char *const envp[], struct task_struct *task);
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       return __execve(filename, argv, envp, current);
-}
-
 unsigned long
 get_wchan(struct task_struct *p)
 {
index bf5b93a885d3cc6eb1b6ccd2ded74223b6cd2d32..9cfdaa19ab63314da7e04e0958eaadda0fadde9a 100644 (file)
 #define DBG(x)
 #endif
 
-/*
- * sys32_execve() executes a new program.
- */
-
-asmlinkage int sys32_execve(struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
-       filename = getname((const char __user *) regs->gr[26]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
-                                compat_ptr(regs->gr[24]), regs);
-       putname(filename);
-out:
-
-       return error;
-}
-
 asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
        int r22, int r21, int r20)
 {
index 3735abd7f8f6f067488b20de9b44ab487ac2dff2..cb2da96d6ab99317f84edadbca2f0dd67884e887 100644 (file)
@@ -66,7 +66,7 @@
        ENTRY_SAME(creat)
        ENTRY_SAME(link)
        ENTRY_SAME(unlink)              /* 10 */
-       ENTRY_DIFF(execve_wrapper)
+       ENTRY_COMP(execve)
        ENTRY_SAME(chdir)
        /* See comments in kernel/time.c!!! Maybe we don't need this? */
        ENTRY_COMP(time)
index a902a5c1c76a337280fb8b6d42500e0e6f2caffb..5af5aa707176ff460b5185b080749ecb32392401 100644 (file)
@@ -144,6 +144,7 @@ config PPC
        select GENERIC_KERNEL_THREAD
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_EXECVE
 
 config EARLY_PRINTK
        bool
index 921dce6d84458d3ef02b7b8ea1a6590809c226ef..280068cfff2e8721e39e4582277de4670bd09793 100644 (file)
@@ -56,7 +56,6 @@
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index 9499385676e784362c20eade975ae396aaff144d..d22e73e4618b7924879517f1f59cb99dcd63b43e 100644 (file)
@@ -444,11 +444,6 @@ ret_from_kernel_thread:
        PPC440EP_ERR42
        blrl
        li      r3,0
-       b       do_exit         # no return
-
-       .globl  __ret_from_kernel_execve
-__ret_from_kernel_execve:
-       addi    r1,r3,-STACK_FRAME_OVERHEAD
        b       ret_from_syscall
 
 /* Traced system call support */
index 56e0ff0878b5534c76b8c93818f7536498ce52df..e9a906c27234fe880a5c78bd9c80ef7835c712ab 100644 (file)
@@ -373,17 +373,11 @@ _GLOBAL(ret_from_fork)
 _GLOBAL(ret_from_kernel_thread)
        bl      .schedule_tail
        REST_NVGPRS(r1)
-       REST_GPR(2,r1)
+       ld      r14, 0(r14)
        mtlr    r14
        mr      r3,r15
        blrl
        li      r3,0
-       b       .do_exit        # no return
-
-_GLOBAL(__ret_from_kernel_execve)
-       addi    r1,r3,-STACK_FRAME_OVERHEAD
-       li      r10,1
-       std     r10,SOFTE(r1)
        b       syscall_exit
 
        .section        ".toc","aw"
index ba48233500f6d47d7f2a554f5023f23060b5cff2..f6d244db92030ba0e5938675ede2845e33b1f294 100644 (file)
@@ -745,25 +745,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        /* Copy registers */
        sp -= sizeof(struct pt_regs);
        childregs = (struct pt_regs *) sp;
-       if (!regs) {
-               /* for kernel thread, set `current' and stackptr in new task */
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               struct thread_info *ti = (void *)task_stack_page(p);
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gpr[1] = sp + sizeof(struct pt_regs);
+               childregs->gpr[14] = usp;       /* function */
 #ifdef CONFIG_PPC64
-               childregs->gpr[14] = *(unsigned long *)usp;
-               childregs->gpr[2] = ((unsigned long *)usp)[1],
                clear_tsk_thread_flag(p, TIF_32BIT);
-#else
-               childregs->gpr[14] = usp;       /* function */
-               childregs->gpr[2] = (unsigned long) p;
+               childregs->softe = 1;
 #endif
                childregs->gpr[15] = arg;
                p->thread.regs = NULL;  /* no user register state */
+               ti->flags |= _TIF_RESTOREALL;
                f = ret_from_kernel_thread;
        } else {
                CHECK_FULL_REGS(regs);
                *childregs = *regs;
-               childregs->gpr[1] = usp;
+               if (usp)
+                       childregs->gpr[1] = usp;
                p->thread.regs = childregs;
                childregs->gpr[3] = 0;  /* Result from fork() */
                if (clone_flags & CLONE_SETTLS) {
@@ -1027,22 +1026,11 @@ int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
        return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
 }
 
-#define TRUNC_PTR(x)   ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
-
 int sys_clone(unsigned long clone_flags, unsigned long usp,
              int __user *parent_tidp, void __user *child_threadptr,
              int __user *child_tidp, int p6,
              struct pt_regs *regs)
 {
-       CHECK_FULL_REGS(regs);
-       if (usp == 0)
-               usp = regs->gpr[1];     /* stack pointer for child */
-#ifdef CONFIG_PPC64
-       if (is_32bit_task()) {
-               parent_tidp = TRUNC_PTR(parent_tidp);
-               child_tidp = TRUNC_PTR(child_tidp);
-       }
-#endif
        return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
 }
 
@@ -1050,28 +1038,17 @@ int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
             unsigned long p4, unsigned long p5, unsigned long p6,
             struct pt_regs *regs)
 {
-       CHECK_FULL_REGS(regs);
-       return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
+       return do_fork(SIGCHLD, 0, regs, 0, NULL, NULL);
 }
 
 int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
              unsigned long p4, unsigned long p5, unsigned long p6,
              struct pt_regs *regs)
 {
-       CHECK_FULL_REGS(regs);
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
                        regs, 0, NULL, NULL);
 }
 
-void __ret_from_kernel_execve(struct pt_regs *normal)
-__noreturn;
-
-void ret_from_kernel_execve(struct pt_regs *normal)
-{
-       set_thread_flag(TIF_RESTOREALL);
-       __ret_from_kernel_execve(normal);
-}
-
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
                                  unsigned long nbytes)
 {
index d385f396dfee90172e5a984702cd9ded8a76387d..a163784e72c8df809690f0a446bc56749ee6b246 100644 (file)
@@ -138,6 +138,7 @@ config S390
        select KTIME_SCALAR if 32BIT
        select HAVE_ARCH_SECCOMP_FILTER
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
 
index bbbae41fa9a555dd587831a6c7e85a8a996d963c..ccbcab7742cdfb15502d0de1337a3d752be0b21f 100644 (file)
@@ -54,7 +54,6 @@
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index ef46f66bc0d6bdf0caa0dc4ecaae4225f3d3b1ef..aa8f2ba6289b2da57b409cbaec0a3a596206001a 100644 (file)
@@ -330,40 +330,18 @@ ENTRY(ret_from_fork)
        la      %r11,STACK_FRAME_OVERHEAD(%r15)
        l       %r12,__LC_THREAD_INFO
        l       %r13,__LC_SVC_NEW_PSW+4
-       tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
-       je      1f
        l       %r1,BASED(.Lschedule_tail)
        basr    %r14,%r1                # call schedule_tail
        TRACE_IRQS_ON
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       j       sysc_tracenogo
-
-1:     # it's a kernel thread
-       st      %r15,__PT_R15(%r11)     # store stack pointer for new kthread
-       l       %r1,BASED(.Lschedule_tail)
-       basr    %r14,%r1                # call schedule_tail
-       TRACE_IRQS_ON
-       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       lm      %r9,%r11,__PT_R9(%r11)  # load gprs
+       tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
+       jne     sysc_tracenogo
+       # it's a kernel thread
+       lm      %r9,%r10,__PT_R9(%r11)  # load gprs
 ENTRY(kernel_thread_starter)
        la      %r2,0(%r10)
        basr    %r14,%r9
-       la      %r2,0
-       br      %r11                    # do_exit
-
-#
-# kernel_execve function needs to deal with pt_regs that is not
-# at the usual place
-#
-ENTRY(ret_from_kernel_execve)
-       ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
-       lr      %r15,%r2
-       lr      %r11,%r2
-       ahi     %r15,-STACK_FRAME_OVERHEAD
-       xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
-       l       %r12,__LC_THREAD_INFO
-       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       j       sysc_return
+       j       sysc_tracenogo
 
 /*
  * Program check handler routine
index 07d8de353984da0fd8c8792348cebba214391c0c..499e95e90f38d9d785609a3c0ed2d1e41a5c8f15 100644 (file)
@@ -352,33 +352,17 @@ sysc_tracenogo:
 ENTRY(ret_from_fork)
        la      %r11,STACK_FRAME_OVERHEAD(%r15)
        lg      %r12,__LC_THREAD_INFO
-       tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
-       je      1f
        brasl   %r14,schedule_tail
        TRACE_IRQS_ON
        ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       j       sysc_tracenogo
-1:     # it's a kernel thread
-       stg     %r15,__PT_R15(%r11)     # store stack pointer for new kthread
-       brasl   %r14,schedule_tail
-       TRACE_IRQS_ON
-       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       lmg     %r9,%r11,__PT_R9(%r11)  # load gprs
+       tm      __PT_PSW+1(%r11),0x01   # forking a kernel thread ?
+       jne     sysc_tracenogo
+       # it's a kernel thread
+       lmg     %r9,%r10,__PT_R9(%r11)  # load gprs
 ENTRY(kernel_thread_starter)
        la      %r2,0(%r10)
        basr    %r14,%r9
-       la      %r2,0
-       br      %r11                    # do_exit
-
-ENTRY(ret_from_kernel_execve)
-       ssm     __LC_PGM_NEW_PSW        # disable I/O and ext. interrupts
-       lgr     %r15,%r2
-       lgr     %r11,%r2
-       aghi    %r15,-STACK_FRAME_OVERHEAD
-       xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
-       lg      %r12,__LC_THREAD_INFO
-       ssm     __LC_SVC_NEW_PSW        # reenable interrupts
-       j       sysc_return
+       j       sysc_tracenogo
 
 /*
  * Program check handler routine
index 4f93a431a45a8142133ae655bff700de79f7e254..a285e78fb9c563d1eab1e33daee7787b8aa44756 100644 (file)
@@ -13,6 +13,8 @@ config SCORE
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_REL
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 choice
        prompt "System type"
index ab3aceb542094e7a80eda7158c96665ace799214..d9a922d8711b2155a2225699e5958236dbb70adb 100644 (file)
@@ -13,7 +13,6 @@ struct task_struct;
  */
 extern void (*cpu_wait)(void);
 
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 extern void start_thread(struct pt_regs *regs,
                        unsigned long pc, unsigned long sp);
index 1dd5e0d6b0c35bd266297426765808ccff101cf5..8d332534342f608f5ae6c037707c73e94b7b8db8 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_SCORE_SYSCALLS_H
 
 asmlinkage long score_clone(struct pt_regs *regs);
-asmlinkage long score_execve(struct pt_regs *regs);
 asmlinkage long score_sigaltstack(struct pt_regs *regs);
 asmlinkage long score_rt_sigreturn(struct pt_regs *regs);
 
index a862384e9c16d80defe1b478bb40cd2c1e877f25..b006ca435120500d4ee75c10ef61ca02413e110b 100644 (file)
@@ -4,5 +4,6 @@
 #define __ARCH_WANT_SYSCALL_NO_FLAGS
 #define __ARCH_WANT_SYSCALL_OFF_T
 #define __ARCH_WANT_SYSCALL_DEPRECATED
+#define __ARCH_WANT_SYS_EXECVE
 
 #include <asm-generic/unistd.h>
index 83bb96079c43c513a832c6dd41a8de32a9cdffe6..da9901088bbbc907be62d85c367615ec2151462d 100644 (file)
@@ -278,6 +278,13 @@ need_resched:
        nop
 #endif
 
+ENTRY(ret_from_kernel_thread)
+       bl      schedule_tail                   # r4=struct task_struct *prev
+       nop
+       mv      r4, r13
+       brl     r12
+       j       syscall_exit
+
 ENTRY(ret_from_fork)
        bl      schedule_tail                   # r4=struct task_struct *prev
 
@@ -480,11 +487,6 @@ illegal_syscall:
        sw      r9, [r0, PT_R7]
        j       syscall_return
 
-ENTRY(sys_execve)
-       mv      r4, r0
-       la      r8, score_execve
-       br      r8
-
 ENTRY(sys_clone)
        mv      r4, r0
        la      r8, score_clone
index 637970cfd3f41454f33af2eaa3f2255541dd21b5..6f311cf64b9987385b473e6a8f7209defd78af76 100644 (file)
@@ -60,6 +60,7 @@ void __noreturn cpu_idle(void)
 }
 
 void ret_from_fork(void);
+void ret_from_kernel_thread(void);
 
 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
 {
@@ -86,29 +87,27 @@ void flush_thread(void) {}
  * set up the kernel stack and exception frames for a new process
  */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       p->set_child_tid = NULL;
-       p->clear_child_tid = NULL;
-
-       *childregs = *regs;
-       childregs->regs[7] = 0;         /* Clear error flag */
-       childregs->regs[4] = 0;         /* Child gets zero as return value */
-       regs->regs[4] = p->pid;
-
-       if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */
-               childregs->regs[0] = usp;               /* user fork */
+       p->thread.reg0 = (unsigned long) childregs;
+       if (unlikely(!regs)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               p->thread->reg12 = usp;
+               p->thread->reg13 = arg;
+               p->thread.reg3 = (unsigned long) ret_from_kernel_thread;
        } else {
-               childregs->regs[28] = (unsigned long) ti; /* kernel fork */
-               childregs->regs[0] = (unsigned long) childregs;
+               *childregs = *regs;
+               childregs->regs[7] = 0;         /* Clear error flag */
+               childregs->regs[4] = 0;         /* Child gets zero as return value */
+               childregs->regs[0] = usp;       /* user fork */
+               regs->regs[4] = p->pid;         /* WTF? */
+               p->thread.reg3 = (unsigned long) ret_from_fork;
        }
 
-       p->thread.reg0 = (unsigned long) childregs;
-       p->thread.reg3 = (unsigned long) ret_from_fork;
        p->thread.cp0_psr = 0;
 
        return 0;
@@ -120,32 +119,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
        return 1;
 }
 
-static void __noreturn
-kernel_thread_helper(void *unused0, int (*fn)(void *),
-                void *arg, void *unused1)
-{
-       do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread.
- */
-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.regs[6] = (unsigned long) arg;
-       regs.regs[5] = (unsigned long) fn;
-       regs.cp0_epc = (unsigned long) kernel_thread_helper;
-       regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \
-                       ((regs.cp0_psr & 0x3) << 2);
-
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \
-                       0, &regs, 0, NULL, NULL);
-}
-
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
        return task_pt_regs(tsk)->cp0_epc;
index d45cf00a33511aee8c6616fc419569714bc6ebf8..c54434c2fd9dfeb8a5578d5c73d0e4987242856c 100644 (file)
@@ -83,57 +83,3 @@ score_vfork(struct pt_regs *regs)
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
                        regs->regs[0], regs, 0, NULL, NULL);
 }
-
-/*
- * sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long
-score_execve(struct pt_regs *regs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname((char __user*)regs->regs[4]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-
-       error = do_execve(filename->name,
-                         (const char __user *const __user *)regs->regs[5],
-                         (const char __user *const __user *)regs->regs[6],
-                         regs);
-
-       putname(filename);
-       return error;
-}
-
-/*
- * 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 unsigned long __r4 asm("r4") = (unsigned long) filename;
-       register unsigned long __r5 asm("r5") = (unsigned long) argv;
-       register unsigned long __r6 asm("r6") = (unsigned long) envp;
-       register unsigned long __r7 asm("r7");
-
-       __asm__ __volatile__ (" \n"
-               "ldi    r27, %5         \n"
-               "syscall                \n"
-               "mv     %0, r4          \n"
-               "mv     %1, r7          \n"
-               : "=&r" (__r4), "=r" (__r7)
-               : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve)
-               : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25",
-                 "r26", "r27", "memory");
-
-       if (__r7 == 0)
-               return __r4;
-
-       return -__r4;
-}
index babc2b826c5caf5f26f9a029452e5067451190c1..8451317eed58d3b79bc7ec3df8df6eac0b20fd0d 100644 (file)
@@ -40,6 +40,8 @@ config SUPERH
        select GENERIC_STRNLEN_USER
        select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
index b6311fd2d066a1db774409f1dac29f2b856290e4..b1320d55ca305139f5087694a6c6b3c2db3a6990 100644 (file)
@@ -126,11 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo
 /* 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 */
 #define copy_segments(p, mm)   do { } while(0)
 #define release_segments(mm)   do { } while(0)
index cd6029fb2c015f89742e3519b5b04172ef39ce5e..1ee8946f09520a987a19ae477cac15087f19bf4a 100644 (file)
@@ -159,11 +159,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 */
 #define copy_segments(p, mm)   do { } while (0)
index 6c1fa559753c10b6f8f4d1d78d10492d7c318cc1..d2f89f1741f4d3d67d4a12f1d6107dea1f4fe64c 100644 (file)
@@ -19,10 +19,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs __regs);
-asmlinkage int sys_execve(const char __user *ufilename,
-                         const char __user *const __user *uargv,
-                         const char __user *const __user *uenvp,
-                         unsigned long r7, struct pt_regs __regs);
 asmlinkage int sys_sigsuspend(old_sigset_t mask);
 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
                             struct old_sigaction __user *oact);
index ee519f41d9500561b75c31caf0b293557e1d7e76..3fedd9f1fab50d9470b749ba4b466962d0509c71 100644 (file)
@@ -21,10 +21,6 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
                         unsigned long r4, unsigned long r5,
                         unsigned long r6, unsigned long r7,
                         struct pt_regs *pregs);
-asmlinkage int sys_execve(const char *ufilename, char **uargv,
-                         char **uenvp, unsigned long r5,
-                         unsigned long r6, unsigned long r7,
-                         struct pt_regs *pregs);
 
 /* Misc syscall related bits */
 asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
index 38956dfa76f7fb52137375470d0ccb5b35f1741d..f1f4775766a64dea0a29b824496e34a9fab60a7f 100644 (file)
@@ -28,6 +28,7 @@
 # define __ARCH_WANT_SYS_SIGPENDING
 # define __ARCH_WANT_SYS_SIGPROCMASK
 # define __ARCH_WANT_SYS_RT_SIGACTION
+# define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index 88571ff8eeec463fd36d68dc67f7cf0a9cc1b8e1..f259b37874e907176dfe8ee3a50cde1cef9fdc72 100644 (file)
@@ -16,7 +16,7 @@ obj-y := debugtraps.o dma-nommu.o dumpstack.o                 \
           machvec.o nmi_debug.o process.o                              \
           process_$(BITS).o ptrace.o ptrace_$(BITS).o                  \
           reboot.o return_address.o                                    \
-          setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o            \
+          setup.o signal_$(BITS).o sys_sh.o                            \
           syscalls_$(BITS).o time.o topology.o traps.o                 \
           traps_$(BITS).o unwinder.o
 
@@ -25,6 +25,7 @@ obj-y                         += iomap.o
 obj-$(CONFIG_HAS_IOPORT)       += ioport.o
 endif
 
+obj-$(CONFIG_SUPERH32)         += sys_sh32.o
 obj-y                          += cpu/
 obj-$(CONFIG_VSYSCALL)         += vsyscall/
 obj-$(CONFIG_SMP)              += smp.o
index 7e605b95592aea7ac767b817df3a7a61af8d4f20..0c8d0377d40bdf005a1d90e9929b9fe26011b0a9 100644 (file)
@@ -1228,6 +1228,25 @@ ret_from_fork:
        pta     ret_from_syscall, tr0
        blink   tr0, ZERO
 
+.global        ret_from_kernel_thread
+ret_from_kernel_thread:
+
+       movi    schedule_tail,r5
+       ori     r5, 1, r5
+       ptabs   r5, tr0
+       blink   tr0, LINK
+
+       ld.q    SP, FRAME_R(2), r2
+       ld.q    SP, FRAME_R(3), r3
+       ptabs   r3, tr0
+       blink   tr0, LINK
+
+       ld.q    SP, FRAME_S(FSPC), r2
+       addi    r2, 4, r2               /* Move PC, being pre-execution event */
+       st.q    SP, FRAME_S(FSPC), r2
+       pta     ret_from_syscall, tr0
+       blink   tr0, ZERO
+
 syscall_allowed:
        /* Use LINK to deflect the exit point, default is syscall_ret */
        pta     syscall_ret, tr0
index b96489d8b27dde9e38630d51de4e9d7f04115c08..9b6e4beeb296261c2fb5b315377822e236c587cf 100644 (file)
@@ -297,6 +297,19 @@ ret_from_fork:
         mov    r0, r4
        bra     syscall_exit
         nop
+
+       .align  2
+       .globl  ret_from_kernel_thread
+ret_from_kernel_thread:
+       mov.l   1f, r8
+       jsr     @r8
+        mov    r0, r4
+       mov.l   @(OFF_R5,r15), r5   ! fn
+       jsr     @r5
+        mov.l  @(OFF_R4,r15), r4   ! arg
+       bra     syscall_exit
+        nop
+
        .align  2
 1:     .long   schedule_tail
 
index ba7345f37bc9d0c6a1e4cc62760ca5e34fe65342..fce8029de922f1bbc0be0b2bf6cd54aea0ba2de4 100644 (file)
@@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs)
        show_code(regs);
 }
 
-/*
- * Create a kernel thread
- */
-__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-       do_exit(fn(arg));
-}
-
-/* Don't use this in BL=1(cli).  Or else, CPU resets! */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-       int pid;
-
-       memset(&regs, 0, sizeof(regs));
-       regs.regs[4] = (unsigned long)arg;
-       regs.regs[5] = (unsigned long)fn;
-
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.sr = SR_MD;
-#if defined(CONFIG_SH_FPU)
-       regs.sr |= SR_FD;
-#endif
-
-       /* Ok, create the new process.. */
-       pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-                     &regs, 0, NULL, NULL);
-
-       return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void start_thread(struct pt_regs *regs, unsigned long new_pc,
                  unsigned long new_sp)
 {
@@ -157,9 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 EXPORT_SYMBOL(dump_fpu);
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *ti = task_thread_info(p);
@@ -177,29 +146,34 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        }
 #endif
 
-       childregs = task_pt_regs(p);
-       *childregs = *regs;
+       memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
 
-       if (user_mode(regs)) {
-               childregs->regs[15] = usp;
-               ti->addr_limit = USER_DS;
-       } else {
-               childregs->regs[15] = (unsigned long)childregs;
+       childregs = task_pt_regs(p);
+       p->thread.sp = (unsigned long) childregs;
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               p->thread.pc = (unsigned long) ret_from_kernel_thread;
+               childregs->regs[4] = arg;
+               childregs->regs[5] = usp;
+               childregs->sr = SR_MD;
+#if defined(CONFIG_SH_FPU)
+               childregs->sr |= SR_FD;
+#endif
                ti->addr_limit = KERNEL_DS;
                ti->status &= ~TS_USEDFPU;
                p->fpu_counter = 0;
+               return 0;
        }
+       *childregs = *regs;
+
+       childregs->regs[15] = usp;
+       ti->addr_limit = USER_DS;
 
        if (clone_flags & CLONE_SETTLS)
                childregs->gbr = childregs->regs[0];
 
        childregs->regs[0] = 0; /* Set return value for child */
-
-       p->thread.sp = (unsigned long) childregs;
        p->thread.pc = (unsigned long) ret_from_fork;
-
-       memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
-
        return 0;
 }
 
@@ -288,29 +262,6 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
                       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 r7, struct pt_regs __regs)
-{
-       struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-       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, regs);
-       putname(filename);
-out:
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long pc;
index 98a709f0c3c45c1f6ece40d34b79a69cd4de4e2c..3a0f3fd3bb58fd9128759e0c8252606a30c37007 100644 (file)
@@ -284,39 +284,6 @@ void show_regs(struct pt_regs *regs)
        }
 }
 
-/*
- * Create a kernel thread
- */
-__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
-{
-       do_exit(fn(arg));
-}
-
-/*
- * 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 freed until both the parent and the child have exited.
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-       regs.regs[2] = (unsigned long)arg;
-       regs.regs[3] = (unsigned long)fn;
-
-       regs.pc = (unsigned long)kernel_thread_helper;
-       regs.sr = (1 << 30);
-
-       /* 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..
  */
@@ -401,15 +368,17 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 EXPORT_SYMBOL(dump_fpu);
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct pt_regs *childregs;
 
 #ifdef CONFIG_SH_FPU
-       if(last_task_used_math == current) {
+       /* can't happen for a kernel thread */
+       if (last_task_used_math == current) {
                enable_fpu();
                save_fpu(current);
                disable_fpu();
@@ -419,7 +388,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 #endif
        /* Copy from sh version */
        childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;
+       p->thread.sp = (unsigned long) childregs;
 
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childregs, 0, sizeof(struct pt_regs));
+               childregs->regs[2] = (unsigned long)arg;
+               childregs->regs[3] = (unsigned long)fn;
+               childregs->sr = (1 << 30); /* not user_mode */
+               childregs->sr |= SR_FD; /* Invalidate FPU flag */
+               p->thread.pc = (unsigned long) ret_from_kernel_thread;
+               return 0;
+       }
        *childregs = *regs;
 
        /*
@@ -428,19 +407,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
         * 32-bit wide and context switch must take care
         * of NEFF sign extension.
         */
-       if (user_mode(regs)) {
-               childregs->regs[15] = neff_sign_extend(usp);
-               p->thread.uregs = childregs;
-       } else {
-               childregs->regs[15] =
-                       neff_sign_extend((unsigned long)task_stack_page(p) +
-                                        THREAD_SIZE);
-       }
+       childregs->regs[15] = neff_sign_extend(usp);
+       p->thread.uregs = childregs;
 
        childregs->regs[9] = 0; /* Set return value for child */
        childregs->sr |= SR_FD; /* Invalidate FPU flag */
 
-       p->thread.sp = (unsigned long) childregs;
        p->thread.pc = (unsigned long) ret_from_fork;
 
        return 0;
@@ -482,31 +454,6 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *ufilename, char **uargv,
-                         char **uenvp, unsigned long r5,
-                         unsigned long r6, unsigned long r7,
-                         struct pt_regs *pregs)
-{
-       int error;
-       struct filename *filename;
-
-       filename = getname((char __user *)ufilename);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-
-       error = do_execve(filename->name,
-                         (const char __user *const __user *)uargv,
-                         (const char __user *const __user *)uenvp,
-                         pregs);
-       putname(filename);
-out:
-       return error;
-}
-
 #ifdef CONFIG_FRAME_POINTER
 static int in_sh64_switch_to(unsigned long pc)
 {
index f56b6fe5c5d02d7cdb5084bce5732cba7c32ec68..497bab3a04015ca08774aa1771d47f40418d0b10 100644 (file)
@@ -60,27 +60,3 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
                                (u64)len0 << 32 | len1, advice);
 #endif
 }
-
-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
-#define SYSCALL_ARG3   "trapa #0x23"
-#else
-#define SYSCALL_ARG3   "trapa #0x13"
-#endif
-
-/*
- * 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 __sc0 __asm__ ("r3") = __NR_execve;
-       register long __sc4 __asm__ ("r4") = (long) filename;
-       register long __sc5 __asm__ ("r5") = (long) argv;
-       register long __sc6 __asm__ ("r6") = (long) envp;
-       __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)
-                       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
-                       : "memory");
-       return __sc0;
-}
diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c
deleted file mode 100644 (file)
index c5a38c4..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/sh/kernel/sys_sh64.c
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/SH5
- * platform.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/errno.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/syscalls.h>
-#include <linux/ipc.h>
-#include <asm/uaccess.h>
-#include <asm/ptrace.h>
-#include <asm/unistd.h>
-
-/*
- * 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 unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve);
-       register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename;
-       register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv;
-       register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp;
-       __asm__ __volatile__ ("trapa    %1 !\t\t\t execve(%2,%3,%4)"
-       : "=r" (__sc0)
-       : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );
-       __asm__ __volatile__ ("!dummy   %0 %1 %2 %3"
-       : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory");
-       return __sc0;
-}
index 9f2edb5c555179de8d00ee5d2031546df35f8a9d..0c7d365fa402d90dacbc9566ee8eb121b726b75a 100644 (file)
@@ -41,6 +41,8 @@ config SPARC
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config SPARC32
        def_bool !64BIT
index f74ac9ee33a8ef461f0277af60731adf7a0f904a..c1e01914fd98b53c48a4aee32dccaa2e7fbb0c82 100644 (file)
@@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)            do { } while(0)
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long get_wchan(struct task_struct *);
 
index 721e25f0e2ea80f19d4a7868791d4653097a2124..cce72ce4c33499c21d20b31cf69f28bfa189d239 100644 (file)
@@ -94,6 +94,7 @@ struct thread_struct {
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/fpumacro.h>
 
 /* Return saved PC of a blocked thread. */
 struct task_struct;
@@ -143,6 +144,10 @@ do { \
        : \
        : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
          "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+       fprs_write(0);  \
+       current_thread_info()->xfsr[0] = 0;     \
+       current_thread_info()->fpsaved[0] = 0;  \
+       regs->tstate &= ~TSTATE_PEF;    \
 } while (0)
 
 #define start_thread32(regs, pc, sp) \
@@ -183,13 +188,15 @@ do { \
        : \
        : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
          "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+       fprs_write(0);  \
+       current_thread_info()->xfsr[0] = 0;     \
+       current_thread_info()->fpsaved[0] = 0;  \
+       regs->tstate &= ~TSTATE_PEF;    \
 } while (0)
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)            do { } while (0)
 
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long get_wchan(struct task_struct *task);
 
 #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
index da43bdc622943bf422a396abba301148151f8f96..bdfafd7af46fb48eeb04e25787733b0500f66d07 100644 (file)
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define arch_ptrace_stop(exit_code, info) \
        synchronize_user_stack()
 
+#define current_pt_regs() \
+       ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 struct global_reg_snapshot {
        unsigned long           tstate;
        unsigned long           tpc;
@@ -55,9 +58,7 @@ union global_cpu_snapshot {
 
 extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
 
-#define force_successful_syscall_return()          \
-do {   current_thread_info()->syscall_noerror = 1; \
-} while (0)
+#define force_successful_syscall_return() set_thread_noerror(1)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
 #define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
@@ -100,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
 #define arch_ptrace_stop(exit_code, info) \
        synchronize_user_stack()
 
+#define current_pt_regs() \
+       ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
index 7923c4a2be388a963d94f1b0c050b8cb78fab7bd..cad36f56fa03e6605797c4dca13f5127048b47d7 100644 (file)
@@ -23,7 +23,7 @@ do {  flush_tlb_pending();                                            \
        /* If you are tempted to conditionalize the following */        \
        /* so that ASI is only written if it changes, think again. */   \
        __asm__ __volatile__("wr %%g0, %0, %%asi"                       \
-       : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
+       : : "r" (task_thread_info(next)->current_ds));\
        trap_block[current_thread_info()->cpu].thread =                 \
                task_thread_info(next);                                 \
        __asm__ __volatile__(                                           \
index 45a43f637a1480291f6a85ef532c8717bb30046d..bf8972adea173329cabc6dc4044d8c6dd8089d7e 100644 (file)
@@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
                                     struct pt_regs *regs,
                                     unsigned long stack_size);
 
-extern asmlinkage int sparc_execve(struct pt_regs *regs);
-
 #endif /* _SPARC64_SYSCALLS_H */
index a3fe4dcc0aa6c5d25c7fa67ce3c74390b3a01876..269bd92313df76e3c2261c464ded3c5c45be4efd 100644 (file)
 #define TI_FLAG_FAULT_CODE_SHIFT       56
 #define TI_FLAG_BYTE_WSTATE            1
 #define TI_FLAG_WSTATE_SHIFT           48
-#define TI_FLAG_BYTE_CWP               2
-#define TI_FLAG_CWP_SHIFT              40
-#define TI_FLAG_BYTE_CURRENT_DS                3
-#define TI_FLAG_CURRENT_DS_SHIFT       32
-#define TI_FLAG_BYTE_FPDEPTH           4
-#define TI_FLAG_FPDEPTH_SHIFT          24
+#define TI_FLAG_BYTE_NOERROR           2
+#define TI_FLAG_BYTE_NOERROR_SHIFT     40
+#define TI_FLAG_BYTE_FPDEPTH           3
+#define TI_FLAG_FPDEPTH_SHIFT          32
+#define TI_FLAG_BYTE_CWP               4
+#define TI_FLAG_CWP_SHIFT              24
 #define TI_FLAG_BYTE_WSAVED            5
 #define TI_FLAG_WSAVED_SHIFT           16
 
@@ -47,7 +47,7 @@ struct thread_info {
        struct exec_domain      *exec_domain;
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        __u8                    new_child;
-       __u8                    syscall_noerror;
+       __u8                    current_ds;
        __u16                   cpu;
 
        unsigned long           *utraps;
@@ -74,9 +74,9 @@ struct thread_info {
 #define TI_FAULT_CODE  (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
 #define TI_WSTATE      (TI_FLAGS + TI_FLAG_BYTE_WSTATE)
 #define TI_CWP         (TI_FLAGS + TI_FLAG_BYTE_CWP)
-#define TI_CURRENT_DS  (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
 #define TI_FPDEPTH     (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
 #define TI_WSAVED      (TI_FLAGS + TI_FLAG_BYTE_WSAVED)
+#define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR)
 #define TI_FPSAVED     0x00000010
 #define TI_KSP         0x00000018
 #define TI_FAULT_ADDR  0x00000020
@@ -84,7 +84,7 @@ struct thread_info {
 #define TI_EXEC_DOMAIN 0x00000030
 #define TI_PRE_COUNT   0x00000038
 #define TI_NEW_CHILD   0x0000003c
-#define TI_SYS_NOERROR 0x0000003d
+#define TI_CURRENT_DS  0x0000003d
 #define TI_CPU         0x0000003e
 #define TI_UTRAPS      0x00000040
 #define TI_REG_WINDOW  0x00000048
@@ -121,7 +121,7 @@ struct thread_info {
 #define INIT_THREAD_INFO(tsk)                          \
 {                                                      \
        .task           =       &tsk,                   \
-       .flags          = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,   \
+       .current_ds     =       ASI_P,                  \
        .exec_domain    =       &default_exec_domain,   \
        .preempt_count  =       INIT_PREEMPT_COUNT,     \
        .restart_block  = {                             \
@@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define set_thread_wstate(val)         (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
 #define get_thread_cwp()               (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
 #define set_thread_cwp(val)            (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
-#define get_thread_current_ds()                (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS])
-#define set_thread_current_ds(val)     (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val))
+#define get_thread_noerror()           (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR])
+#define set_thread_noerror(val)                (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val))
 #define get_thread_fpdepth()           (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
 #define set_thread_fpdepth(val)                (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
 #define get_thread_wsaved()            (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
 #define set_thread_wsaved(val)         (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
-
 #endif /* !(__ASSEMBLY__) */
 
 /*
index 73083e1d38d9b9cd5e4a032183f3367765b88add..e562d3caee57457a3b188f13b2959d47a7f835b4 100644 (file)
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-#define get_fs() ((mm_segment_t) { get_thread_current_ds() })
+#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)})
 #define get_ds() (KERNEL_DS)
 
 #define segment_eq(a,b)  ((a).seg == (b).seg)
 
 #define set_fs(val)                                                            \
 do {                                                                           \
-       set_thread_current_ds((val).seg);                                       \
+       current_thread_info()->current_ds =(val).seg;                           \
        __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));        \
 } while(0)
 
index 0ecea6ed943e3a5b525e90711ef80a5cdbc16f57..c3e5d8b6417123b19ff0383abb063d85d82db243 100644 (file)
@@ -46,6 +46,7 @@
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_SENDFILE
 #endif
+#define __ARCH_WANT_SYS_EXECVE
 
 /*
  * "Conditional" syscalls
index dcaa1cf0de40c790b27b32fbbdfe997cfdee072f..21fd1a8f47d2c57c3f403a7a5ab47eeb88d6cf54 100644 (file)
@@ -806,23 +806,10 @@ sys_nis_syscall:
        call    c_sys_nis_syscall
         mov    %l5, %o7
 
-       .align  4
-       .globl  sys_execve
-sys_execve:
-       mov     %o7, %l5
-       add     %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
-       call    sparc_execve
-        mov    %l5, %o7
-
-       .globl  sunos_execv
 sunos_execv:
-       st      %g0, [%sp + STACKFRAME_SZ + PT_I2]
-
-       call    sparc_execve
-        add    %sp, STACKFRAME_SZ, %o0
-
-       b       ret_sys_call
-        ld     [%sp + STACKFRAME_SZ + PT_I0], %o0
+       .globl  sunos_execv
+       b       sys_execve
+        clr    %i2
 
        .align  4
        .globl  sys_sparc_pipe
@@ -959,17 +946,9 @@ flush_patch_four:
         .align  4
 linux_sparc_ni_syscall:
        sethi   %hi(sys_ni_syscall), %l7
-       b       syscall_is_too_hard
+       b       do_syscall
         or     %l7, %lo(sys_ni_syscall), %l7
 
-linux_fast_syscall:
-       andn    %l7, 3, %l7
-       mov     %i0, %o0
-       mov     %i1, %o1
-       mov     %i2, %o2
-       jmpl    %l7 + %g0, %g0
-        mov    %i3, %o3
-
 linux_syscall_trace:
        add     %sp, STACKFRAME_SZ, %o0
        call    syscall_trace
@@ -991,6 +970,23 @@ ret_from_fork:
        b       ret_sys_call
         ld     [%sp + STACKFRAME_SZ + PT_I0], %o0
 
+       .globl  ret_from_kernel_thread
+ret_from_kernel_thread:
+       call    schedule_tail
+        ld     [%g3 + TI_TASK], %o0
+       ld      [%sp + STACKFRAME_SZ + PT_G1], %l0
+       call    %l0
+        ld     [%sp + STACKFRAME_SZ + PT_G2], %o0
+       rd      %psr, %l1
+       ld      [%sp + STACKFRAME_SZ + PT_PSR], %l0
+       andn    %l0, PSR_CWP, %l0
+       nop
+       and     %l1, PSR_CWP, %l1
+       or      %l0, %l1, %l0
+       st      %l0, [%sp + STACKFRAME_SZ + PT_PSR]
+       b       ret_sys_call
+        mov    0, %o0
+
        /* Linux native system calls enter here... */
        .align  4
        .globl  linux_sparc_syscall
@@ -1002,11 +998,8 @@ linux_sparc_syscall:
        bgeu    linux_sparc_ni_syscall
         sll    %g1, 2, %l4
        ld      [%l7 + %l4], %l7
-       andcc   %l7, 1, %g0
-       bne     linux_fast_syscall
-        /* Just do first insn from SAVE_ALL in the delay slot */
 
-syscall_is_too_hard:
+do_syscall:
        SAVE_ALL_HEAD
         rd     %wim, %l3
 
index 786b185e6e3fa8d37e6cac8b820b0654b1b787c3..1276ca2567bab310771d214baa77876ea9e43f0e 100644 (file)
@@ -92,8 +92,10 @@ etrap_save:  save    %g2, -STACK_BIAS, %sp
                rdpr    %wstate, %g2
                wrpr    %g0, 0, %canrestore
                sll     %g2, 3, %g2
+
+               /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR.  */
                mov     1, %l5
-               stb     %l5, [%l6 + TI_FPDEPTH]
+               sth     %l5, [%l6 + TI_SYS_NOERROR]
 
                wrpr    %g3, 0, %otherwin
                wrpr    %g2, 0, %wstate
@@ -152,7 +154,9 @@ etrap_save: save    %g2, -STACK_BIAS, %sp
                add     %l6, TI_FPSAVED + 1, %l4
                srl     %l5, 1, %l3
                add     %l5, 2, %l5
-               stb     %l5, [%l6 + TI_FPDEPTH]
+
+               /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR.  */
+               sth     %l5, [%l6 + TI_SYS_NOERROR]
                ba,pt   %xcc, 2b
                 stb    %g0, [%l4 + %l3]
                nop
index 487bffb36f5eb4a2792808e317e845cdaa8553d1..bf4c6addce7b161aa39b87e50ee5972d324b14e0 100644 (file)
@@ -316,9 +316,10 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
  * XXX See comment above sys_vfork in sparc64. todo.
  */
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *ti = task_thread_info(p);
@@ -336,16 +337,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        }
 
        /*
-        *  p->thread_info         new_stack   childregs
-        *  !                      !           !             {if(PSR_PS) }
-        *  V                      V (stk.fr.) V  (pt_regs)  { (stk.fr.) }
-        *  +----- - - - - - ------+===========+============={+==========}+
+        *  p->thread_info         new_stack   childregs stack bottom
+        *  !                      !           !             !
+        *  V                      V (stk.fr.) V  (pt_regs)  V
+        *  +----- - - - - - ------+===========+=============+
         */
        new_stack = task_stack_page(p) + THREAD_SIZE;
-       if (regs->psr & PSR_PS)
-               new_stack -= STACKFRAME_SZ;
        new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
-       memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
        childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
 
        /*
@@ -356,55 +354,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
         * Thus, kpsr|=PSR_PIL.
         */
        ti->ksp = (unsigned long) new_stack;
+       p->thread.kregs = childregs;
+
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               extern int nwindows;
+               unsigned long psr;
+               memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
+               p->thread.flags |= SPARC_FLAG_KTHREAD;
+               p->thread.current_ds = KERNEL_DS;
+               ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
+               childregs->u_regs[UREG_G1] = sp; /* function */
+               childregs->u_regs[UREG_G2] = arg;
+               psr = childregs->psr = get_psr();
+               ti->kpsr = psr | PSR_PIL;
+               ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);
+               return 0;
+       }
+       memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
+       childregs->u_regs[UREG_FP] = sp;
+       p->thread.flags &= ~SPARC_FLAG_KTHREAD;
+       p->thread.current_ds = USER_DS;
        ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
        ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
        ti->kwim = current->thread.fork_kwim;
 
-       if(regs->psr & PSR_PS) {
-               extern struct pt_regs fake_swapper_regs;
+       if (sp != regs->u_regs[UREG_FP]) {
+               struct sparc_stackf __user *childstack;
+               struct sparc_stackf __user *parentstack;
 
-               p->thread.kregs = &fake_swapper_regs;
-               new_stack += STACKFRAME_SZ + TRACEREG_SZ;
-               childregs->u_regs[UREG_FP] = (unsigned long) new_stack;
-               p->thread.flags |= SPARC_FLAG_KTHREAD;
-               p->thread.current_ds = KERNEL_DS;
-               memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ);
-               childregs->u_regs[UREG_G6] = (unsigned long) ti;
-       } else {
-               p->thread.kregs = childregs;
-               childregs->u_regs[UREG_FP] = sp;
-               p->thread.flags &= ~SPARC_FLAG_KTHREAD;
-               p->thread.current_ds = USER_DS;
-
-               if (sp != regs->u_regs[UREG_FP]) {
-                       struct sparc_stackf __user *childstack;
-                       struct sparc_stackf __user *parentstack;
-
-                       /*
-                        * This is a clone() call with supplied user stack.
-                        * Set some valid stack frames to give to the child.
-                        */
-                       childstack = (struct sparc_stackf __user *)
-                               (sp & ~0xfUL);
-                       parentstack = (struct sparc_stackf __user *)
-                               regs->u_regs[UREG_FP];
+               /*
+                * This is a clone() call with supplied user stack.
+                * Set some valid stack frames to give to the child.
+                */
+               childstack = (struct sparc_stackf __user *)
+                       (sp & ~0xfUL);
+               parentstack = (struct sparc_stackf __user *)
+                       regs->u_regs[UREG_FP];
 
 #if 0
-                       printk("clone: parent stack:\n");
-                       show_stackframe(parentstack);
+               printk("clone: parent stack:\n");
+               show_stackframe(parentstack);
 #endif
 
-                       childstack = clone_stackframe(childstack, parentstack);
-                       if (!childstack)
-                               return -EFAULT;
+               childstack = clone_stackframe(childstack, parentstack);
+               if (!childstack)
+                       return -EFAULT;
 
 #if 0
-                       printk("clone: child stack:\n");
-                       show_stackframe(childstack);
+               printk("clone: child stack:\n");
+               show_stackframe(childstack);
 #endif
 
-                       childregs->u_regs[UREG_FP] = (unsigned long)childstack;
-               }
+               childregs->u_regs[UREG_FP] = (unsigned long)childstack;
        }
 
 #ifdef CONFIG_SMP
@@ -475,69 +476,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
        return 1;
 }
 
-/*
- * sparc_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage int sparc_execve(struct pt_regs *regs)
-{
-       int error, base = 0;
-       struct filename *filename;
-
-       /* Check for indirect call. */
-       if(regs->u_regs[UREG_G1] == 0)
-               base = 1;
-
-       filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
-       error = PTR_ERR(filename);
-       if(IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name,
-                         (const char __user *const  __user *)
-                         regs->u_regs[base + UREG_I1],
-                         (const char __user *const  __user *)
-                         regs->u_regs[base + UREG_I2],
-                         regs);
-       putname(filename);
-out:
-       return error;
-}
-
-/*
- * 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 freed until both the parent and the child have exited.
- */
-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       long retval;
-
-       __asm__ __volatile__("mov %4, %%g2\n\t"    /* Set aside fn ptr... */
-                            "mov %5, %%g3\n\t"    /* and arg. */
-                            "mov %1, %%g1\n\t"
-                            "mov %2, %%o0\n\t"    /* Clone flags. */
-                            "mov 0, %%o1\n\t"     /* usp arg == 0 */
-                            "t 0x10\n\t"          /* Linux/Sparc clone(). */
-                            "cmp %%o1, 0\n\t"
-                            "be 1f\n\t"           /* The parent, just return. */
-                            " nop\n\t"            /* Delay slot. */
-                            "jmpl %%g2, %%o7\n\t" /* Call the function. */
-                            " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
-                            "mov %3, %%g1\n\t"
-                            "t 0x10\n\t"          /* Linux/Sparc exit(). */
-                            /* Notreached by child. */
-                            "1: mov %%o0, %0\n\t" :
-                            "=r" (retval) :
-                            "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
-                            "i" (__NR_exit),  "r" (fn), "r" (arg) :
-                            "g1", "g2", "g3", "o0", "o1", "memory", "cc");
-       return retval;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc, fp, bias = 0;
index c6e0c2910043556a073ba8e8f11843f09d20ca71..dff54f46728d697548bc9a4580216171a717b18d 100644 (file)
@@ -622,64 +622,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
  * Child  -->  %o0 == parents pid, %o1 == 1
  */
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long unused,
+               unsigned long arg,
                struct task_struct *p, struct pt_regs *regs)
 {
        struct thread_info *t = task_thread_info(p);
        struct sparc_stackf *parent_sf;
        unsigned long child_stack_sz;
        char *child_trap_frame;
-       int kernel_thread;
-
-       kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0;
-       parent_sf = ((struct sparc_stackf *) regs) - 1;
 
        /* Calculate offset to stack_frame & pt_regs */
-       child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) +
-                         (kernel_thread ? STACKFRAME_SZ : 0));
+       child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
        child_trap_frame = (task_stack_page(p) +
                            (THREAD_SIZE - child_stack_sz));
-       memcpy(child_trap_frame, parent_sf, child_stack_sz);
 
-       t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) |
-                                (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
-               (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
        t->new_child = 1;
        t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
        t->kregs = (struct pt_regs *) (child_trap_frame +
                                       sizeof(struct sparc_stackf));
        t->fpsaved[0] = 0;
 
-       if (kernel_thread) {
-               struct sparc_stackf *child_sf = (struct sparc_stackf *)
-                       (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ));
-
-               /* Zero terminate the stack backtrace.  */
-               child_sf->fp = NULL;
-               t->kregs->u_regs[UREG_FP] =
-                 ((unsigned long) child_sf) - STACK_BIAS;
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(child_trap_frame, 0, child_stack_sz);
+               __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
+                       (current_pt_regs()->tstate + 1) & TSTATE_CWP;
+               t->current_ds = ASI_P;
+               t->kregs->u_regs[UREG_G1] = sp; /* function */
+               t->kregs->u_regs[UREG_G2] = arg;
+               return 0;
+       }
 
-               t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);
-               t->kregs->u_regs[UREG_G6] = (unsigned long) t;
-               t->kregs->u_regs[UREG_G4] = (unsigned long) t->task;
-       } else {
-               if (t->flags & _TIF_32BIT) {
-                       sp &= 0x00000000ffffffffUL;
-                       regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
-               }
-               t->kregs->u_regs[UREG_FP] = sp;
-               t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
-               if (sp != regs->u_regs[UREG_FP]) {
-                       unsigned long csp;
-
-                       csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
-                       if (!csp)
-                               return -EFAULT;
-                       t->kregs->u_regs[UREG_FP] = csp;
-               }
-               if (t->utraps)
-                       t->utraps[0]++;
+       parent_sf = ((struct sparc_stackf *) regs) - 1;
+       memcpy(child_trap_frame, parent_sf, child_stack_sz);
+       if (t->flags & _TIF_32BIT) {
+               sp &= 0x00000000ffffffffUL;
+               regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
        }
+       t->kregs->u_regs[UREG_FP] = sp;
+       __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 
+               (regs->tstate + 1) & TSTATE_CWP;
+       t->current_ds = ASI_AIUS;
+       if (sp != regs->u_regs[UREG_FP]) {
+               unsigned long csp;
+
+               csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
+               if (!csp)
+                       return -EFAULT;
+               t->kregs->u_regs[UREG_FP] = csp;
+       }
+       if (t->utraps)
+               t->utraps[0]++;
 
        /* Set the return value for the child. */
        t->kregs->u_regs[UREG_I0] = current->pid;
@@ -694,45 +685,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        return 0;
 }
 
-/*
- * 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 freed until both the parent and the child have exited.
- */
-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       long retval;
-
-       /* If the parent runs before fn(arg) is called by the child,
-        * the input registers of this function can be clobbered.
-        * So we stash 'fn' and 'arg' into global registers which
-        * will not be modified by the parent.
-        */
-       __asm__ __volatile__("mov %4, %%g2\n\t"    /* Save FN into global */
-                            "mov %5, %%g3\n\t"    /* Save ARG into global */
-                            "mov %1, %%g1\n\t"    /* Clone syscall nr. */
-                            "mov %2, %%o0\n\t"    /* Clone flags. */
-                            "mov 0, %%o1\n\t"     /* usp arg == 0 */
-                            "t 0x6d\n\t"          /* Linux/Sparc clone(). */
-                            "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
-                            " mov %%o0, %0\n\t"
-                            "jmpl %%g2, %%o7\n\t"   /* Call the function. */
-                            " mov %%g3, %%o0\n\t"   /* Set arg in delay. */
-                            "mov %3, %%g1\n\t"
-                            "t 0x6d\n\t"          /* Linux/Sparc exit(). */
-                            /* Notreached by child. */
-                            "1:" :
-                            "=r" (retval) :
-                            "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
-                            "i" (__NR_exit),  "r" (fn), "r" (arg) :
-                            "g1", "g2", "g3", "o0", "o1", "memory", "cc");
-       return retval;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 typedef struct {
        union {
                unsigned int    pr_regs[32];
@@ -799,41 +751,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * sparc_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage int sparc_execve(struct pt_regs *regs)
-{
-       int error, base = 0;
-       struct filename *filename;
-
-       /* User register window flush is done by entry.S */
-
-       /* Check for indirect call. */
-       if (regs->u_regs[UREG_G1] == 0)
-               base = 1;
-
-       filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name,
-                         (const char __user *const __user *)
-                         regs->u_regs[base + UREG_I1],
-                         (const char __user *const __user *)
-                         regs->u_regs[base + UREG_I2], regs);
-       putname(filename);
-       if (!error) {
-               fprs_write(0);
-               current_thread_info()->xfsr[0] = 0;
-               current_thread_info()->fpsaved[0] = 0;
-               regs->tstate &= ~TSTATE_PEF;
-       }
-out:
-       return error;
-}
-
 unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc, fp, bias = 0;
index c3239811a1b5775903c77e64057e78d01130fdd0..03c7e929ec34d41eedd7fad7378795c806be5081 100644 (file)
@@ -396,42 +396,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
         return ret;
 }
 
-/*
- * sparc32_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage long sparc32_execve(struct pt_regs *regs)
-{
-       int error, base = 0;
-       struct filename *filename;
-
-       /* User register window flush is done by entry.S */
-
-       /* Check for indirect call. */
-       if ((u32)regs->u_regs[UREG_G1] == 0)
-               base = 1;
-
-       filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-
-       error = compat_do_execve(filename->name,
-                                compat_ptr(regs->u_regs[base + UREG_I1]),
-                                compat_ptr(regs->u_regs[base + UREG_I2]), regs);
-
-       putname(filename);
-
-       if (!error) {
-               fprs_write(0);
-               current_thread_info()->xfsr[0] = 0;
-               current_thread_info()->fpsaved[0] = 0;
-               regs->tstate &= ~TSTATE_PEF;
-       }
-out:
-       return error;
-}
-
 #ifdef CONFIG_MODULES
 
 asmlinkage long sys32_init_module(void __user *umod, u32 len,
index 0c9b31b22e07e3e68b1f43f3928f0483dd9a7960..a8e6eb0a11d503b2c611e69243f8edb9981dfae8 100644 (file)
@@ -258,27 +258,3 @@ out:
        up_read(&uts_sem);
        return err;
 }
-
-/*
- * 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[])
-{
-       long __res;
-       register long __g1 __asm__ ("g1") = __NR_execve;
-       register long __o0 __asm__ ("o0") = (long)(filename);
-       register long __o1 __asm__ ("o1") = (long)(argv);
-       register long __o2 __asm__ ("o2") = (long)(envp);
-       asm volatile ("t 0x10\n\t"
-                     "bcc 1f\n\t"
-                     "mov %%o0, %0\n\t"
-                     "sub %%g0, %%o0, %0\n\t"
-                     "1:\n\t"
-                     : "=r" (__res), "=&r" (__o0)
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
-                     : "cc");
-       return __res;
-}
index 878ef3d5fec522d6b23d0640df962f33c2b958df..51b85feb8b973a0cbfaf8f8e35ae347227f0e12a 100644 (file)
@@ -730,28 +730,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
        return ret;
 }
 
-/*
- * 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[])
-{
-       long __res;
-       register long __g1 __asm__ ("g1") = __NR_execve;
-       register long __o0 __asm__ ("o0") = (long)(filename);
-       register long __o1 __asm__ ("o1") = (long)(argv);
-       register long __o2 __asm__ ("o2") = (long)(envp);
-       asm volatile ("t 0x6d\n\t"
-                     "sub %%g0, %%o0, %0\n\t"
-                     "movcc %%xcc, %%o0, %0\n\t"
-                     : "=r" (__res), "=&r" (__o0)
-                     : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
-                     : "cc");
-       return __res;
-}
-
 asmlinkage long sys_kern_features(void)
 {
        return KERN_FEATURE_MIXED_MODE_STACK;
index 7f5f65d0b3fde92235c838bd976916bc863d0315..2ef41e67f0bef3e4ffce7e5bd7d4f6426ebeb765 100644 (file)
@@ -1,23 +1,19 @@
        /* SunOS's execv() call only specifies the argv argument, the
         * environment settings are the same as the calling processes.
         */
-sys_execve:
-       sethi   %hi(sparc_execve), %g1
-       ba,pt   %xcc, execve_merge
-        or     %g1, %lo(sparc_execve), %g1
+sys64_execve:
+       set     sys_execve, %g1
+       jmpl    %g1, %g0
+        flushw
 
 #ifdef CONFIG_COMPAT
 sunos_execv:
-       stx     %g0, [%sp + PTREGS_OFF + PT_V9_I2]
+       mov     %g0, %o2
 sys32_execve:
-       sethi   %hi(sparc32_execve), %g1
-       or      %g1, %lo(sparc32_execve), %g1
-#endif
-
-execve_merge:
-       flushw
+       set     compat_sys_execve, %g1
        jmpl    %g1, %g0
-        add    %sp, PTREGS_OFF, %o0
+        flushw
+#endif
 
        .align  32
 sys_sparc_pipe:
@@ -112,11 +108,16 @@ sys_clone:
 ret_from_syscall:
        /* Clear current_thread_info()->new_child. */
        stb     %g0, [%g6 + TI_NEW_CHILD]
-       ldx     [%g6 + TI_FLAGS], %l0
        call    schedule_tail
         mov    %g7, %o0
+       ldx     [%sp + PTREGS_OFF + PT_V9_I0], %o0
+       brnz,pt %o0, ret_sys_call
+        ldx    [%g6 + TI_FLAGS], %l0
+       ldx     [%sp + PTREGS_OFF + PT_V9_G1], %l1
+       call    %l1
+        ldx    [%sp + PTREGS_OFF + PT_V9_G2], %o0
        ba,pt   %xcc, ret_sys_call
-        ldx    [%sp + PTREGS_OFF + PT_V9_I0], %o0
+        mov    0, %o0
 
        .globl  sparc_exit
        .type   sparc_exit,#function
@@ -222,7 +223,6 @@ ret_sys_call:
        ldx     [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
 
 2:
-       stb     %g0, [%g6 + TI_SYS_NOERROR]
        /* System call success, clear Carry condition code. */
        andn    %g3, %g2, %g3
 3:
index 1c9af9fa38e9b0b489cb38899685e4c4c76b6584..ebb7f5fc58fb5c952582968230656a9cf9b0128b 100644 (file)
@@ -107,7 +107,7 @@ sys_call_table:
 /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall
        .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
 /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
-       .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
+       .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve
 /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
        .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
 /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
index b66a77968f35ccd188a1c82ee956720248661706..e7ecf1507d901cadecbc45cf881b6c22ebe7d293 100644 (file)
@@ -2688,8 +2688,8 @@ void __init trap_init(void)
                     TI_PRE_COUNT != offsetof(struct thread_info,
                                              preempt_count) ||
                     TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
-                    TI_SYS_NOERROR != offsetof(struct thread_info,
-                                               syscall_noerror) ||
+                    TI_CURRENT_DS != offsetof(struct thread_info,
+                                               current_ds) ||
                     TI_RESTART_BLOCK != offsetof(struct thread_info,
                                                  restart_block) ||
                     TI_KUNA_REGS != offsetof(struct thread_info,
index 9e28a118e6a45250444e69c9062fcb7c78743435..85be1ca539b2e4cc5aea5d6fb8b1587fc7a4e73a 100644 (file)
@@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void)
 void prom_world(int enter)
 {
        if (!enter)
-               set_fs((mm_segment_t) { get_thread_current_ds() });
+               set_fs(get_fs());
 
        __asm__ __volatile__("flushw");
 }
index 875d008828b8ec619c295cf1b2d5c8923ea0389b..ea7f61e8bc9e14cf525d6bde75fb909433959372 100644 (file)
@@ -21,6 +21,8 @@ config TILE
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
index 3063e6fc8daaa0dd3dd982a857889ffec74f451e..ca61fb4296b34d835e1e147d40cbc9c84a385a9d 100644 (file)
@@ -275,18 +275,14 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
 struct compat_sigaction;
 struct compat_siginfo;
 struct compat_sigaltstack;
-long compat_sys_execve(const char __user *path,
-                      compat_uptr_t __user *argv,
-                      compat_uptr_t __user *envp, struct pt_regs *);
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
                             struct compat_sigaction __user *oact,
                             size_t sigsetsize);
 long compat_sys_rt_sigqueueinfo(int pid, int sig,
                                struct compat_siginfo __user *uinfo);
-long compat_sys_rt_sigreturn(struct pt_regs *);
+long compat_sys_rt_sigreturn(void);
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                           struct compat_sigaltstack __user *uoss_ptr,
-                           struct pt_regs *);
+                           struct compat_sigaltstack __user *uoss_ptr);
 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
@@ -303,12 +299,7 @@ long compat_sys_fallocate(int fd, int mode,
 long compat_sys_sched_rr_get_interval(compat_pid_t pid,
                                      struct compat_timespec __user *interval);
 
-/* These are the intvec_64.S trampolines. */
-long _compat_sys_execve(const char __user *path,
-                       const compat_uptr_t __user *argv,
-                       const compat_uptr_t __user *envp);
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                           struct compat_sigaltstack __user *uoss_ptr);
+/* Assembly trampoline to avoid clobbering r0. */
 long _compat_sys_rt_sigreturn(void);
 
 #endif /* _ASM_TILE_COMPAT_H */
index f8ccf08f6934704924f6081476d61d85e28b181f..b73e1039c911d48ad4956e1fad08fb0b546e7edf 100644 (file)
@@ -148,6 +148,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #define compat_start_thread(regs, ip, usp) do { \
                regs->pc = ptr_to_compat_reg((void *)(ip)); \
                regs->sp = ptr_to_compat_reg((void *)(usp)); \
+               single_step_execve();   \
        } while (0)
 
 /*
index 8c4dd9ff91eb91745e8918506375f2d4cb10d588..879073e765864202c02ba84fd5a520bdbca8df48 100644 (file)
@@ -211,6 +211,7 @@ static inline void start_thread(struct pt_regs *regs,
 {
        regs->pc = pc;
        regs->sp = usp;
+       single_step_execve();
 }
 
 /* Free all resources held by a thread. */
@@ -239,6 +240,9 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA)
 #define task_pt_regs(task) \
   ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1)
+#define current_pt_regs()                                   \
+  ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \
+                      (KSTK_PTREGS_GAP - 1)) - 1)
 #define task_sp(task)  (task_pt_regs(task)->sp)
 #define task_pc(task)  (task_pt_regs(task)->pc)
 /* Aliases for pc and sp (used in fs/proc/array.c) */
index 1d48c5fee8b7199cb61fb4feff7bf078689890ae..b8f888cbe6b030c46bf7d54e58353de476565eaa 100644 (file)
@@ -68,7 +68,10 @@ extern unsigned long get_switch_to_pc(void);
 /* Support function for forking a new task. */
 void ret_from_fork(void);
 
-/* Called from ret_from_fork() when a new process starts up. */
+/* Support function for forking a new kernel thread. */
+void ret_from_kernel_thread(void *fn, void *arg);
+
+/* Called from ret_from_xxx() when a new process starts up. */
 struct task_struct *sim_notify_fork(struct task_struct *prev);
 
 #endif /* !__ASSEMBLY__ */
index 06f0464cfed941b3b15903749871b2f02005546a..369696d63e7b833fe6f01758a0d95c1bf8b1fe4f 100644 (file)
@@ -51,8 +51,7 @@ long sys_cacheflush(unsigned long addr, unsigned long len,
 
 #ifndef __tilegx__
 /* mm/fault.c */
-long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
-long _sys_cmpxchg_badaddr(unsigned long address);
+long sys_cmpxchg_badaddr(unsigned long address);
 #endif
 
 #ifdef CONFIG_COMPAT
@@ -63,14 +62,23 @@ long sys_truncate64(const char __user *path, loff_t length);
 long sys_ftruncate64(unsigned int fd, loff_t length);
 #endif
 
+/* Provide versions of standard syscalls that use current_pt_regs(). */
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+               void __user *parent_tid, void __user *child_tid);
+long sys_execve(const char __user *filename,
+                const char __user *const __user *argv,
+                const char __user *const __user *envp);
+long sys_rt_sigreturn(void);
+long sys_sigaltstack(const stack_t __user *, stack_t __user *);
+#define sys_clone sys_clone
+#define sys_execve sys_execve
+#define sys_rt_sigreturn sys_rt_sigreturn
+#define sys_sigaltstack sys_sigaltstack
+
 /* These are the intvec*.S trampolines. */
-long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
 long _sys_rt_sigreturn(void);
 long _sys_clone(unsigned long clone_flags, unsigned long newsp,
                void __user *parent_tid, void __user *child_tid);
-long _sys_execve(const char __user *filename,
-                const char __user *const __user *argv,
-                const char __user *const __user *envp);
 
 #include <asm-generic/syscalls.h>
 
index 6e032a0a268eebeacb8c04b4fb1f17f1da0bbcd3..dab827dc8acb01e6af2e985549315e8a50d3774e 100644 (file)
@@ -16,4 +16,5 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #endif
 #define __ARCH_WANT_SYS_NEWFSTATAT
+#define __ARCH_WANT_SYS_EXECVE
 #include <uapi/asm/unistd.h>
index d67459b9ac2aa43f4c44eb50125c0143509e873f..a2e805569d5d4cbad881b12faa620a2c5578ce23 100644 (file)
@@ -102,10 +102,9 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid,
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
 
-/* Call the trampolines to manage pt_regs where necessary. */
-#define compat_sys_execve _compat_sys_execve
-#define compat_sys_sigaltstack _compat_sys_sigaltstack
+/* Call the assembly trampolines where necessary. */
 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
+#undef sys_clone
 #define sys_clone _sys_clone
 
 /*
index 08b4fe1717bb975aa6edff118fa79f641e77b237..2e4cc69224a6ff83ed5bc0dbe8e4544891b8d99f 100644 (file)
@@ -197,8 +197,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 }
 
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                           struct compat_sigaltstack __user *uoss_ptr,
-                           struct pt_regs *regs)
+                           struct compat_sigaltstack __user *uoss_ptr)
 {
        stack_t uss, uoss;
        int ret;
@@ -219,7 +218,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        set_fs(KERNEL_DS);
        ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
                             (stack_t __user __force *)&uoss,
-                            (unsigned long)compat_ptr(regs->sp));
+                            (unsigned long)compat_ptr(current_pt_regs()->sp));
        set_fs(seg);
        if (ret >= 0 && uoss_ptr)  {
                if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
@@ -232,8 +231,9 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 }
 
 /* The assembly shim for this function arranges to ignore the return value. */
-long compat_sys_rt_sigreturn(struct pt_regs *regs)
+long compat_sys_rt_sigreturn(void)
 {
+       struct pt_regs *regs = current_pt_regs();
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
        sigset_t set;
@@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
-       if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
+       if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT)
                goto badframe;
 
        return 0;
index c31637baff283698f776daf5a83c480dd00b26d6..f116cb0bce20b9cfa395f8876c6ddfa4f858e98b 100644 (file)
@@ -27,17 +27,6 @@ STD_ENTRY(current_text_addr)
        { move r0, lr; jrp lr }
        STD_ENDPROC(current_text_addr)
 
-/*
- * Implement execve().  The i386 code has a note that forking from kernel
- * space results in no copy on write until the execve, so we should be
- * careful not to write to the stack here.
- */
-STD_ENTRY(kernel_execve)
-       moveli TREG_SYSCALL_NR_NAME, __NR_execve
-       swint1
-       jrp lr
-       STD_ENDPROC(kernel_execve)
-
 /*
  * We don't run this function directly, but instead copy it to a page
  * we map into every user process.  See vdso_setup().
index 6943515100f8518cbe3b6f37c4eae8440c6a4e6d..f212bf7cea86693c0649d56d1b9b46cc3ea0417c 100644 (file)
@@ -1291,6 +1291,21 @@ STD_ENTRY(ret_from_fork)
        }
        STD_ENDPROC(ret_from_fork)
 
+STD_ENTRY(ret_from_kernel_thread)
+       jal     sim_notify_fork
+       jal     schedule_tail
+       FEEDBACK_REENTER(ret_from_fork)
+       {
+        move   r0, r31
+        jalr   r30
+       }
+       FEEDBACK_REENTER(ret_from_kernel_thread)
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
+       STD_ENDPROC(ret_from_kernel_thread)
+
        /*
         * Code for ill interrupt.
         */
@@ -1437,15 +1452,6 @@ STD_ENTRY_LOCAL(bad_intr)
        panic   "Unhandled interrupt %#x: PC %#lx"
        STD_ENDPROC(bad_intr)
 
-/* Put address of pt_regs in reg and jump. */
-#define PTREGS_SYSCALL(x, reg)                          \
-       STD_ENTRY(_##x);                                \
-       {                                               \
-        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-        j      x                                       \
-       };                                              \
-       STD_ENDPROC(_##x)
-
 /*
  * Special-case sigreturn to not write r0 to the stack on return.
  * This is technically more efficient, but it also avoids difficulties
@@ -1461,12 +1467,9 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
-PTREGS_SYSCALL(sys_execve, r3)
-PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
-PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+/* Save additional callee-saves to pt_regs and jump to standard function. */
 STD_ENTRY(_sys_clone)
        push_extra_callee_saves r4
        j       sys_clone
index 7c06d597ffd0263875d0d67565f487df608575de..54bc9a6678e8d6b03c319d56b7b5b234f502fb6e 100644 (file)
@@ -1150,6 +1150,21 @@ STD_ENTRY(ret_from_fork)
        }
        STD_ENDPROC(ret_from_fork)
 
+STD_ENTRY(ret_from_kernel_thread)
+       jal     sim_notify_fork
+       jal     schedule_tail
+       FEEDBACK_REENTER(ret_from_fork)
+       {
+        move   r0, r31
+        jalr   r30
+       }
+       FEEDBACK_REENTER(ret_from_kernel_thread)
+       {
+        movei  r30, 0               /* not an NMI */
+        j      .Lresume_userspace   /* jump into middle of interrupt_return */
+       }
+       STD_ENDPROC(ret_from_kernel_thread)
+
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
@@ -1166,15 +1181,6 @@ STD_ENTRY_LOCAL(bad_intr)
        panic   "Unhandled interrupt %#x: PC %#lx"
        STD_ENDPROC(bad_intr)
 
-/* Put address of pt_regs in reg and jump. */
-#define PTREGS_SYSCALL(x, reg)                          \
-       STD_ENTRY(_##x);                                \
-       {                                               \
-        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-        j      x                                       \
-       };                                              \
-       STD_ENDPROC(_##x)
-
 /*
  * Special-case sigreturn to not write r0 to the stack on return.
  * This is technically more efficient, but it also avoids difficulties
@@ -1190,16 +1196,12 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
-PTREGS_SYSCALL(sys_execve, r3)
-PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 #ifdef CONFIG_COMPAT
-PTREGS_SYSCALL(compat_sys_execve, r3)
-PTREGS_SYSCALL(compat_sys_sigaltstack, r2)
 PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0)
 #endif
 
-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+/* Save additional callee-saves to pt_regs and jump to standard function. */
 STD_ENTRY(_sys_clone)
        push_extra_callee_saves r4
        j       sys_clone
index 307d010696c994d1db638accea596c01ba46ebbf..1c20029d2f5a896664d0e5618e80aa7375f0ee64 100644 (file)
@@ -157,24 +157,44 @@ void arch_release_thread_info(struct thread_info *info)
 static void save_arch_state(struct thread_struct *t);
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long stack_size,
-               struct task_struct *p, struct pt_regs *regs)
+               unsigned long arg,
+               struct task_struct *p, struct pt_regs *unused)
 {
-       struct pt_regs *childregs;
+       struct pt_regs *childregs = task_pt_regs(p);
        unsigned long ksp;
+       unsigned long *callee_regs;
 
        /*
-        * When creating a new kernel thread we pass sp as zero.
-        * Assign it to a reasonable value now that we have the stack.
+        * Set up the stack and stack pointer appropriately for the
+        * new child to find itself woken up in __switch_to().
+        * The callee-saved registers must be on the stack to be read;
+        * the new task will then jump to assembly support to handle
+        * calling schedule_tail(), etc., and (for userspace tasks)
+        * returning to the context set up in the pt_regs.
         */
-       if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0))
-               sp = KSTK_TOP(p);
+       ksp = (unsigned long) childregs;
+       ksp -= C_ABI_SAVE_AREA_SIZE;   /* interrupt-entry save area */
+       ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
+       ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
+       callee_regs = (unsigned long *)ksp;
+       ksp -= C_ABI_SAVE_AREA_SIZE;   /* __switch_to() save area */
+       ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
+       p->thread.ksp = ksp;
 
-       /*
-        * Do not clone step state from the parent; each thread
-        * must make its own lazily.
-        */
-       task_thread_info(p)->step_state = NULL;
+       /* Record the pid of the task that created this one. */
+       p->thread.creator_pid = current->pid;
+
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               /* kernel thread */
+               memset(childregs, 0, sizeof(struct pt_regs));
+               memset(&callee_regs[2], 0,
+                      (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long));
+               callee_regs[0] = sp;   /* r30 = function */
+               callee_regs[1] = arg;  /* r31 = arg */
+               childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0);
+               p->thread.pc = (unsigned long) ret_from_kernel_thread;
+               return 0;
+       }
 
        /*
         * Start new thread in ret_from_fork so it schedules properly
@@ -182,46 +202,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
         */
        p->thread.pc = (unsigned long) ret_from_fork;
 
-       /* Save user stack top pointer so we can ID the stack vm area later. */
-       p->thread.usp0 = sp;
-
-       /* Record the pid of the process that created this one. */
-       p->thread.creator_pid = current->pid;
+       /*
+        * Do not clone step state from the parent; each thread
+        * must make its own lazily.
+        */
+       task_thread_info(p)->step_state = NULL;
 
        /*
         * Copy the registers onto the kernel stack so the
         * return-from-interrupt code will reload it into registers.
         */
-       childregs = task_pt_regs(p);
-       *childregs = *regs;
+       *childregs = *current_pt_regs();
        childregs->regs[0] = 0;         /* return value is zero */
-       childregs->sp = sp;  /* override with new user stack pointer */
+       if (sp)
+               childregs->sp = sp;  /* override with new user stack pointer */
+       memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG],
+              CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
+
+       /* Save user stack top pointer so we can ID the stack vm area later. */
+       p->thread.usp0 = childregs->sp;
 
        /*
         * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
         * which is passed in as arg #5 to sys_clone().
         */
        if (clone_flags & CLONE_SETTLS)
-               childregs->tp = regs->regs[4];
+               childregs->tp = childregs->regs[4];
 
-       /*
-        * Copy the callee-saved registers from the passed pt_regs struct
-        * into the context-switch callee-saved registers area.
-        * This way when we start the interrupt-return sequence, the
-        * callee-save registers will be correctly in registers, which
-        * is how we assume the compiler leaves them as we start doing
-        * the normal return-from-interrupt path after calling C code.
-        * Zero out the C ABI save area to mark the top of the stack.
-        */
-       ksp = (unsigned long) childregs;
-       ksp -= C_ABI_SAVE_AREA_SIZE;   /* interrupt-entry save area */
-       ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
-       ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
-       memcpy((void *)ksp, &regs->regs[CALLEE_SAVED_FIRST_REG],
-              CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
-       ksp -= C_ABI_SAVE_AREA_SIZE;   /* __switch_to() save area */
-       ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
-       p->thread.ksp = ksp;
 
 #if CHIP_HAS_TILE_DMA()
        /*
@@ -578,61 +585,13 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
 }
 
 /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
-SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
-               void __user *, parent_tidptr, void __user *, child_tidptr,
-               struct pt_regs *, regs)
+SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp,
+               void __user *, parent_tidptr, void __user *, child_tidptr)
 {
-       if (!newsp)
-               newsp = regs->sp;
-       return do_fork(clone_flags, newsp, regs, 0,
+       return do_fork(clone_flags, newsp, current_pt_regs(), 0,
                       parent_tidptr, child_tidptr);
 }
 
-/*
- * sys_execve() executes a new program.
- */
-SYSCALL_DEFINE4(execve, const char __user *, path,
-               const char __user *const __user *, argv,
-               const char __user *const __user *, envp,
-               struct pt_regs *, regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(path);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-       if (error == 0)
-               single_step_execve();
-out:
-       return error;
-}
-
-#ifdef CONFIG_COMPAT
-long compat_sys_execve(const char __user *path,
-                      compat_uptr_t __user *argv,
-                      compat_uptr_t __user *envp,
-                      struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(path);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = compat_do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-       if (error == 0)
-               single_step_execve();
-out:
-       return error;
-}
-#endif
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct KBacktraceIterator kbt;
@@ -650,37 +609,6 @@ unsigned long get_wchan(struct task_struct *p)
        return 0;
 }
 
-/*
- * We pass in lr as zero (cleared in kernel_thread) and the caller
- * part of the backtrace ABI on the stack also zeroed (in copy_thread)
- * so that backtraces will stop with this function.
- * Note that we don't use r0, since copy_thread() clears it.
- */
-static void start_kernel_thread(int dummy, int (*fn)(int), int arg)
-{
-       do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-       regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0);  /* run at kernel PL, no ICS */
-       regs.pc = (long) start_kernel_thread;
-       regs.flags = PT_FLAGS_CALLER_SAVES;   /* need to restore r1 and r2 */
-       regs.regs[1] = (long) fn;             /* function pointer */
-       regs.regs[2] = (long) arg;            /* parameter register */
-
-       /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs,
-                      0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /* Flush thread state. */
 void flush_thread(void)
 {
index 67efb656d10451946baa827066811948dc45b2d6..657a7ace4ab4638e6b32701e0f59a2a3a0650556 100644 (file)
 
 #define DEBUG_SIG 0
 
-SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
-               stack_t __user *, uoss, struct pt_regs *, regs)
+SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss,
+               stack_t __user *, uoss)
 {
-       return do_sigaltstack(uss, uoss, regs->sp);
+       return do_sigaltstack(uss, uoss, current_pt_regs()->sp);
 }
 
 
@@ -83,8 +83,9 @@ void signal_fault(const char *type, struct pt_regs *regs,
 }
 
 /* The assembly shim for this function arranges to ignore the return value. */
-SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
+SYSCALL_DEFINE0(rt_sigreturn)
 {
+       struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
        sigset_t set;
index b08095b402d6c3d5f0a1f651b8c5578ed39c15fa..02ff5c0ef775091f43589361faa00d7760abe675 100644 (file)
@@ -106,14 +106,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 #define sys_readahead sys32_readahead
 #endif
 
-/* Call the trampolines to manage pt_regs where necessary. */
-#define sys_execve _sys_execve
-#define sys_sigaltstack _sys_sigaltstack
+/* Call the assembly trampolines where necessary. */
+#undef sys_rt_sigreturn
 #define sys_rt_sigreturn _sys_rt_sigreturn
+#undef sys_clone
 #define sys_clone _sys_clone
-#ifndef __tilegx__
-#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
-#endif
 
 /*
  * Note that we can't include <linux/unistd.h> here since the header
index fe811fa5f1b96f682633e2c54f6be6bbdd525095..3d2b81c163a6aac89e0e32d862bd603021eec917 100644 (file)
@@ -70,9 +70,10 @@ static noinline void force_sig_info_fault(const char *type, int si_signo,
  * Synthesize the fault a PL0 process would get by doing a word-load of
  * an unaligned address or a high kernel address.
  */
-SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
-               struct pt_regs *, regs)
+SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address)
 {
+       struct pt_regs *regs = current_pt_regs();
+
        if (address >= PAGE_OFFSET)
                force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR,
                                     address, INT_DTLB_MISS, current, regs);
index d0ced1011f2fa28cf96087880d6cddda011de13f..d2db71077d932a371652e884617006f68d0fa2c1 100644 (file)
@@ -286,10 +286,8 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd,
 
 int compat_do_execve(const char *filename, const compat_uptr_t __user *argv,
                     const compat_uptr_t __user *envp, struct pt_regs *regs);
-#ifdef __ARCH_WANT_SYS_EXECVE
 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv,
                     const compat_uptr_t __user *envp);
-#endif
 
 asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
                compat_ulong_t __user *outp, compat_ulong_t __user *exp,