* 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. */
| 88 | * ready to run and return to user mode. |
| 89 | */ |
| 90 | void |
| 91 | cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) |
| 92 | { |
| 93 | struct pcb *pcb2; |
| 94 | |
| 95 | if ((flags & RFPROC) == 0) |
| 96 | return; |
| 97 | /* It is assumed that the vm_thread_alloc called |
| 98 | * cpu_thread_alloc() before cpu_fork is called. |
| 99 | */ |
| 100 | |
| 101 | /* Point the pcb to the top of the stack */ |
| 102 | pcb2 = td2->td_pcb; |
| 103 | |
| 104 | /* Copy td1's pcb, note that in this case |
| 105 | * our pcb also includes the td_frame being copied |
| 106 | * too. The older mips2 code did an additional copy |
| 107 | * of the td_frame, for us that's not needed any |
| 108 | * longer (this copy does them both) |
| 109 | */ |
| 110 | bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); |
| 111 | |
| 112 | /* Point mdproc and then copy over td1's contents |
| 113 | * md_proc is empty for MIPS |
| 114 | */ |
| 115 | td2->td_md.md_flags = td1->td_md.md_flags & MDTD_FPUSED; |
| 116 | |
| 117 | /* |
| 118 | * Set up return-value registers as fork() libc stub expects. |
| 119 | */ |
| 120 | td2->td_frame->v0 = 0; |
| 121 | td2->td_frame->v1 = 1; |
| 122 | td2->td_frame->a3 = 0; |
| 123 | |
| 124 | if (td1 == PCPU_GET(fpcurthread)) |
| 125 | MipsSaveCurFPState(td1); |
| 126 | |
| 127 | pcb2->pcb_context[PCB_REG_RA] = (register_t)(intptr_t)fork_trampoline; |
| 128 | /* Make sp 64-bit aligned */ |
| 129 | pcb2->pcb_context[PCB_REG_SP] = (register_t)(((vm_offset_t)td2->td_pcb & |
| 130 | ~(sizeof(__int64_t) - 1)) - CALLFRAME_SIZ); |
| 131 | pcb2->pcb_context[PCB_REG_S0] = (register_t)(intptr_t)fork_return; |
| 132 | pcb2->pcb_context[PCB_REG_S1] = (register_t)(intptr_t)td2; |
| 133 | pcb2->pcb_context[PCB_REG_S2] = (register_t)(intptr_t)td2->td_frame; |
| 134 | pcb2->pcb_context[PCB_REG_SR] = mips_rd_status() & |
| 135 | (MIPS_SR_KX | MIPS_SR_UX | MIPS_SR_INT_MASK); |
| 136 | /* |
| 137 | * FREEBSD_DEVELOPERS_FIXME: |
| 138 | * Setup any other CPU-Specific registers (Not MIPS Standard) |
| 139 | * and/or bits in other standard MIPS registers (if CPU-Specific) |
| 140 | * that are needed. |
| 141 | */ |
| 142 | |
| 143 | td2->td_md.md_tls = td1->td_md.md_tls; |
| 144 | p2->p_md.md_tls_tcb_offset = td1->td_proc->p_md.md_tls_tcb_offset; |
| 145 | td2->td_md.md_saved_intr = MIPS_SR_INT_IE; |
| 146 | td2->td_md.md_spinlock_count = 1; |
| 147 | #ifdef CPU_CNMIPS |
nothing calls this directly
no test coverage detected