diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 12:22:13 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 12:22:13 -0800 | 
| commit | 9977d9b379cb77e0f67bd6f4563618106e58e11d (patch) | |
| tree | 0191accfddf578edb52c69c933d64521e3dce297 /arch/sparc/kernel | |
| parent | cf4af01221579a4e895f43dbfc47598fbfc5a731 (diff) | |
| parent | 541880d9a2c7871f6370071d55aa6662d329c51e (diff) | |
| download | olio-linux-3.10-9977d9b379cb77e0f67bd6f4563618106e58e11d.tar.xz olio-linux-3.10-9977d9b379cb77e0f67bd6f4563618106e58e11d.zip  | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull big execve/kernel_thread/fork unification series from Al Viro:
 "All architectures are converted to new model.  Quite a bit of that
  stuff is actually shared with architecture trees; in such cases it's
  literally shared branch pulled by both, not a cherry-pick.
  A lot of ugliness and black magic is gone (-3KLoC total in this one):
   - kernel_thread()/kernel_execve()/sys_execve() redesign.
     We don't do syscalls from kernel anymore for either kernel_thread()
     or kernel_execve():
     kernel_thread() is essentially clone(2) with callback run before we
     return to userland, the callbacks either never return or do
     successful do_execve() before returning.
     kernel_execve() is a wrapper for do_execve() - it doesn't need to
     do transition to user mode anymore.
     As a result kernel_thread() and kernel_execve() are
     arch-independent now - they live in kernel/fork.c and fs/exec.c
     resp.  sys_execve() is also in fs/exec.c and it's completely
     architecture-independent.
   - daemonize() is gone, along with its parts in fs/*.c
   - struct pt_regs * is no longer passed to do_fork/copy_process/
     copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump.
   - sys_fork()/sys_vfork()/sys_clone() unified; some architectures
     still need wrappers (ones with callee-saved registers not saved in
     pt_regs on syscall entry), but the main part of those suckers is in
     kernel/fork.c now."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits)
  do_coredump(): get rid of pt_regs argument
  print_fatal_signal(): get rid of pt_regs argument
  ptrace_signal(): get rid of unused arguments
  get rid of ptrace_signal_deliver() arguments
  new helper: signal_pt_regs()
  unify default ptrace_signal_deliver
  flagday: kill pt_regs argument of do_fork()
  death to idle_regs()
  don't pass regs to copy_process()
  flagday: don't pass regs to copy_thread()
  bfin: switch to generic vfork, get rid of pointless wrappers
  xtensa: switch to generic clone()
  openrisc: switch to use of generic fork and clone
  unicore32: switch to generic clone(2)
  score: switch to generic fork/vfork/clone
  c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone()
  take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h
  mn10300: switch to generic fork/vfork/clone
  h8300: switch to generic fork/vfork/clone
  tile: switch to generic clone()
  ...
Conflicts:
	arch/microblaze/include/asm/Kbuild
Diffstat (limited to 'arch/sparc/kernel')
| -rw-r--r-- | arch/sparc/kernel/entry.S | 51 | ||||
| -rw-r--r-- | arch/sparc/kernel/etrap_64.S | 8 | ||||
| -rw-r--r-- | arch/sparc/kernel/process_32.c | 158 | ||||
| -rw-r--r-- | arch/sparc/kernel/process_64.c | 146 | ||||
| -rw-r--r-- | arch/sparc/kernel/sys_sparc32.c | 36 | ||||
| -rw-r--r-- | arch/sparc/kernel/sys_sparc_32.c | 24 | ||||
| -rw-r--r-- | arch/sparc/kernel/sys_sparc_64.c | 22 | ||||
| -rw-r--r-- | arch/sparc/kernel/syscalls.S | 30 | ||||
| -rw-r--r-- | arch/sparc/kernel/systbls_64.S | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/traps_64.c | 4 | 
10 files changed, 124 insertions, 357 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index dcaa1cf0de4..21fd1a8f47d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -806,23 +806,10 @@ sys_nis_syscall:  	call	c_sys_nis_syscall  	 mov	%l5, %o7 -	.align	4 -	.globl	sys_execve -sys_execve: -	mov	%o7, %l5 -	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg -	call	sparc_execve -	 mov	%l5, %o7 - -	.globl	sunos_execv  sunos_execv: -	st	%g0, [%sp + STACKFRAME_SZ + PT_I2] - -	call	sparc_execve -	 add	%sp, STACKFRAME_SZ, %o0 - -	b	ret_sys_call -	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0 +	.globl	sunos_execv +	b	sys_execve +	 clr	%i2  	.align	4  	.globl	sys_sparc_pipe @@ -959,17 +946,9 @@ flush_patch_four:          .align  4  linux_sparc_ni_syscall:  	sethi   %hi(sys_ni_syscall), %l7 -	b       syscall_is_too_hard +	b       do_syscall  	 or     %l7, %lo(sys_ni_syscall), %l7 -linux_fast_syscall: -	andn	%l7, 3, %l7 -	mov	%i0, %o0 -	mov	%i1, %o1 -	mov 	%i2, %o2 -	jmpl	%l7 + %g0, %g0 -	 mov	%i3, %o3 -  linux_syscall_trace:  	add	%sp, STACKFRAME_SZ, %o0  	call	syscall_trace @@ -991,6 +970,23 @@ ret_from_fork:  	b	ret_sys_call  	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0 +	.globl	ret_from_kernel_thread +ret_from_kernel_thread: +	call	schedule_tail +	 ld	[%g3 + TI_TASK], %o0 +	ld	[%sp + STACKFRAME_SZ + PT_G1], %l0 +	call	%l0 +	 ld	[%sp + STACKFRAME_SZ + PT_G2], %o0 +	rd	%psr, %l1 +	ld	[%sp + STACKFRAME_SZ + PT_PSR], %l0 +	andn	%l0, PSR_CWP, %l0 +	nop +	and	%l1, PSR_CWP, %l1 +	or	%l0, %l1, %l0 +	st	%l0, [%sp + STACKFRAME_SZ + PT_PSR] +	b	ret_sys_call +	 mov	0, %o0 +  	/* Linux native system calls enter here... */  	.align	4  	.globl	linux_sparc_syscall @@ -1002,11 +998,8 @@ linux_sparc_syscall:  	bgeu	linux_sparc_ni_syscall  	 sll	%g1, 2, %l4  	ld	[%l7 + %l4], %l7 -	andcc	%l7, 1, %g0 -	bne	linux_fast_syscall -	 /* Just do first insn from SAVE_ALL in the delay slot */ -syscall_is_too_hard: +do_syscall:  	SAVE_ALL_HEAD  	 rd	%wim, %l3 diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S index 786b185e6e3..1276ca2567b 100644 --- a/arch/sparc/kernel/etrap_64.S +++ b/arch/sparc/kernel/etrap_64.S @@ -92,8 +92,10 @@ etrap_save:	save	%g2, -STACK_BIAS, %sp  		rdpr	%wstate, %g2  		wrpr	%g0, 0, %canrestore  		sll	%g2, 3, %g2 + +		/* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR.  */  		mov	1, %l5 -		stb	%l5, [%l6 + TI_FPDEPTH] +		sth	%l5, [%l6 + TI_SYS_NOERROR]  		wrpr	%g3, 0, %otherwin  		wrpr	%g2, 0, %wstate @@ -152,7 +154,9 @@ etrap_save:	save	%g2, -STACK_BIAS, %sp  		add	%l6, TI_FPSAVED + 1, %l4  		srl	%l5, 1, %l3  		add	%l5, 2, %l5 -		stb	%l5, [%l6 + TI_FPDEPTH] + +		/* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR.  */ +		sth	%l5, [%l6 + TI_SYS_NOERROR]  		ba,pt	%xcc, 2b  		 stb	%g0, [%l4 + %l3]  		nop diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 487bffb36f5..be8e862bada 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -286,8 +286,7 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,  	parent_tid_ptr = regs->u_regs[UREG_I2];  	child_tid_ptr = regs->u_regs[UREG_I4]; -	ret = do_fork(clone_flags, stack_start, -		      regs, stack_size, +	ret = do_fork(clone_flags, stack_start, stack_size,  		      (int __user *) parent_tid_ptr,  		      (int __user *) child_tid_ptr); @@ -316,13 +315,13 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,   * XXX See comment above sys_vfork in sparc64. todo.   */  extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void);  int copy_thread(unsigned long clone_flags, unsigned long sp, -		unsigned long unused, -		struct task_struct *p, struct pt_regs *regs) +		unsigned long arg, struct task_struct *p)  {  	struct thread_info *ti = task_thread_info(p); -	struct pt_regs *childregs; +	struct pt_regs *childregs, *regs = current_pt_regs();  	char *new_stack;  #ifndef CONFIG_SMP @@ -336,16 +335,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	}  	/* -	 *  p->thread_info         new_stack   childregs -	 *  !                      !           !             {if(PSR_PS) } -	 *  V                      V (stk.fr.) V  (pt_regs)  { (stk.fr.) } -	 *  +----- - - - - - ------+===========+============={+==========}+ +	 *  p->thread_info         new_stack   childregs stack bottom +	 *  !                      !           !             ! +	 *  V                      V (stk.fr.) V  (pt_regs)  V +	 *  +----- - - - - - ------+===========+=============+  	 */  	new_stack = task_stack_page(p) + THREAD_SIZE; -	if (regs->psr & PSR_PS) -		new_stack -= STACKFRAME_SZ;  	new_stack -= STACKFRAME_SZ + TRACEREG_SZ; -	memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);  	childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);  	/* @@ -356,55 +352,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	 * Thus, kpsr|=PSR_PIL.  	 */  	ti->ksp = (unsigned long) new_stack; -	ti->kpc = (((unsigned long) ret_from_fork) - 0x8); -	ti->kpsr = current->thread.fork_kpsr | PSR_PIL; -	ti->kwim = current->thread.fork_kwim; +	p->thread.kregs = childregs; -	if(regs->psr & PSR_PS) { -		extern struct pt_regs fake_swapper_regs; - -		p->thread.kregs = &fake_swapper_regs; -		new_stack += STACKFRAME_SZ + TRACEREG_SZ; -		childregs->u_regs[UREG_FP] = (unsigned long) new_stack; +	if (unlikely(p->flags & PF_KTHREAD)) { +		extern int nwindows; +		unsigned long psr; +		memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);  		p->thread.flags |= SPARC_FLAG_KTHREAD;  		p->thread.current_ds = KERNEL_DS; -		memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); -		childregs->u_regs[UREG_G6] = (unsigned long) ti; -	} else { -		p->thread.kregs = childregs; -		childregs->u_regs[UREG_FP] = sp; -		p->thread.flags &= ~SPARC_FLAG_KTHREAD; -		p->thread.current_ds = USER_DS; +		ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8); +		childregs->u_regs[UREG_G1] = sp; /* function */ +		childregs->u_regs[UREG_G2] = arg; +		psr = childregs->psr = get_psr(); +		ti->kpsr = psr | PSR_PIL; +		ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows); +		return 0; +	} +	memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); +	childregs->u_regs[UREG_FP] = sp; +	p->thread.flags &= ~SPARC_FLAG_KTHREAD; +	p->thread.current_ds = USER_DS; +	ti->kpc = (((unsigned long) ret_from_fork) - 0x8); +	ti->kpsr = current->thread.fork_kpsr | PSR_PIL; +	ti->kwim = current->thread.fork_kwim; -		if (sp != regs->u_regs[UREG_FP]) { -			struct sparc_stackf __user *childstack; -			struct sparc_stackf __user *parentstack; +	if (sp != regs->u_regs[UREG_FP]) { +		struct sparc_stackf __user *childstack; +		struct sparc_stackf __user *parentstack; -			/* -			 * This is a clone() call with supplied user stack. -			 * Set some valid stack frames to give to the child. -			 */ -			childstack = (struct sparc_stackf __user *) -				(sp & ~0xfUL); -			parentstack = (struct sparc_stackf __user *) -				regs->u_regs[UREG_FP]; +		/* +		 * This is a clone() call with supplied user stack. +		 * Set some valid stack frames to give to the child. +		 */ +		childstack = (struct sparc_stackf __user *) +			(sp & ~0xfUL); +		parentstack = (struct sparc_stackf __user *) +			regs->u_regs[UREG_FP];  #if 0 -			printk("clone: parent stack:\n"); -			show_stackframe(parentstack); +		printk("clone: parent stack:\n"); +		show_stackframe(parentstack);  #endif -			childstack = clone_stackframe(childstack, parentstack); -			if (!childstack) -				return -EFAULT; +		childstack = clone_stackframe(childstack, parentstack); +		if (!childstack) +			return -EFAULT;  #if 0 -			printk("clone: child stack:\n"); -			show_stackframe(childstack); +		printk("clone: child stack:\n"); +		show_stackframe(childstack);  #endif -			childregs->u_regs[UREG_FP] = (unsigned long)childstack; -		} +		childregs->u_regs[UREG_FP] = (unsigned long)childstack;  	}  #ifdef CONFIG_SMP @@ -475,69 +474,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)  	return 1;  } -/* - * sparc_execve() executes a new program after the asm stub has set - * things up for us.  This should basically do what I want it to. - */ -asmlinkage int sparc_execve(struct pt_regs *regs) -{ -	int error, base = 0; -	struct filename *filename; - -	/* Check for indirect call. */ -	if(regs->u_regs[UREG_G1] == 0) -		base = 1; - -	filename = getname((char __user *)regs->u_regs[base + UREG_I0]); -	error = PTR_ERR(filename); -	if(IS_ERR(filename)) -		goto out; -	error = do_execve(filename->name, -			  (const char __user *const  __user *) -			  regs->u_regs[base + UREG_I1], -			  (const char __user *const  __user *) -			  regs->u_regs[base + UREG_I2], -			  regs); -	putname(filename); -out: -	return error; -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ -	long retval; - -	__asm__ __volatile__("mov %4, %%g2\n\t"    /* Set aside fn ptr... */ -			     "mov %5, %%g3\n\t"    /* and arg. */ -			     "mov %1, %%g1\n\t" -			     "mov %2, %%o0\n\t"    /* Clone flags. */ -			     "mov 0, %%o1\n\t"     /* usp arg == 0 */ -			     "t 0x10\n\t"          /* Linux/Sparc clone(). */ -			     "cmp %%o1, 0\n\t" -			     "be 1f\n\t"           /* The parent, just return. */ -			     " nop\n\t"            /* Delay slot. */ -			     "jmpl %%g2, %%o7\n\t" /* Call the function. */ -			     " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ -			     "mov %3, %%g1\n\t" -			     "t 0x10\n\t"          /* Linux/Sparc exit(). */ -			     /* Notreached by child. */ -			     "1: mov %%o0, %0\n\t" : -			     "=r" (retval) : -			     "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), -			     "i" (__NR_exit),  "r" (fn), "r" (arg) : -			     "g1", "g2", "g3", "o0", "o1", "memory", "cc"); -	return retval; -} -EXPORT_SYMBOL(kernel_thread); -  unsigned long get_wchan(struct task_struct *task)  {  	unsigned long pc, fp, bias = 0; diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index c6e0c291004..cdb80b2adbe 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -601,8 +601,7 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,  		child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];  	} -	ret = do_fork(clone_flags, stack_start, -		      regs, stack_size, +	ret = do_fork(clone_flags, stack_start, stack_size,  		      parent_tid_ptr, child_tid_ptr);  	/* If we get an error and potentially restart the system @@ -622,64 +621,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,   * Child  -->  %o0 == parents pid, %o1 == 1   */  int copy_thread(unsigned long clone_flags, unsigned long sp, -		unsigned long unused, -		struct task_struct *p, struct pt_regs *regs) +		unsigned long arg, struct task_struct *p)  {  	struct thread_info *t = task_thread_info(p); +	struct pt_regs *regs = current_pt_regs();  	struct sparc_stackf *parent_sf;  	unsigned long child_stack_sz;  	char *child_trap_frame; -	int kernel_thread; - -	kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; -	parent_sf = ((struct sparc_stackf *) regs) - 1;  	/* Calculate offset to stack_frame & pt_regs */ -	child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + -			  (kernel_thread ? STACKFRAME_SZ : 0)); +	child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);  	child_trap_frame = (task_stack_page(p) +  			    (THREAD_SIZE - child_stack_sz)); -	memcpy(child_trap_frame, parent_sf, child_stack_sz); -	t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | -				 (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | -		(((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);  	t->new_child = 1;  	t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;  	t->kregs = (struct pt_regs *) (child_trap_frame +  				       sizeof(struct sparc_stackf));  	t->fpsaved[0] = 0; -	if (kernel_thread) { -		struct sparc_stackf *child_sf = (struct sparc_stackf *) -			(child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); - -		/* Zero terminate the stack backtrace.  */ -		child_sf->fp = NULL; -		t->kregs->u_regs[UREG_FP] = -		  ((unsigned long) child_sf) - STACK_BIAS; +	if (unlikely(p->flags & PF_KTHREAD)) { +		memset(child_trap_frame, 0, child_stack_sz); +		__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =  +			(current_pt_regs()->tstate + 1) & TSTATE_CWP; +		t->current_ds = ASI_P; +		t->kregs->u_regs[UREG_G1] = sp; /* function */ +		t->kregs->u_regs[UREG_G2] = arg; +		return 0; +	} -		t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); -		t->kregs->u_regs[UREG_G6] = (unsigned long) t; -		t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; -	} else { -		if (t->flags & _TIF_32BIT) { -			sp &= 0x00000000ffffffffUL; -			regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; -		} -		t->kregs->u_regs[UREG_FP] = sp; -		t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT); -		if (sp != regs->u_regs[UREG_FP]) { -			unsigned long csp; +	parent_sf = ((struct sparc_stackf *) regs) - 1; +	memcpy(child_trap_frame, parent_sf, child_stack_sz); +	if (t->flags & _TIF_32BIT) { +		sp &= 0x00000000ffffffffUL; +		regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; +	} +	t->kregs->u_regs[UREG_FP] = sp; +	__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =  +		(regs->tstate + 1) & TSTATE_CWP; +	t->current_ds = ASI_AIUS; +	if (sp != regs->u_regs[UREG_FP]) { +		unsigned long csp; -			csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); -			if (!csp) -				return -EFAULT; -			t->kregs->u_regs[UREG_FP] = csp; -		} -		if (t->utraps) -			t->utraps[0]++; +		csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); +		if (!csp) +			return -EFAULT; +		t->kregs->u_regs[UREG_FP] = csp;  	} +	if (t->utraps) +		t->utraps[0]++;  	/* Set the return value for the child. */  	t->kregs->u_regs[UREG_I0] = current->pid; @@ -694,45 +684,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,  	return 0;  } -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ -	long retval; - -	/* If the parent runs before fn(arg) is called by the child, -	 * the input registers of this function can be clobbered. -	 * So we stash 'fn' and 'arg' into global registers which -	 * will not be modified by the parent. -	 */ -	__asm__ __volatile__("mov %4, %%g2\n\t"	   /* Save FN into global */ -			     "mov %5, %%g3\n\t"	   /* Save ARG into global */ -			     "mov %1, %%g1\n\t"	   /* Clone syscall nr. */ -			     "mov %2, %%o0\n\t"	   /* Clone flags. */ -			     "mov 0, %%o1\n\t"	   /* usp arg == 0 */ -			     "t 0x6d\n\t"	   /* Linux/Sparc clone(). */ -			     "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ -			     " mov %%o0, %0\n\t" -			     "jmpl %%g2, %%o7\n\t"   /* Call the function. */ -			     " mov %%g3, %%o0\n\t"   /* Set arg in delay. */ -			     "mov %3, %%g1\n\t" -			     "t 0x6d\n\t"	   /* Linux/Sparc exit(). */ -			     /* Notreached by child. */ -			     "1:" : -			     "=r" (retval) : -			     "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), -			     "i" (__NR_exit),  "r" (fn), "r" (arg) : -			     "g1", "g2", "g3", "o0", "o1", "memory", "cc"); -	return retval; -} -EXPORT_SYMBOL(kernel_thread); -  typedef struct {  	union {  		unsigned int	pr_regs[32]; @@ -799,41 +750,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)  }  EXPORT_SYMBOL(dump_fpu); -/* - * sparc_execve() executes a new program after the asm stub has set - * things up for us.  This should basically do what I want it to. - */ -asmlinkage int sparc_execve(struct pt_regs *regs) -{ -	int error, base = 0; -	struct filename *filename; - -	/* User register window flush is done by entry.S */ - -	/* Check for indirect call. */ -	if (regs->u_regs[UREG_G1] == 0) -		base = 1; - -	filename = getname((char __user *)regs->u_regs[base + UREG_I0]); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; -	error = do_execve(filename->name, -			  (const char __user *const __user *) -			  regs->u_regs[base + UREG_I1], -			  (const char __user *const __user *) -			  regs->u_regs[base + UREG_I2], regs); -	putname(filename); -	if (!error) { -		fprs_write(0); -		current_thread_info()->xfsr[0] = 0; -		current_thread_info()->fpsaved[0] = 0; -		regs->tstate &= ~TSTATE_PEF; -	} -out: -	return error; -} -  unsigned long get_wchan(struct task_struct *task)  {  	unsigned long pc, fp, bias = 0; diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index c3239811a1b..03c7e929ec3 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -396,42 +396,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,          return ret;  } -/* - * sparc32_execve() executes a new program after the asm stub has set - * things up for us.  This should basically do what I want it to. - */ -asmlinkage long sparc32_execve(struct pt_regs *regs) -{ -	int error, base = 0; -	struct filename *filename; - -	/* User register window flush is done by entry.S */ - -	/* Check for indirect call. */ -	if ((u32)regs->u_regs[UREG_G1] == 0) -		base = 1; - -	filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; - -	error = compat_do_execve(filename->name, -				 compat_ptr(regs->u_regs[base + UREG_I1]), -				 compat_ptr(regs->u_regs[base + UREG_I2]), regs); - -	putname(filename); - -	if (!error) { -		fprs_write(0); -		current_thread_info()->xfsr[0] = 0; -		current_thread_info()->fpsaved[0] = 0; -		regs->tstate &= ~TSTATE_PEF; -	} -out: -	return error; -} -  #ifdef CONFIG_MODULES  asmlinkage long sys32_init_module(void __user *umod, u32 len, diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 57277c83015..2da0bdcae52 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -249,27 +249,3 @@ out:  	up_read(&uts_sem);  	return err;  } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, -		  const char *const argv[], -		  const char *const envp[]) -{ -	long __res; -	register long __g1 __asm__ ("g1") = __NR_execve; -	register long __o0 __asm__ ("o0") = (long)(filename); -	register long __o1 __asm__ ("o1") = (long)(argv); -	register long __o2 __asm__ ("o2") = (long)(envp); -	asm volatile ("t 0x10\n\t" -		      "bcc 1f\n\t" -		      "mov %%o0, %0\n\t" -		      "sub %%g0, %%o0, %0\n\t" -		      "1:\n\t" -		      : "=r" (__res), "=&r" (__o0) -		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) -		      : "cc"); -	return __res; -} diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 97309c0ec53..708bc29d36a 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -646,28 +646,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,  	return ret;  } -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, -		  const char *const argv[], -		  const char *const envp[]) -{ -	long __res; -	register long __g1 __asm__ ("g1") = __NR_execve; -	register long __o0 __asm__ ("o0") = (long)(filename); -	register long __o1 __asm__ ("o1") = (long)(argv); -	register long __o2 __asm__ ("o2") = (long)(envp); -	asm volatile ("t 0x6d\n\t" -		      "sub %%g0, %%o0, %0\n\t" -		      "movcc %%xcc, %%o0, %0\n\t" -		      : "=r" (__res), "=&r" (__o0) -		      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) -		      : "cc"); -	return __res; -} -  asmlinkage long sys_kern_features(void)  {  	return KERN_FEATURE_MIXED_MODE_STACK; diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index bf2347794e3..e0fed7711a9 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -1,23 +1,19 @@  	/* SunOS's execv() call only specifies the argv argument, the  	 * environment settings are the same as the calling processes.  	 */ -sys_execve: -	sethi	%hi(sparc_execve), %g1 -	ba,pt	%xcc, execve_merge -	 or	%g1, %lo(sparc_execve), %g1 +sys64_execve: +	set	sys_execve, %g1 +	jmpl	%g1, %g0 +	 flushw  #ifdef CONFIG_COMPAT  sunos_execv: -	stx	%g0, [%sp + PTREGS_OFF + PT_V9_I2] +	mov	%g0, %o2  sys32_execve: -	sethi	%hi(sparc32_execve), %g1 -	or	%g1, %lo(sparc32_execve), %g1 -#endif - -execve_merge: -	flushw +	set	compat_sys_execve, %g1  	jmpl	%g1, %g0 -	 add	%sp, PTREGS_OFF, %o0 +	 flushw +#endif  	.align	32  sys_sparc_pipe: @@ -112,11 +108,16 @@ sys_clone:  ret_from_syscall:  	/* Clear current_thread_info()->new_child. */  	stb	%g0, [%g6 + TI_NEW_CHILD] -	ldx	[%g6 + TI_FLAGS], %l0  	call	schedule_tail  	 mov	%g7, %o0 +	ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0 +	brnz,pt	%o0, ret_sys_call +	 ldx	[%g6 + TI_FLAGS], %l0 +	ldx	[%sp + PTREGS_OFF + PT_V9_G1], %l1 +	call	%l1 +	 ldx	[%sp + PTREGS_OFF + PT_V9_G2], %o0  	ba,pt	%xcc, ret_sys_call -	 ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0 +	 mov	0, %o0  	.globl	sparc_exit_group  	.type	sparc_exit_group,#function @@ -232,7 +233,6 @@ ret_sys_call:  	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc  2: -	stb	%g0, [%g6 + TI_SYS_NOERROR]  	/* System call success, clear Carry condition code. */  	andn	%g3, %g2, %g3  3: diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 017b74a63dc..cdbd9b81775 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -107,7 +107,7 @@ sys_call_table:  /*40*/	.word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall  	.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid  /*50*/	.word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl -	.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve +	.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve  /*60*/	.word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize  	.word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall  /*70*/	.word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index b66a77968f3..e7ecf1507d9 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -2688,8 +2688,8 @@ void __init trap_init(void)  		     TI_PRE_COUNT != offsetof(struct thread_info,  					      preempt_count) ||  		     TI_NEW_CHILD != offsetof(struct thread_info, new_child) || -		     TI_SYS_NOERROR != offsetof(struct thread_info, -						syscall_noerror) || +		     TI_CURRENT_DS != offsetof(struct thread_info, +						current_ds) ||  		     TI_RESTART_BLOCK != offsetof(struct thread_info,  						  restart_block) ||  		     TI_KUNA_REGS != offsetof(struct thread_info,  |