Skip to content

Commit

Permalink
sh: switch to generic fork/vfork/clone
Browse files Browse the repository at this point in the history
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Nov 29, 2012
1 parent 415bfae commit 0ad9513
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 110 deletions.
10 changes: 0 additions & 10 deletions arch/sh/include/asm/syscalls_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@

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_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact);
Expand Down
13 changes: 0 additions & 13 deletions arch/sh/include/asm/syscalls_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,6 @@

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 */
asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
Expand Down
3 changes: 3 additions & 0 deletions arch/sh/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
# define __ARCH_WANT_SYS_SIGPROCMASK
# define __ARCH_WANT_SYS_RT_SIGACTION
# define __ARCH_WANT_SYS_EXECVE
# define __ARCH_WANT_SYS_FORK
# define __ARCH_WANT_SYS_VFORK
# define __ARCH_WANT_SYS_CLONE

/*
* "Conditional" syscalls
Expand Down
52 changes: 4 additions & 48 deletions arch/sh/kernel/process_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ asmlinkage void ret_from_kernel_thread(void);

int copy_thread(unsigned long clone_flags, unsigned long usp,
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 pt_regs *childregs;
Expand Down Expand Up @@ -164,9 +164,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->fpu_counter = 0;
return 0;
}
*childregs = *regs;
*childregs = *current_pt_regs();

childregs->regs[15] = usp;
if (usp)
childregs->regs[15] = usp;
ti->addr_limit = USER_DS;

if (clone_flags & CLONE_SETTLS)
Expand Down Expand Up @@ -217,51 +218,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
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 pc;
Expand Down
43 changes: 4 additions & 39 deletions arch/sh/kernel/process_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
save_fpu(current);
disable_fpu();
last_task_used_math = NULL;
regs->sr |= SR_FD;
current_pt_regs()->sr |= SR_FD;
}
#endif
/* Copy from sh version */
Expand All @@ -399,15 +399,16 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->thread.pc = (unsigned long) ret_from_kernel_thread;
return 0;
}
*childregs = *regs;
*childregs = *current_pt_regs();

/*
* Sign extend the edited stack.
* Note that thread.pc and thread.pc will stay
* 32-bit wide and context switch must take care
* of NEFF sign extension.
*/
childregs->regs[15] = neff_sign_extend(usp);
if (usp)
childregs->regs[15] = neff_sign_extend(usp);
p->thread.uregs = childregs;

childregs->regs[9] = 0; /* Set return value for child */
Expand All @@ -418,42 +419,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
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
static int in_sh64_switch_to(unsigned long pc)
{
Expand Down

0 comments on commit 0ad9513

Please sign in to comment.