src/sys/mips/mips/vm_machdep.c
/*
 * Initialize machine state, mostly pcb and trap frame for a new
 * thread, about to return to userspace.  Put enough state in the new
 * thread's PCB to get it to go back to the fork_return(), which
 * finalizes the thread state and handles peculiarities of the first
 * return to userspace for the new thread.
 */
Initialize machine state, mostly pcb and trap frame for a new
thread, about to return to userspace.  Put enough state in the new
thread's PCB to get it to go back to the fork_return(), which
finalizes the thread state and handles peculiarities of the first
return to userspace for the new thread.
Initialize machine state mostly pcb and trap frame for a new thread about to return to userspace . Put enough state in the new thread ' s PCB to get it to go back to the fork_return () which finalizes the thread state and handles peculiarities of the first return to userspace for the new thread .
void
cpu_copy_thread(struct thread *td, struct thread *td0)
{
	struct pcb *pcb2;
	pcb2 = td->td_pcb;
	bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
	pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline;
	pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td->td_pcb &
	    ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ);
	pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return;
	pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td;
	pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td->td_frame;
	pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() &
	    (MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK);
	td->td_md.md_spinlock_count = 1;
	td->td_md.md_saved_intr = MIPS_SR_INT_IE;
#if 0
	td->td_md.md_saved_sr = ( (MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT) |
	                          (MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX) |
	                          (MIPS_SR_INT_IE | MIPS_HARD_INT_MASK));
#endif
}
void cpu_copy_thread ( struct thread * td , struct thread * td0 ) { struct pcb * pcb2 ; pcb2 = td -> td_pcb ; bcopy ( td0 -> td_pcb , pcb2 , sizeof ( * pcb2 ) ) ; pcb2 -> pcb_context [ PCB_REG_RA ] = ( register_t ) ( intptr_t ) fork_trampoline ; pcb2 -> pcb_context [ PCB_REG_SP ] = ( register_t ) ( ( ( vm_offset_t ) td -> td_pcb & ~ ( sizeof ( __int64_t ) - 1 ) ) - CALLFRAME_SIZ ) ; pcb2 -> pcb_context [ PCB_REG_S0 ] = ( register_t ) ( intptr_t ) fork_return ; pcb2 -> pcb_context [ PCB_REG_S1 ] = ( register_t ) ( intptr_t ) td ; pcb2 -> pcb_context [ PCB_REG_S2 ] = ( register_t ) ( intptr_t ) td -> td_frame ; pcb2 -> pcb_context [ PCB_REG_SR ] = mips_rd_status ( ) & ( MIPS_SR_PX | MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK ) ; td -> td_md . md_spinlock_count = 1 ; td -> td_md . md_saved_intr = MIPS_SR_INT_IE ; #if 0 td -> td_md . md_saved_sr = ( ( MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT ) | ( MIPS_SR_PX | MIPS_SR_UX | MIPS_SR_KX | MIPS_SR_SX ) | ( MIPS_SR_INT_IE | MIPS_HARD_INT_MASK ) ) ; #endif }
Initialize machine state, mostly pcb and trap frame for a new
 thread, about to return to userspace.
Initialize machine state mostly pcb and trap frame for a new thread about to return to userspace .
/* Point the pcb to the top of the stack. */ /*
	 * Copy the upcall pcb.  This loads kernel regs.
	 * Those not loaded individually below get their default
	 * values here.
	 *
	 * XXXKSE It might be a good idea to simply skip this as
	 * the values of the other registers may be unimportant.
	 * This would remove any requirement for knowing the KSE
	 * at this time (see the matching comment below for
	 * more analysis) (need a good safe default).
	 * In MIPS, the trapframe is the first element of the PCB
	 * and gets copied when we copy the PCB. No separate copy
	 * is needed.
	 */ /*
	 * Set registers for trampoline to user mode.
	 */ /* Make sp 64-bit aligned */ /* Dont set IE bit in SR. sched lock release will take care of it */ /*
	 * FREEBSD_DEVELOPERS_FIXME:
	 * Setup any other CPU-Specific registers (Not MIPS Standard)
	 * that are needed.
	 */ /* Setup to release spin count in in fork_exit(). */ /* Maybe we need to fix this? */