summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/ppc/kernel/entry.S2
-rw-r--r--arch/ppc/kernel/misc.S1
-rw-r--r--arch/ppc/kernel/process.c17
3 files changed, 11 insertions, 9 deletions
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index bcef1397bb94..0f68f70455cf 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -182,9 +182,7 @@ syscall_exit_cont:
.globl ret_from_fork
ret_from_fork:
REST_NVGPRS(r1)
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
bl schedule_tail
-#endif
li r3,0
b ret_from_syscall
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 480f941794b1..4f9291dafcb7 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1006,6 +1006,7 @@ _GLOBAL(kernel_thread)
mr r31,r4 /* argument */
ori r3,r5,CLONE_VM /* flags */
oris r3,r3,CLONE_UNTRACED>>16
+ li r4,0 /* new sp (unused) */
li r0,__NR_clone
sc
cmpi 0,r3,0 /* parent or child? */
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index c2aaff96a18a..6d6b3d3fed00 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -332,7 +332,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
unsigned long childframe;
- p->user_tid = NULL;
+ p->set_child_tid = p->clear_child_tid = NULL;
CHECK_FULL_REGS(regs);
/* Copy registers */
@@ -344,8 +344,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->gpr[1] = sp + sizeof(struct pt_regs);
childregs->gpr[2] = (unsigned long) p;
p->thread.regs = NULL; /* no user register state */
- } else
+ } else {
+ childregs->gpr[1] = usp;
p->thread.regs = childregs;
+ }
childregs->gpr[3] = 0; /* Result from fork() */
sp -= STACK_FRAME_OVERHEAD;
childframe = sp;
@@ -449,9 +451,9 @@ int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
struct task_struct *p;
CHECK_FULL_REGS(regs);
- if ((p1 & (CLONE_SETTID | CLONE_CLEARTID)) == 0)
- p3 = 0;
- p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3);
+ if (p2 == 0)
+ p2 = regs->gpr[1]; /* stack pointer for child */
+ p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
@@ -460,7 +462,7 @@ int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
{
struct task_struct *p;
CHECK_FULL_REGS(regs);
- p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL);
+ p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
@@ -469,7 +471,8 @@ int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
{
struct task_struct *p;
CHECK_FULL_REGS(regs);
- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL);
+ p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs,
+ 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}