}
/*
- * This gets run with P1 containing the
- * function to call, and R1 containing
- * the "args". Note P0 is clobbered on the way here.
- */
-void kernel_thread_helper(void);
-__asm__(".section .text\n"
- ".align 4\n"
- "_kernel_thread_helper:\n\t"
- "\tsp += -12;\n\t"
- "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
-{
- struct pt_regs regs;
-
- memset(®s, 0, sizeof(regs));
-
- regs.r1 = (unsigned long)arg;
- regs.p1 = (unsigned long)fn;
- regs.pc = (unsigned long)kernel_thread_helper;
- regs.orig_p0 = -1;
- /* Set bit 2 to tell ret_from_fork we should be returning to kernel
- mode. */
- regs.ipend = 0x8002;
- __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL,
- NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
* Do necessary setup to start up a newly executed thread.
*
* pass the data segment into user programs if it exists,
struct task_struct *p, struct pt_regs *regs)
{
struct pt_regs *childregs;
+ unsigned long *v;
childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
- *childregs = *regs;
- childregs->r0 = 0;
+ v = ((unsigned long *)childregs) - 2;
+ if (unlikely(!regs)) {
+ memset(childregs, 0, sizeof(struct pt_regs));
+ v[0] = usp;
+ v[1] = topstk;
+ childregs->orig_p0 = -1;
+ childregs->ipend = 0x8000;
+ __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):);
+ p->thread.usp = 0;
+ } else {
+ *childregs = *regs;
+ childregs->r0 = 0;
+ p->thread.usp = usp;
+ v[0] = v[1] = 0;
+ }
- p->thread.usp = usp;
- p->thread.ksp = (unsigned long)childregs;
+ p->thread.ksp = (unsigned long)v;
p->thread.pc = (unsigned long)ret_from_fork;
return 0;
jump .Lsyscall_really_exit;
ENDPROC(_trap)
-ENTRY(_kernel_execve)
- link SIZEOF_PTREGS;
- p0 = sp;
- r3 = SIZEOF_PTREGS / 4;
- r4 = 0(x);
-.Lclear_regs:
- [p0++] = r4;
- r3 += -1;
- cc = r3 == 0;
- if !cc jump .Lclear_regs (bp);
-
- p0 = sp;
- sp += -16;
- [sp + 12] = p0;
- pseudo_long_call _do_execve, p5;
- SP += 16;
- cc = r0 == 0;
- if ! cc jump .Lexecve_failed;
- /* Success. Copy our temporary pt_regs to the top of the kernel
- * stack and do a normal exception return.
- */
- r1 = sp;
- r0 = (-KERNEL_STACK_SIZE) (x);
- r1 = r1 & r0;
- p2 = r1;
- p3 = [p2];
- r0 = KERNEL_STACK_SIZE - 4 (z);
- p1 = r0;
- p1 = p1 + p2;
-
- p0 = fp;
- r4 = [p0--];
- r3 = SIZEOF_PTREGS / 4;
-.Lcopy_regs:
- r4 = [p0--];
- [p1--] = r4;
- r3 += -1;
- cc = r3 == 0;
- if ! cc jump .Lcopy_regs (bp);
-
- r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
- p1 = r0;
- p1 = p1 + p2;
- sp = p1;
- r0 = syscfg;
- [SP + PT_SYSCFG] = r0;
- [p3 + (TASK_THREAD + THREAD_KSP)] = sp;
-
- RESTORE_CONTEXT;
- rti;
-.Lexecve_failed:
- unlink;
- rts;
-ENDPROC(_kernel_execve)
-
ENTRY(_system_call)
/* Store IPEND */
p2.l = lo(IPEND);