FreeBSD/sys/amd64/amd64/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));
	clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE |
	    PCB_KERNFPU);
	pcb2->pcb_save = get_pcb_user_save_pcb(pcb2);
	bcopy(get_pcb_user_save_td(td0), pcb2->pcb_save,
	    cpu_max_ext_state_size);
	set_pcb_flags(pcb2, PCB_FULL_IRET);
	bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
	td->td_frame->tf_rflags &= ~PSL_T;
	pcb2->pcb_r12 = (register_t)fork_return;	    
	pcb2->pcb_rbp = 0;
	pcb2->pcb_rsp = (register_t)td->td_frame - sizeof(void *);	
	pcb2->pcb_rbx = (register_t)td;			    
	pcb2->pcb_rip = (register_t)fork_trampoline;
	td->td_md.md_spinlock_count = 1;
	td->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
}
void cpu_copy_thread ( struct thread * td , struct thread * td0 ) { struct pcb * pcb2 ; pcb2 = td -> td_pcb ; bcopy ( td0 -> td_pcb , pcb2 , sizeof ( * pcb2 ) ) ; clear_pcb_flags ( pcb2 , PCB_FPUINITDONE | PCB_USERFPUINITDONE | PCB_KERNFPU ) ; pcb2 -> pcb_save = get_pcb_user_save_pcb ( pcb2 ) ; bcopy ( get_pcb_user_save_td ( td0 ) , pcb2 -> pcb_save , cpu_max_ext_state_size ) ; set_pcb_flags ( pcb2 , PCB_FULL_IRET ) ; bcopy ( td0 -> td_frame , td -> td_frame , sizeof ( struct trapframe ) ) ; td -> td_frame -> tf_rflags &= ~ PSL_T ; pcb2 -> pcb_r12 = ( register_t ) fork_return ; pcb2 -> pcb_rbp = 0 ; pcb2 -> pcb_rsp = ( register_t ) td -> td_frame - sizeof ( void * ) ; pcb2 -> pcb_rbx = ( register_t ) td ; pcb2 -> pcb_rip = ( register_t ) fork_trampoline ; td -> td_md . md_spinlock_count = 1 ; td -> td_md . md_saved_flags = PSL_KERNEL | PSL_I ; }
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.
	 */ /*
	 * Create a new fresh stack for the new thread.
	 */ /* If the current thread has the trap bit set (i.e. a debugger had
	 * single stepped the process to the system call), we need to clear
	 * the trap flag from the new frame. Otherwise, the new thread will
	 * receive a (likely unexpected) SIGTRAP when it executes the first
	 * instruction after returning to userland.
	 */ /*
	 * Set registers for trampoline to user mode.  Leave space for the
	 * return address on stack.  These are the kernel mode register values.
	 */ /* trampoline arg */ /* trampoline arg */ /* trampoline arg */ /*
	 * If we didn't copy the pcb, we'd need to do the following registers:
	 * pcb2->pcb_dr*:	cloned above.
	 * pcb2->pcb_savefpu:	cloned above.
	 * pcb2->pcb_onfault:	cloned above (always NULL here?).
	 * pcb2->pcb_[fg]sbase: cloned above
	 */ /* Setup to release spin count in fork_exit(). */