int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { struct pt_regs * childregs; long childksp; extern void save_fp(void*); childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; if (last_task_used_math == current) if (mips_cpu.options & MIPS_CPU_FPU) { __enable_fpu(); save_fp(p); } /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; set_gpreg(childregs, 7, 0); /* Clear error flag */ if(current->personality == PER_LINUX) { set_gpreg(childregs, 2, 0); /* Child gets zero as return value */ set_gpreg(regs, 2, p->pid); } else { /* Under IRIX things are a little different. */ set_gpreg(childregs, 2, 0); set_gpreg(childregs, 3, 1); set_gpreg(regs, 2, p->pid); set_gpreg(regs, 3, 0); } if (childregs->cp0_status & ST0_CU0) { set_gpreg(childregs, 28, (unsigned long) p); set_gpreg(childregs, 29, childksp); p->thread.current_ds = KERNEL_DS; } else { set_gpreg(childregs, 29, usp); p->thread.current_ds = USER_DS; } p->thread.reg29 = (unsigned long) childregs; p->thread.reg31 = (unsigned long) ret_from_fork; /* * New tasks loose permission to use the fpu. This accelerates context * switching for most programs since they don't use the fpu. */ #ifdef CONFIG_PS2 /* keep COP2 usable bit to share the VPU0 context */ p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) & ~(ST0_CU1|KU_MASK); childregs->cp0_status &= ~(ST0_CU1); #else p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) & ~(ST0_CU2|ST0_CU1|KU_MASK); childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); #endif return 0; }
asmlinkage int sys_pipe(struct pt_regs regs) { int fd[2]; int error, res; lock_kernel(); error = do_pipe(fd); if (error) { res = error; goto out; } set_gpreg(®s, 3, fd[1]); res = fd[0]; out: unlock_kernel(); return res; }