Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Nov 2007 13:18:51 GMT
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 128736 for review
Message-ID:  <200711061318.lA6DIpe6076880@repoman.freebsd.org>

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

Change 128736 by gonzo@gonzo_jeeves on 2007/11/06 13:18:45

	o Implement cpu_set_upcall

Affected files ...

.. //depot/projects/mips2/src/sys/mips/mips/vm_machdep.c#17 edit

Differences ...

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

@@ -171,10 +171,52 @@
 	return ((struct sf_buf *)m);
 }
 
+/*
+ * Initialize machine state (pcb and trap frame) for a new thread about to
+ * upcall. Put enough state in the new thread's PCB to get it to go back 
+ * userret(), where we can intercept it again to set the return (upcall)
+ * Address and stack, along with those from upcals that are from other sources
+ * such as those generated in thread_userret() itself.
+ */
 void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
-	panic("%s", __func__);
+	register_t sp;
+
+	/*
+	 * Preserve SP from beeing overwritten.
+	 */
+	sp = td->td_pcb->pcb_regs[PCB_REG_SP];
+
+	bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
+	bcopy(td0->td_frame, td->td_frame, sizeof *td->td_frame);
+
+	/*
+	 * Call fork_trampoline into fork_return via the pcb.
+	 */
+	td->td_pcb->pcb_regs[PCB_REG_RA] = (register_t)fork_trampoline;
+	td->td_pcb->pcb_regs[PCB_REG_S0] = (register_t)fork_return;
+	td->td_pcb->pcb_regs[PCB_REG_S1] = (register_t)td;
+	td->td_pcb->pcb_regs[PCB_REG_S2] = (register_t)td->td_frame;
+	/*
+	 * Restore original stack.
+       	 */
+	td->td_pcb->pcb_regs[PCB_REG_SP] = sp;
+
+	/*
+	 * DO NOT ENABLE ANY INTERRUPTS HERE: 
+	 *	after cpu_throw we're supposed to be with td_lock locked
+	 *	and this means - no interrupts enabled.
+	 */	 
+	td->td_pcb->pcb_regs[PCB_REG_SR] = 0;
+
+	/* 
+	 * Setup to release spin count in fork_exit(). By unlocking
+	 * sched_lock we'll enable interrupts and unmask timer 
+	 * interrupt (HW IRQ5)
+	 */
+	td->td_md.md_spinlock_count = 1;
+	td->td_md.md_saved_sr = MIPS_SR_INT_IE | (((1 << 5) << 8) << 2);
 }
 
 void



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