The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=755efb8d8fcacc6607bc46469750d78497f89378

commit 755efb8d8fcacc6607bc46469750d78497f89378
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2021-03-12 17:47:41 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2021-03-12 17:47:41 +0000

    x86: Copy the FPU/XSAVE state from the creating thread to new threads.
    
    POSIX states that new threads created via pthread_create() should
    inherit the "floating point environment" from the creating thread.
    
    Discussed with: kib
    MFC after:      1 week
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D29204
---
 sys/amd64/amd64/vm_machdep.c | 10 ++++++----
 sys/i386/i386/vm_machdep.c   | 12 +++++++++---
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 76f7f400dd9c..f10d0339a65a 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -564,16 +564,18 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
 
        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
index d3182cb224bf..502de6e7f38f 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -428,14 +428,21 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
        /* 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 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
        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.
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to