avr32: switch to generic kernel_thread()/kernel_execve()
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 15 Oct 2012 06:23:22 +0000 (02:23 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 15 Oct 2012 15:14:38 +0000 (11:14 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/avr32/Kconfig
arch/avr32/include/asm/processor.h
arch/avr32/kernel/Makefile
arch/avr32/kernel/entry-avr32b.S
arch/avr32/kernel/process.c
arch/avr32/kernel/sys_avr32.c [deleted file]

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 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..07380c3a4f7821ff69b2b27d912146d0949178e2 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))
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;
-}