diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -564,16 +564,18 @@ pcb2 = td->td_pcb; + /* Ensure that td0's pcb is up to date. */ + fpuexit(td0); + if (td0 == curthread) + update_pcb_bases(td0->td_pcb); + /* * Copy the upcall pcb. This loads kernel regs. * Those not loaded individually below get their default * values here. */ - if (td0 == curthread) - update_pcb_bases(td0->td_pcb); bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); - clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE | - PCB_KERNFPU); + clear_pcb_flags(pcb2, 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); diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -428,14 +428,21 @@ /* Point the pcb to the top of the stack. */ pcb2 = td->td_pcb; + /* Ensure that td0's pcb is up to date. */ + if (td0 == curthread) + td0->td_pcb->pcb_gs = rgs(); + critical_enter(); + if (PCPU_GET(fpcurthread) == td0) + npxsave(td0->td_pcb->pcb_save); + critical_exit(); + /* * Copy the upcall pcb. This loads kernel regs. * Those not loaded individually below get their default * values here. */ bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); - pcb2->pcb_flags &= ~(PCB_NPXINITDONE | PCB_NPXUSERINITDONE | - PCB_KERNNPX); + pcb2->pcb_flags &= ~PCB_KERNNPX; pcb2->pcb_save = get_pcb_user_save_pcb(pcb2); bcopy(get_pcb_user_save_td(td0), pcb2->pcb_save, cpu_max_ext_state_size); @@ -463,7 +470,6 @@ pcb2->pcb_esp = (int)td->td_frame - sizeof(void *); /* trampoline arg */ pcb2->pcb_ebx = (int)td; /* trampoline arg */ pcb2->pcb_eip = (int)fork_trampoline + setidt_disp; - pcb2->pcb_gs = rgs(); /* * If we didn't copy the pcb, we'd need to do the following registers: * pcb2->pcb_cr3: cloned above.