diff options
Diffstat (limited to 'arch/avr32/kernel/process.c')
| -rw-r--r-- | arch/avr32/kernel/process.c | 115 | 
1 files changed, 20 insertions, 95 deletions
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 1bb0a8abd79b..fd78f58ea79a 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -69,44 +69,6 @@ void machine_restart(char *cmd)  }  /* - * 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   */  void exit_thread(void) @@ -332,26 +294,32 @@ 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, -		struct task_struct *p, struct pt_regs *regs) +		unsigned long arg, +		struct task_struct *p)  { -	struct pt_regs *childregs; - -	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; -	*childregs = *regs; - -	if (user_mode(regs)) -		childregs->sp = usp; -	else -		childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - -	childregs->r12 = 0; /* Set return value for child */ +	struct pt_regs *childregs = task_pt_regs(p); + +	if (unlikely(p->flags & PF_KTHREAD)) { +		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 = *current_pt_regs(); +		if (usp) +			childregs->sp = usp; +		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)) @@ -360,49 +328,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  	return 0;  } -/* r12-r8 are dummy parameters to force the compiler to use the stack */ -asmlinkage int sys_fork(struct pt_regs *regs) -{ -	return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, -		void __user *parent_tidptr, void __user *child_tidptr, -		struct pt_regs *regs) -{ -	if (!newsp) -		newsp = regs->sp; -	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, -			child_tidptr); -} - -asmlinkage int sys_vfork(struct pt_regs *regs) -{ -	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, 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()?"  |