git: 1ebb5d7920fe - stable/13 - x86: Copy the FPU/XSAVE state from the creating thread to new threads.
John Baldwin
jhb at FreeBSD.org
Mon Mar 29 22:12:00 UTC 2021
The branch stable/13 has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=1ebb5d7920fea1b8bb849d07bf930bd579f0695c
commit 1ebb5d7920fea1b8bb849d07bf930bd579f0695c
Author: John Baldwin <jhb at FreeBSD.org>
AuthorDate: 2021-03-12 17:47:41 +0000
Commit: John Baldwin <jhb at FreeBSD.org>
CommitDate: 2021-03-29 18:10:37 +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.
Sponsored by: Netflix
(cherry picked from commit 755efb8d8fcacc6607bc46469750d78497f89378)
---
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.
More information about the dev-commits-src-all
mailing list