*
* Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others.
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2004 Thiemo Seufer
*/
#include <linux/config.h>
#include <linux/errno.h>
childksp = (unsigned long)ti + THREAD_SIZE - 32;
- preempt_disable();
-
if (is_fpu_owner()) {
save_fp(p);
}
- preempt_enable();
-
/* set up new TSS. */
childregs = (struct pt_regs *) childksp - 1;
*childregs = *regs;
p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
clear_tsk_thread_flag(p, TIF_USEDFPU);
+ p->set_child_tid = p->clear_child_tid = NULL;
return 0;
}
/*
* Create a kernel thread
*/
-ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
-{
- do_exit(fn(arg));
-}
-
long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
- struct pt_regs regs;
-
- memset(®s, 0, sizeof(regs));
-
- regs.regs[4] = (unsigned long) arg;
- regs.regs[5] = (unsigned long) fn;
- regs.cp0_epc = (unsigned long) kernel_thread_helper;
- regs.cp0_status = read_c0_status();
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
- regs.cp0_status &= ~(ST0_KUP | ST0_IEC);
- regs.cp0_status |= ST0_IEP;
-#else
- regs.cp0_status |= ST0_EXL;
+ long retval;
+
+ __asm__ __volatile__(
+ " move $6, $sp \n"
+ " move $4, %5 \n"
+ " li $2, %1 \n"
+ " syscall \n"
+ " beq $6, $sp, 1f \n"
+#ifdef CONFIG_MIPS32 /* On o32 the caller has to create the stackframe */
+ " subu $sp, 32 \n"
#endif
-
- /* Ok, create the new process.. */
- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
+ " move $4, %3 \n"
+ " jalr %4 \n"
+ " move $4, $2 \n"
+ " li $2, %2 \n"
+ " syscall \n"
+#ifdef CONFIG_MIPS32 /* On o32 the caller has to deallocate the stackframe */
+ " addiu $sp, 32 \n"
+#endif
+ "1: move %0, $2"
+ : "=r" (retval)
+ : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn),
+ "r" (flags | CLONE_VM | CLONE_UNTRACED)
+ /*
+ * The called subroutine might have destroyed any of the
+ * at, result, argument or temporary registers ...
+ */
+ : "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$9","$10","$11","$12","$13","$14","$15","$24","$25","$31");
+
+ return retval;
}
struct mips_frame_info {