Commit 9fa2b7c4 authored by Miles Bader's avatar Miles Bader Committed by Linus Torvalds

[PATCH] Set child process initial stack-pointers correctly on the v850

Previously the v850's copy_thread function didn't set the child's stack
pointer at all, with the result that it accidentally worked for vfork
(where the child has the same SP as the parent), but not for user
threads; kernel threads also accidentally worked, for a different
reason.
parent 59c336ee
/* /*
* arch/v850/kernel/process.c -- Arch-dependent process handling * arch/v850/kernel/process.c -- Arch-dependent process handling
* *
* Copyright (C) 2001,02 NEC Corporation * Copyright (C) 2001,02,03 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org> * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
* *
* This file is subject to the terms and conditions of the GNU General * This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this * Public License. See the file COPYING in the main directory of this
...@@ -75,7 +75,9 @@ int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) ...@@ -75,7 +75,9 @@ int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
set_fs (KERNEL_DS); set_fs (KERNEL_DS);
/* Clone this thread. */ /* Clone this thread. Note that we don't pass the clone syscall's
second argument -- it's ignored for calls from kernel mode (the
child's SP is always set to the top of the kernel stack). */
arg0 = flags | CLONE_VM; arg0 = flags | CLONE_VM;
syscall = __NR_clone; syscall = __NR_clone;
asm volatile ("trap " SYSCALL_SHORT_TRAP asm volatile ("trap " SYSCALL_SHORT_TRAP
...@@ -109,7 +111,8 @@ int copy_thread (int nr, unsigned long clone_flags, ...@@ -109,7 +111,8 @@ int copy_thread (int nr, unsigned long clone_flags,
struct task_struct *p, struct pt_regs *regs) struct task_struct *p, struct pt_regs *regs)
{ {
/* Start pushing stuff from the top of the child's kernel stack. */ /* Start pushing stuff from the top of the child's kernel stack. */
unsigned long ksp = (unsigned long)p->thread_info + THREAD_SIZE; unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE;
unsigned long ksp = orig_ksp;
/* We push two `state save' stack fames (see entry.S) on the new /* We push two `state save' stack fames (see entry.S) on the new
kernel stack: kernel stack:
1) The innermost one is what switch_thread would have 1) The innermost one is what switch_thread would have
...@@ -138,6 +141,19 @@ int copy_thread (int nr, unsigned long clone_flags, ...@@ -138,6 +141,19 @@ int copy_thread (int nr, unsigned long clone_flags,
jump when the child thread begins running. */ jump when the child thread begins running. */
child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork; child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork;
if (regs->kernel_mode)
/* Since we're returning to kernel-mode, make sure the child's
stored kernel stack pointer agrees with what the actual
stack pointer will be at that point (the trap return code
always restores the SP, even when returning to
kernel-mode). */
child_trap_regs->gpr[GPR_SP] = orig_ksp;
else
/* Set the child's user-mode stack-pointer (the name
`stack_start' is a misnomer, it's just the initial SP
value). */
child_trap_regs->gpr[GPR_SP] = stack_start;
/* Thread state for the child (everything else is on the stack). */ /* Thread state for the child (everything else is on the stack). */
p->thread.ksp = ksp; p->thread.ksp = ksp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment