sparc64: Fix kernel thread stack termination.

Because of the silly way I set up the initial stack for
new kernel threads, there is a loop at the top of the
stack.

To fix this, properly add another stack frame that is copied
from the parent and terminate it in the child by setting
the frame pointer in that frame to zero.

Signed-off-by: David S. Miller <davem@davemloft.net>

+24 -10
+24 -10
arch/sparc64/kernel/process.c
··· 657 657 struct task_struct *p, struct pt_regs *regs) 658 658 { 659 659 struct thread_info *t = task_thread_info(p); 660 + struct sparc_stackf *parent_sf; 661 + unsigned long child_stack_sz; 660 662 char *child_trap_frame; 663 + int kernel_thread; 664 + 665 + kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; 666 + parent_sf = ((struct sparc_stackf *) regs) - 1; 661 667 662 668 /* Calculate offset to stack_frame & pt_regs */ 663 - child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); 664 - memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); 669 + child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + 670 + (kernel_thread ? STACKFRAME_SZ : 0)); 671 + child_trap_frame = (task_stack_page(p) + 672 + (THREAD_SIZE - child_stack_sz)); 673 + memcpy(child_trap_frame, parent_sf, child_stack_sz); 665 674 666 - t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | 675 + t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | 676 + (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | 667 677 (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); 668 678 t->new_child = 1; 669 679 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; 670 - t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct sparc_stackf)); 680 + t->kregs = (struct pt_regs *) (child_trap_frame + 681 + sizeof(struct sparc_stackf)); 671 682 t->fpsaved[0] = 0; 672 683 673 - if (regs->tstate & TSTATE_PRIV) { 684 + if (kernel_thread) { 685 + struct sparc_stackf *child_sf = (struct sparc_stackf *) 686 + (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); 687 + 688 + /* Zero terminate the stack backtrace. */ 689 + child_sf->fp = NULL; 690 + t->kregs->u_regs[UREG_FP] = 691 + ((unsigned long) child_sf) - STACK_BIAS; 692 + 674 693 /* Special case, if we are spawning a kernel thread from 675 694 * a userspace task (via KMOD, NFS, or similar) we must 676 695 * disable performance counters in the child because the ··· 700 681 t->pcr_reg = 0; 701 682 t->flags &= ~_TIF_PERFCTR; 702 683 } 703 - t->kregs->u_regs[UREG_FP] = t->ksp; 704 684 t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); 705 - flush_register_windows(); 706 - memcpy((void *)(t->ksp + STACK_BIAS), 707 - (void *)(regs->u_regs[UREG_FP] + STACK_BIAS), 708 - sizeof(struct sparc_stackf)); 709 685 t->kregs->u_regs[UREG_G6] = (unsigned long) t; 710 686 t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; 711 687 } else {