git: 38fdb37047ea - stable/14 - x86: handle MXCSR from XSAVEOPT when x87 state was optimized
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 02 Apr 2024 08:59:43 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=38fdb37047ead625b97b82e8f6532ed7bc404ee3
commit 38fdb37047ead625b97b82e8f6532ed7bc404ee3
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-03-27 11:01:44 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-04-02 08:58:20 +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 63fcf7b0a361..8a0666fc0614 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -853,7 +853,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();
@@ -884,10 +887,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 9cbb1340e9d1..122452598f29 100644
--- a/sys/i386/i386/npx.c
+++ b/sys/i386/i386/npx.c
@@ -977,8 +977,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);
@@ -1021,10 +1024,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;
}
}