* 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. */
| 65 | * ready to run and return to user mode. |
| 66 | */ |
| 67 | void |
| 68 | cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) |
| 69 | { |
| 70 | struct pcb *pcb2; |
| 71 | struct trapframe *tf; |
| 72 | |
| 73 | if ((flags & RFPROC) == 0) |
| 74 | return; |
| 75 | |
| 76 | if (td1 == curthread) { |
| 77 | /* |
| 78 | * Save the tpidr_el0 and the vfp state, these normally happen |
| 79 | * in cpu_switch, but if userland changes these then forks |
| 80 | * this may not have happened. |
| 81 | */ |
| 82 | td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0); |
| 83 | td1->td_pcb->pcb_tpidrro_el0 = READ_SPECIALREG(tpidrro_el0); |
| 84 | #ifdef VFP |
| 85 | if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0) |
| 86 | vfp_save_state(td1, td1->td_pcb); |
| 87 | #endif |
| 88 | } |
| 89 | |
| 90 | pcb2 = (struct pcb *)(td2->td_kstack + |
| 91 | td2->td_kstack_pages * PAGE_SIZE) - 1; |
| 92 | |
| 93 | td2->td_pcb = pcb2; |
| 94 | bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); |
| 95 | |
| 96 | tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1); |
| 97 | bcopy(td1->td_frame, tf, sizeof(*tf)); |
| 98 | tf->tf_x[0] = 0; |
| 99 | tf->tf_x[1] = 0; |
| 100 | tf->tf_spsr = td1->td_frame->tf_spsr & (PSR_M_32 | PSR_DAIF); |
| 101 | |
| 102 | td2->td_frame = tf; |
| 103 | |
| 104 | /* Set the return value registers for fork() */ |
| 105 | td2->td_pcb->pcb_x[8] = (uintptr_t)fork_return; |
| 106 | td2->td_pcb->pcb_x[9] = (uintptr_t)td2; |
| 107 | td2->td_pcb->pcb_lr = (uintptr_t)fork_trampoline; |
| 108 | td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame; |
| 109 | td2->td_pcb->pcb_fpusaved = &td2->td_pcb->pcb_fpustate; |
| 110 | td2->td_pcb->pcb_vfpcpu = UINT_MAX; |
| 111 | td2->td_pcb->pcb_fpusaved->vfp_fpcr = initial_fpcr; |
| 112 | |
| 113 | /* Setup to release spin count in fork_exit(). */ |
| 114 | td2->td_md.md_spinlock_count = 1; |
| 115 | td2->td_md.md_saved_daif = td1->td_md.md_saved_daif & ~DAIF_I_MASKED; |
| 116 | } |
| 117 | |
| 118 | void |
| 119 | cpu_reset(void) |
nothing calls this directly
no test coverage detected