diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 06a7d5df9d75..513b36b7d0b0 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -125,6 +125,10 @@ fpuinit(void) mxcsr = __INITIAL_MXCSR__; ldmxcsr(mxcsr); fxsave(&fpu_cleanstate); + if (fpu_cleanstate.sv_env.en_mxcsr_mask) + cpu_mxcsr_mask = fpu_cleanstate.sv_env.en_mxcsr_mask; + else + cpu_mxcsr_mask = 0xFFBF; start_emulating(); bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp)); bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm)); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 026046218937..43c19d39e0ca 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1507,7 +1507,7 @@ set_fpregs_xmm(struct fpreg *fpregs, struct savefpu *sv_xmm) penv_xmm->en_rip = penv_fpreg->en_rip; penv_xmm->en_rdp = penv_fpreg->en_rdp; penv_xmm->en_mxcsr = penv_fpreg->en_mxcsr; - penv_xmm->en_mxcsr_mask = penv_fpreg->en_mxcsr_mask; + penv_xmm->en_mxcsr_mask = penv_fpreg->en_mxcsr_mask & cpu_mxcsr_mask; /* FPU registers */ for (i = 0; i < 8; ++i) @@ -1634,6 +1634,7 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) static int set_fpcontext(struct thread *td, const mcontext_t *mcp) { + struct savefpu *fpstate; if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); @@ -1649,7 +1650,9 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) * be called with interrupts disabled. * XXX obsolete on trap-16 systems? */ - fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate); + fpstate = (struct savefpu *)&mcp->mc_fpstate; + fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask; + fpusetregs(td, fpstate); } else return (EINVAL); return (0); diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 4e421eea1654..03220e6a0640 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -47,6 +47,7 @@ extern u_int amd_feature2; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; +extern u_int cpu_mxcsr_mask; extern u_int cpu_procinfo; extern u_int cpu_procinfo2; extern char cpu_vendor[];