PERFORCE change 101788 for review
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Mon Jul 17 19:20:41 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=101788
Change 101788 by gonzo at 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
More information about the p4-projects
mailing list