The branch stable/13 has been updated by kib:

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

commit b79fb02b32d930b1940ad7a21cb17896c848d432
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2024-03-27 11:01:44 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2024-04-02 15:18:00 +0000

    x86: handle MXCSR from XSAVEOPT when x87 state was optimized
    
    PR:     275322
    
    (cherry picked from commit 1c091d11261a3c8cc3728b92760e65242c0f5949)
---
 sys/amd64/amd64/fpu.c | 21 +++++++++++++++++++++
 sys/i386/i386/npx.c   | 21 +++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 18330cb58d3c..3f06033ae89a 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -875,7 +875,10 @@ fpugetregs(struct thread *td)
        struct pcb *pcb;
        uint64_t *xstate_bv, bit;
        char *sa;
+       struct savefpu *s;
+       uint32_t mxcsr, mxcsr_mask;
        int max_ext_n, i, owned;
+       bool do_mxcsr;
 
        pcb = td->td_pcb;
        critical_enter();
@@ -906,10 +909,28 @@ fpugetregs(struct thread *td)
                        bit = 1ULL << i;
                        if ((xsave_mask & bit) == 0 || (*xstate_bv & bit) != 0)
                                continue;
+                       do_mxcsr = false;
+                       if (i == 0 && (*xstate_bv & (XFEATURE_ENABLED_SSE |
+                           XFEATURE_ENABLED_AVX)) != 0) {
+                               /*
+                                * x87 area was not saved by XSAVEOPT,
+                                * but one of XMM or AVX was.  Then we need
+                                * to preserve MXCSR from being overwritten
+                                * with the default value.
+                                */
+                               s = (struct savefpu *)sa;
+                               mxcsr = s->sv_env.en_mxcsr;
+                               mxcsr_mask = s->sv_env.en_mxcsr_mask;
+                               do_mxcsr = true;
+                       }
                        bcopy((char *)fpu_initialstate +
                            xsave_area_desc[i].offset,
                            sa + xsave_area_desc[i].offset,
                            xsave_area_desc[i].size);
+                       if (do_mxcsr) {
+                               s->sv_env.en_mxcsr = mxcsr;
+                               s->sv_env.en_mxcsr_mask = mxcsr_mask;
+                       }
                        *xstate_bv |= bit;
                }
        }
diff --git a/sys/i386/i386/npx.c b/sys/i386/i386/npx.c
index e7e8fc01fa6b..09abf7c17438 100644
--- a/sys/i386/i386/npx.c
+++ b/sys/i386/i386/npx.c
@@ -1001,8 +1001,11 @@ npxgetregs(struct thread *td)
        struct pcb *pcb;
        uint64_t *xstate_bv, bit;
        char *sa;
+       union savefpu *s;
+       uint32_t mxcsr, mxcsr_mask;
        int max_ext_n, i;
        int owned;
+       bool do_mxcsr;
 
        if (!hw_float)
                return (_MC_FPOWNED_NONE);
@@ -1045,10 +1048,28 @@ npxgetregs(struct thread *td)
                        bit = 1ULL << i;
                        if ((xsave_mask & bit) == 0 || (*xstate_bv & bit) != 0)
                                continue;
+                       do_mxcsr = false;
+                       if (i == 0 && (*xstate_bv & (XFEATURE_ENABLED_SSE |
+                           XFEATURE_ENABLED_AVX)) != 0) {
+                               /*
+                                * x87 area was not saved by XSAVEOPT,
+                                * but one of XMM or AVX was.  Then we need
+                                * to preserve MXCSR from being overwritten
+                                * with the default value.
+                                */
+                               s = (union savefpu *)sa;
+                               mxcsr = s->sv_xmm.sv_env.en_mxcsr;
+                               mxcsr_mask = s->sv_xmm.sv_env.en_mxcsr_mask;
+                               do_mxcsr = true;
+                       }
                        bcopy((char *)npx_initialstate +
                            xsave_area_desc[i].offset,
                            sa + xsave_area_desc[i].offset,
                            xsave_area_desc[i].size);
+                       if (do_mxcsr) {
+                               s->sv_xmm.sv_env.en_mxcsr = mxcsr;
+                               s->sv_xmm.sv_env.en_mxcsr_mask = mxcsr_mask;
+                       }
                        *xstate_bv |= bit;
                }
        }

Reply via email to