From: William Lee Irwin III <wli@holomorphy.com>

It fixes the fork-idle consolidation.  During that consolidation, the generic
code was made to pass a pointer to on-stack pt_regs that had been memset() to
0.  ia64, however, requires a NULL pt_regs pointer argument and dispatches on
that in its copy_thread() function to do SMP trampoline-specific RSE -related
setup.  Passing pointers to zeroed pt_regs resulted in SMP wakeup -time
deadlocks and exceptions.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ia64/kernel/smpboot.c |    5 +++++
 25-akpm/kernel/fork.c              |    9 +++++++--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff -puN arch/ia64/kernel/smpboot.c~kill-clone_idletask-fix arch/ia64/kernel/smpboot.c
--- 25/arch/ia64/kernel/smpboot.c~kill-clone_idletask-fix	2004-08-15 13:58:20.595928160 -0700
+++ 25-akpm/arch/ia64/kernel/smpboot.c	2004-08-15 13:58:20.601927248 -0700
@@ -356,6 +356,11 @@ start_secondary (void *unused)
 	return cpu_idle();
 }
 
+struct pt_regs * __init idle_regs(struct pt_regs *regs)
+{
+	return NULL;
+}
+
 struct create_idle {
 	struct task_struct *idle;
 	struct completion done;
diff -puN kernel/fork.c~kill-clone_idletask-fix kernel/fork.c
--- 25/kernel/fork.c~kill-clone_idletask-fix	2004-08-15 13:58:20.597927856 -0700
+++ 25-akpm/kernel/fork.c	2004-08-15 13:58:20.602927096 -0700
@@ -1190,13 +1190,18 @@ bad_fork_free:
 	goto fork_out;
 }
 
+struct pt_regs * __init __attribute__((weak)) idle_regs(struct pt_regs *regs)
+{
+	memset(regs, 0, sizeof(struct pt_regs));
+	return regs;
+}
+
 task_t * __init fork_idle(int cpu)
 {
 	task_t *task;
 	struct pt_regs regs;
 
-	memset(&regs, 0, sizeof(struct pt_regs));
-	task = copy_process(CLONE_VM, 0, &regs, 0, NULL, NULL, 0);
+	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
 	if (!task)
 		return ERR_PTR(-ENOMEM);
 	init_idle(task, cpu);
_