in kernel/process.c [103:146]
int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
struct task_struct *p, unsigned long tls)
{
struct pt_regs *childregs = task_pt_regs(p);
struct pt_regs *regs;
struct switch_stack *stack;
struct switch_stack *childstack =
((struct switch_stack *)childregs) - 1;
if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
memset(childstack, 0,
sizeof(struct switch_stack) + sizeof(struct pt_regs));
childstack->r16 = usp; /* fn */
childstack->r17 = arg;
childstack->ra = (unsigned long) ret_from_kernel_thread;
childregs->estatus = STATUS_PIE;
childregs->sp = (unsigned long) childstack;
p->thread.ksp = (unsigned long) childstack;
p->thread.kregs = childregs;
return 0;
}
regs = current_pt_regs();
*childregs = *regs;
childregs->r2 = 0; /* Set the return value for the child. */
childregs->r7 = 0;
stack = ((struct switch_stack *) regs) - 1;
*childstack = *stack;
childstack->ra = (unsigned long)ret_from_fork;
p->thread.kregs = childregs;
p->thread.ksp = (unsigned long) childstack;
if (usp)
childregs->sp = usp;
/* Initialize tls register. */
if (clone_flags & CLONE_SETTLS)
childstack->r23 = tls;
return 0;
}