From: Al Viro Date: Mon, 15 Oct 2012 06:23:22 +0000 (-0400) Subject: avr32: switch to generic kernel_thread()/kernel_execve() X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=5adc807f707535a5ce97b5d69472ee74d6d099ac;p=linux-beck.git avr32: switch to generic kernel_thread()/kernel_execve() Signed-off-by: Al Viro --- diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 06e73bf665e9..649aeb9acecb 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -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 diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 87d8baccc60e..48d71c5c898a 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h @@ -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) diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 9e2c465ef3a6..119a2e41defe 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile @@ -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 diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index df2884181313..9899d3cc6f03 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -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 diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 1bb0a8abd79b..07380c3a4f78 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -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(®s, 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, ®s, 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 index 62635a09ae3e..000000000000 --- a/arch/avr32/kernel/sys_avr32.c +++ /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 - -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; -}