alpha: switch to generic kernel_thread()
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 10 Sep 2012 02:03:42 +0000 (22:03 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 1 Oct 2012 02:53:18 +0000 (22:53 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/alpha/Kconfig
arch/alpha/include/asm/processor.h
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/process.c

index 9944dedee5b1b1b31abf08599a44421333bd9290..7da91246e2793c6d8ecf5556ca65530c6c7275c0 100644 (file)
@@ -20,6 +20,7 @@ config ALPHA
        select GENERIC_CMOS_UPDATE
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
+       select GENERIC_KERNEL_THREAD
        help
          The Alpha is a 64-bit general-purpose processor designed and
          marketed by the Digital Equipment Corporation of blessed memory,
index e37b887b3d9f636fdcb0b4615a8c648dfc3d364f..6cb7fe85c4b567adad3516a74c5b862a32a50a5e 100644 (file)
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Create a kernel thread without removing it from tasklists.  */
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
index 15fa821d09cd38ff58ea5390439617ee2ff4a2eb..89566b346c0f802bd5bfe0c817bd2fee9bd39d3e 100644 (file)
@@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s);
 EXPORT_SYMBOL(alpha_write_fp_reg);
 EXPORT_SYMBOL(alpha_write_fp_reg_s);
 
-/* entry.S */
-EXPORT_SYMBOL(kernel_thread);
-
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_tcpudp_magic);
 EXPORT_SYMBOL(ip_compute_csum);
index 61ff145cab6ec849ded0335e33500cd22bc8d5ae..421dccf273eb5c323607c4204064608795274b11 100644 (file)
@@ -609,59 +609,22 @@ ret_from_fork:
 .end ret_from_fork
 
 /*
- * kernel_thread(fn, arg, clone_flags)
+ * ... and new kernel threads - here
  */
        .align 4
-       .globl  kernel_thread
-       .ent    kernel_thread
-kernel_thread:
-       /* We can be called from a module.  */
-       ldgp    $gp, 0($27)
-       .prologue 1
-       subq    $sp, SP_OFF+6*8, $sp
-       br      $1, 2f          /* load start address */
-
-       /* We've now "returned" from a fake system call.  */
-       unop
-       blt     $0, 1f          /* error?  */
-       ldi     $1, 0x3fff
-       beq     $20, 1f         /* parent or child?  */
-
-       bic     $sp, $1, $8     /* in child.  */
-       jsr     $26, ($27)
+       .globl  ret_from_kernel_thread
+       .ent    ret_from_kernel_thread
+ret_from_kernel_thread:
+       mov     $17, $16
+       jsr     $26, schedule_tail
+       mov     $9, $27
+       mov     $10, $16
+       jsr     $26, ($9)
        ldgp    $gp, 0($26)
        mov     $0, $16
        mov     $31, $26
        jmp     $31, sys_exit
-
-1:     ret                     /* in parent.  */
-
-       .align 4
-2:     /* Fake a system call stack frame, as we can't do system calls
-          from kernel space.  Note that we store FN and ARG as they
-          need to be set up in the child for the call.  Also store $8
-          and $26 for use in the parent.  */
-       stq     $31, SP_OFF($sp)        /* ps */
-       stq     $1, SP_OFF+8($sp)       /* pc */
-       stq     $gp, SP_OFF+16($sp)     /* gp */
-       stq     $16, 136($sp)           /* $27; FN for child */
-       stq     $17, SP_OFF+24($sp)     /* $16; ARG for child */
-       stq     $8, 64($sp)             /* $8 */
-       stq     $26, 128($sp)           /* $26 */
-       /* Avoid the HAE being gratuitously wrong, to avoid restoring it.  */
-       ldq     $2, alpha_mv+HAE_CACHE
-       stq     $2, 152($sp)            /* HAE */
-
-       /* Shuffle FLAGS to the front; add CLONE_VM.  */
-       ldi     $1, CLONE_VM|CLONE_UNTRACED
-       or      $18, $1, $16
-       bsr     $26, sys_clone
-
-       /* We don't actually care for a3 success widgetry in the kernel.
-          Not for positive errno values.  */
-       stq     $0, 0($sp)              /* $0 */
-       br      ret_to_kernel
-.end kernel_thread
+.end ret_from_kernel_thread
 
 \f
 /*
index 145473909199d71106916eff579648d500312d0e..6b33ecdbc534b4f3324b430344bfab2ad003de37 100644 (file)
@@ -259,33 +259,35 @@ alpha_vfork(struct pt_regs *regs)
 
 /*
  * Copy an alpha thread..
- *
- * Note the "stack_offset" stuff: when returning to kernel mode, we need
- * to have some extra stack-space for the kernel stack that still exists
- * after the "ret_from_fork".  When returning to user mode, we only want
- * the space needed by the syscall stack frame (ie "struct pt_regs").
- * Use the passed "regs" pointer to determine how much space we need
- * for a kernel fork().
  */
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long unused,
+           unsigned long arg,
            struct task_struct * p, struct pt_regs * regs)
 {
        extern void ret_from_fork(void);
+       extern void ret_from_kernel_thread(void);
 
        struct thread_info *childti = task_thread_info(p);
-       struct pt_regs * childregs;
-       struct switch_stack * childstack, *stack;
-       unsigned long stack_offset, settls;
-
-       stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
-       if (!(regs->ps & 8))
-               stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
-       childregs = (struct pt_regs *)
-         (stack_offset + PAGE_SIZE + task_stack_page(p));
-               
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct switch_stack *childstack, *stack;
+       unsigned long settls;
+
+       childstack = ((struct switch_stack *) childregs) - 1;
+       if (unlikely(!regs)) {
+               /* kernel thread */
+               memset(childstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               childstack->r26 = (unsigned long) ret_from_kernel_thread;
+               childstack->r9 = usp;   /* function */
+               childstack->r10 = arg;
+               childregs->hae = alpha_mv.hae_cache,
+               childti->pcb.usp = 0;
+               childti->pcb.ksp = (unsigned long) childstack;
+               childti->pcb.flags = 1; /* set FEN, clear everything else */
+               return 0;
+       }
        *childregs = *regs;
        settls = regs->r20;
        childregs->r0 = 0;
@@ -293,7 +295,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
        regs->r20 = 0;
        stack = ((struct switch_stack *) regs) - 1;
-       childstack = ((struct switch_stack *) childregs) - 1;
        *childstack = *stack;
        childstack->r26 = (unsigned long) ret_from_fork;
        childti->pcb.usp = usp;