* 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. */
| 557 | * return to userspace for the new thread. |
| 558 | */ |
| 559 | void |
| 560 | cpu_copy_thread(struct thread *td, struct thread *td0) |
| 561 | { |
| 562 | struct pcb *pcb2; |
| 563 | |
| 564 | pcb2 = td->td_pcb; |
| 565 | |
| 566 | /* |
| 567 | * Copy the upcall pcb. This loads kernel regs. |
| 568 | * Those not loaded individually below get their default |
| 569 | * values here. |
| 570 | */ |
| 571 | update_pcb_bases(td0->td_pcb); |
| 572 | bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); |
| 573 | clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE | |
| 574 | PCB_KERNFPU); |
| 575 | pcb2->pcb_save = get_pcb_user_save_pcb(pcb2); |
| 576 | bcopy(get_pcb_user_save_td(td0), pcb2->pcb_save, |
| 577 | cpu_max_ext_state_size); |
| 578 | set_pcb_flags_raw(pcb2, PCB_FULL_IRET); |
| 579 | |
| 580 | /* |
| 581 | * Create a new fresh stack for the new thread. |
| 582 | */ |
| 583 | bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); |
| 584 | |
| 585 | /* If the current thread has the trap bit set (i.e. a debugger had |
| 586 | * single stepped the process to the system call), we need to clear |
| 587 | * the trap flag from the new frame. Otherwise, the new thread will |
| 588 | * receive a (likely unexpected) SIGTRAP when it executes the first |
| 589 | * instruction after returning to userland. |
| 590 | */ |
| 591 | td->td_frame->tf_rflags &= ~PSL_T; |
| 592 | |
| 593 | /* |
| 594 | * Set registers for trampoline to user mode. Leave space for the |
| 595 | * return address on stack. These are the kernel mode register values. |
| 596 | */ |
| 597 | pcb2->pcb_r12 = (register_t)fork_return; /* trampoline arg */ |
| 598 | pcb2->pcb_rbp = 0; |
| 599 | pcb2->pcb_rsp = (register_t)td->td_frame - sizeof(void *); /* trampoline arg */ |
| 600 | pcb2->pcb_rbx = (register_t)td; /* trampoline arg */ |
| 601 | pcb2->pcb_rip = (register_t)fork_trampoline; |
| 602 | /* |
| 603 | * If we didn't copy the pcb, we'd need to do the following registers: |
| 604 | * pcb2->pcb_dr*: cloned above. |
| 605 | * pcb2->pcb_savefpu: cloned above. |
| 606 | * pcb2->pcb_onfault: cloned above (always NULL here?). |
| 607 | * pcb2->pcb_[fg]sbase: cloned above |
| 608 | */ |
| 609 | |
| 610 | /* Setup to release spin count in fork_exit(). */ |
| 611 | td->td_md.md_spinlock_count = 1; |
| 612 | td->td_md.md_saved_flags = PSL_KERNEL | PSL_I; |
| 613 | pmap_thread_init_invl_gen(td); |
| 614 | } |
| 615 | |
| 616 | /* |
nothing calls this directly
no test coverage detected