sh: switch to generic fork/vfork/clone

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2012-10-27 00:13:51 -04:00
parent 415bfae9e9
commit 0ad9513d0f
5 changed files with 11 additions and 110 deletions

View File

@ -9,16 +9,6 @@
struct pt_regs; struct pt_regs;
asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long parent_tidptr,
unsigned long child_tidptr,
struct pt_regs __regs);
asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
asmlinkage int sys_sigsuspend(old_sigset_t mask); asmlinkage int sys_sigsuspend(old_sigset_t mask);
asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact); struct old_sigaction __user *oact);

View File

@ -9,19 +9,6 @@
struct pt_regs; struct pt_regs;
asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs);
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs);
asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs);
/* Misc syscall related bits */ /* Misc syscall related bits */
asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs); asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);

View File

@ -29,6 +29,9 @@
# define __ARCH_WANT_SYS_SIGPROCMASK # define __ARCH_WANT_SYS_SIGPROCMASK
# define __ARCH_WANT_SYS_RT_SIGACTION # define __ARCH_WANT_SYS_RT_SIGACTION
# define __ARCH_WANT_SYS_EXECVE # define __ARCH_WANT_SYS_EXECVE
# define __ARCH_WANT_SYS_FORK
# define __ARCH_WANT_SYS_VFORK
# define __ARCH_WANT_SYS_CLONE
/* /*
* "Conditional" syscalls * "Conditional" syscalls

View File

@ -129,7 +129,7 @@ asmlinkage void ret_from_kernel_thread(void);
int copy_thread(unsigned long clone_flags, unsigned long usp, int copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long arg, unsigned long arg,
struct task_struct *p, struct pt_regs *regs) struct task_struct *p, struct pt_regs *unused)
{ {
struct thread_info *ti = task_thread_info(p); struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs; struct pt_regs *childregs;
@ -164,9 +164,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->fpu_counter = 0; p->fpu_counter = 0;
return 0; return 0;
} }
*childregs = *regs; *childregs = *current_pt_regs();
childregs->regs[15] = usp; if (usp)
childregs->regs[15] = usp;
ti->addr_limit = USER_DS; ti->addr_limit = USER_DS;
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
@ -217,51 +218,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
return prev; return prev;
} }
asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
#ifdef CONFIG_MMU
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
#else
/* fork almost works, enough to trick you into looking elsewhere :-( */
return -EINVAL;
#endif
}
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long parent_tidptr,
unsigned long child_tidptr,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
if (!newsp)
newsp = regs->regs[15];
return do_fork(clone_flags, newsp, regs, 0,
(int __user *)parent_tidptr,
(int __user *)child_tidptr);
}
/*
* This is trivial, and on the face of it looks like it
* could equally well be done in user mode.
*
* Not so, for quite unobvious reasons - register pressure.
* In user mode vfork() cannot have a stack frame, and if
* done by calling the "clone()" system call directly, you
* do not have enough call-clobbered registers to hold all
* the information you need.
*/
asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
0, NULL, NULL);
}
unsigned long get_wchan(struct task_struct *p) unsigned long get_wchan(struct task_struct *p)
{ {
unsigned long pc; unsigned long pc;

View File

@ -383,7 +383,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
save_fpu(current); save_fpu(current);
disable_fpu(); disable_fpu();
last_task_used_math = NULL; last_task_used_math = NULL;
regs->sr |= SR_FD; current_pt_regs()->sr |= SR_FD;
} }
#endif #endif
/* Copy from sh version */ /* Copy from sh version */
@ -399,7 +399,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->thread.pc = (unsigned long) ret_from_kernel_thread; p->thread.pc = (unsigned long) ret_from_kernel_thread;
return 0; return 0;
} }
*childregs = *regs; *childregs = *current_pt_regs();
/* /*
* Sign extend the edited stack. * Sign extend the edited stack.
@ -407,7 +407,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
* 32-bit wide and context switch must take care * 32-bit wide and context switch must take care
* of NEFF sign extension. * of NEFF sign extension.
*/ */
childregs->regs[15] = neff_sign_extend(usp); if (usp)
childregs->regs[15] = neff_sign_extend(usp);
p->thread.uregs = childregs; p->thread.uregs = childregs;
childregs->regs[9] = 0; /* Set return value for child */ childregs->regs[9] = 0; /* Set return value for child */
@ -418,42 +419,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
return 0; return 0;
} }
asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs)
{
return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
}
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs)
{
if (!newsp)
newsp = pregs->regs[15];
return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
}
/*
* This is trivial, and on the face of it looks like it
* could equally well be done in user mode.
*
* Not so, for quite unobvious reasons - register pressure.
* In user mode vfork() cannot have a stack frame, and if
* done by calling the "clone()" system call directly, you
* do not have enough call-clobbered registers to hold all
* the information you need.
*/
asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs *pregs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
}
#ifdef CONFIG_FRAME_POINTER #ifdef CONFIG_FRAME_POINTER
static int in_sh64_switch_to(unsigned long pc) static int in_sh64_switch_to(unsigned long pc)
{ {