parisc: switch to generic kernel_thread()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 4 Oct 2012 03:28:08 +0000 (23:28 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 14 Oct 2012 23:36:30 +0000 (19:36 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/parisc/Kconfig
arch/parisc/kernel/entry.S
arch/parisc/kernel/process.c

index 11def45b98c5ee04f356890a8396b8d970624524..c779da7cd96ba7ebcf6d86bca90f38827c68ab83 100644 (file)
@@ -22,6 +22,7 @@ config PARISC
        select GENERIC_STRNCPY_FROM_USER
        select HAVE_MOD_ARCH_SPECIFIC
        select MODULES_USE_ELF_RELA
+       select GENERIC_KERNEL_THREAD
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index 18670a078849b96d92d4dd4ff406a79c2caa28a4..18d05e7373b5da652ac361252b8810a5063fe569 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)
@@ -773,7 +723,6 @@ ENTRY(ret_from_kernel_thread)
        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)
index cbc37216bf90f2fa5c64b5b1956272b9db237b8f..b7b4126774e03fa0689d2cd0028667c57796424a 100644 (file)
@@ -164,23 +164,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 +239,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);
@@ -271,21 +254,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        extern void * const hpux_child_return;
 #endif
 
-       *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) {
+       if (unlikely((p->flags & PF_KTHREAD) && usp != 0)) {
+               memset(cregs, 0, sizeof(struct pt_regs));
                /* kernel thread */
                cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
                /* Must exit via ret_from_kernel_thread in order
@@ -297,10 +267,12 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                 * 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 */
                /*
@@ -308,6 +280,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                 * for setting gr[21].
                 */
 
+               *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 */
+
                /* Use same stack depth as parent */
                cregs->ksp = (unsigned long)stack
                        + (pregs->gr[21] & (THREAD_SIZE - 1));