Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Jul 2006 19:20:40 GMT
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 101788 for review
Message-ID:  <200607171920.k6HJKejF030199@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=101788

Change 101788 by gonzo@gonzo_hq on 2006/07/17 19:20:21

	o fork/context switching routines merged from juli's sources.

Affected files ...

.. //depot/projects/mips2/src/sys/mips/mips/swtch.S#3 edit
.. //depot/projects/mips2/src/sys/mips/mips/vm_machdep.c#4 edit

Differences ...

==== //depot/projects/mips2/src/sys/mips/mips/swtch.S#3 (text+ko) ====

@@ -30,24 +30,86 @@
 
 #include <machine/asm.h>
 #include <machine/asmacros.h>
+#include <machine/cpuregs.h>
 __FBSDID("$FreeBSD$");
 
 /*
- * XXXMIPS: Implement these routines
+ * a0: struct thread *old
+ * a1: struct thread *new
  */
+ENTRY(cpu_throw)
+	subu	sp, 8
+	sw	a1, 0(sp)
+	move	a0, a1
+	jal	pmap_activate
+	nop
+	lw	t3, 0(sp)
+	addu	sp, 8
+	.set at
+	lw	t2, pcpup
+	.set noat
+	sw	t3, PC_CURTHREAD(t2)
+	lw	t0, TD_PCB(t3)
+	sw	t0, PC_CURPCB(t2)
+	lw	s0, PCB_REG_S0(t0)
+	lw	s1, PCB_REG_S1(t0)
+	lw	s2, PCB_REG_S2(t0)
+	lw	s3, PCB_REG_S3(t0)
+	lw	s4, PCB_REG_S4(t0)
+	lw	s5, PCB_REG_S5(t0)
+	lw	s6, PCB_REG_S6(t0)
+	lw	s7, PCB_REG_S7(t0)
+	lw	s8, PCB_REG_S8(t0)
+	lw	sp, PCB_REG_SP(t0)
+	lw	ra, PCB_REG_RA(t0)
+	lw	t0, PCB_REG_SR(t0)
+	/* Copy s0-s3 into a0-s3 so we can just pass args. */
+	move	a0, s0
+	move	a1, s1
+	move	a2, s2
+	move	a3, s3
+	mtc0	t0, MIPS_COP_0_STATUS
+	li	v0, 1
+	jr	ra
+	nop
 
-ENTRY(cpu_throw)
-	break
 END(cpu_throw)
 
-ENTRY(cpu_switch)
-	break
-END(cpu_switch)
+/*
+ * a0: struct pcb *pcb
+ */
+ENTRY(savectx)
+	mfc0	t0, MIPS_COP_0_STATUS
+	sw	s0, PCB_REG_S0(a0)
+	sw	s1, PCB_REG_S1(a0)
+	sw	s2, PCB_REG_S2(a0)
+	sw	s3, PCB_REG_S3(a0)
+	sw	s4, PCB_REG_S4(a0)
+	sw	s5, PCB_REG_S5(a0)
+	sw	s6, PCB_REG_S6(a0)
+	sw	s7, PCB_REG_S7(a0)
+	sw	s8, PCB_REG_S8(a0)
+	sw	sp, PCB_REG_SP(a0)
+	sw	t0, PCB_REG_SR(a0)
+	sw	ra, PCB_REG_RA(a0)
+	li	v0, 0
+	jr	ra
+	nop
 
-ENTRY(savectx)
-	break
 END(savectx)
 
+/*
+ * s0: Routine to call.
+ * s1: a0 for said routine.
+ * s2: a1 for said routine.
+ * These need passed to fork_exit as a0, a1, a2 respectively.
+ */
+
 ENTRY(fork_trampoline)
-	break
+	move	a0, s0
+	move	a1, s1
+	move	a2, s2
+	j	fork_exit
+	nop
+
 END(fork_trampoline)

==== //depot/projects/mips2/src/sys/mips/mips/vm_machdep.c#4 (text+ko) ====

@@ -58,11 +58,53 @@
 #include <vm/uma.h>
 #include <vm/uma_int.h>
 
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the pcb, set up the stack so that the child
+ * ready to run and return to user mode.
+ */
 void
-cpu_fork(register struct thread *td1, register struct proc *p2,
+cpu_fork(register struct thread *td, register struct proc *p2,
     struct thread *td2, int flags)
 {
-	panic("%s", __func__);
+	if ((flags & RFPROC) == 0)
+		return;
+
+	cpu_thread_setup(td2);
+
+	/* Copy the pcb */
+	bcopy(td->td_pcb, td2->td_pcb, sizeof(struct pcb));
+
+	/*
+	 * Copy the trap frame for the return to user mode as if from a
+	 * syscall.  This copies most of the user mode register values.
+	 */
+	bcopy(td->td_frame, td2->td_frame, sizeof *td2->td_frame);
+
+	/*
+	 * Call fork_trampoline into fork_return via the pcb.
+	 */
+	td2->td_pcb->pcb_regs[PCB_REG_RA] = (register_t)fork_trampoline;
+	td2->td_pcb->pcb_regs[PCB_REG_S0] = (register_t)fork_return;
+	td2->td_pcb->pcb_regs[PCB_REG_S1] = (register_t)td2;
+	td2->td_pcb->pcb_regs[PCB_REG_S2] = (register_t)td2->td_frame;
+
+	/*
+ 	 * Now cpu_switch() can schedule the new process.
+	 */
+
+	/* Setup to release sched_lock in fork_exit(). */
+	td2->td_md.md_spinlock_count = 1;
+}
+
+void
+cpu_switch(struct thread *old, struct thread *new)
+{
+	if (!savectx(old->td_pcb)) {
+		pmap_deactivate(old);
+		cpu_throw(old, new);
+		panic("%s: should not be reached", __func__);
+	}
 }
 				
 void
@@ -143,7 +185,8 @@
 void
 cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
 {
-	panic("%s", __func__);
+	td->td_pcb->pcb_regs[PCB_REG_S0] = (register_t)func;
+	td->td_pcb->pcb_regs[PCB_REG_S1] = (register_t)arg;
 }
 
 void  



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607171920.k6HJKejF030199>