Index: head/sys/amd64/amd64/fpu.c =================================================================== --- head/sys/amd64/amd64/fpu.c +++ head/sys/amd64/amd64/fpu.c @@ -100,6 +100,17 @@ "memory"); } +static __inline void +xsaveopt(char *addr, uint64_t mask) +{ + uint32_t low, hi; + + low = mask; + hi = mask >> 32; + __asm __volatile("xsaveopt %0" : "=m" (*addr) : "a" (low), "d" (hi) : + "memory"); +} + #else /* !(__GNUCLIKE_ASM && !lint) */ void fldcw(u_short cw); @@ -113,6 +124,7 @@ void stmxcsr(u_int *csr); void xrstor(char *addr, uint64_t mask); void xsave(char *addr, uint64_t mask); +void xsaveopt(char *addr, uint64_t mask); #endif /* __GNUCLIKE_ASM && !lint */ @@ -158,6 +170,13 @@ } *xsave_area_desc; static void +fpusave_xsaveopt(void *addr) +{ + + xsaveopt((char *)addr, xsave_mask); +} + +static void fpusave_xsave(void *addr) { @@ -201,7 +220,10 @@ { init_xsave(); - return (use_xsave ? fpusave_xsave : fpusave_fxsave); + if (use_xsave) + return ((cpu_stdext_feature & CPUID_EXTSTATE_XSAVEOPT) != 0 ? + fpusave_xsaveopt : fpusave_xsave); + return (fpusave_fxsave); } DEFINE_IFUNC(, void, fpurestore, (void *), static) @@ -356,7 +378,7 @@ saveintr = intr_disable(); stop_emulating(); - fpusave(fpu_initialstate); + fpusave_fxsave(fpu_initialstate); if (fpu_initialstate->sv_env.en_mxcsr_mask) cpu_mxcsr_mask = fpu_initialstate->sv_env.en_mxcsr_mask; else Index: head/sys/i386/i386/npx.c =================================================================== --- head/sys/i386/i386/npx.c +++ head/sys/i386/i386/npx.c @@ -313,7 +313,7 @@ } static void -npxsave_xsaveopt(union savefpu *addr) +fpusave_xsaveopt(union savefpu *addr) { xsaveopt((char *)addr, xsave_mask); @@ -352,29 +352,18 @@ TUNABLE_INT_FETCH("hw.use_xsave", &use_xsave); } -DEFINE_IFUNC(, void, npxsave_core, (union savefpu *), static) +DEFINE_IFUNC(, void, fpusave, (union savefpu *), static) { init_xsave(); if (use_xsave) return ((cpu_stdext_feature & CPUID_EXTSTATE_XSAVEOPT) != 0 ? - npxsave_xsaveopt : fpusave_xsave); + fpusave_xsaveopt : fpusave_xsave); if (cpu_fxsr) return (fpusave_fxsave); return (fpusave_fnsave); } -DEFINE_IFUNC(, void, fpusave, (union savefpu *), static) -{ - - init_xsave(); - if (use_xsave) - return (fpusave_xsave); - if (cpu_fxsr) - return (fpusave_fxsave); - return (fpusave_fnsave); -} - /* * Enable XSAVE if supported and allowed by user. * Calculate the xsave_mask. @@ -494,7 +483,10 @@ saveintr = intr_disable(); stop_emulating(); - fpusave(npx_initialstate); + if (cpu_fxsr) + fpusave_fxsave(npx_initialstate); + else + fpusave_fnsave(npx_initialstate); if (cpu_fxsr) { if (npx_initialstate->sv_xmm.sv_env.en_mxcsr_mask) cpu_mxcsr_mask = @@ -922,7 +914,7 @@ { stop_emulating(); - npxsave_core(addr); + fpusave(addr); } void npxswitch(struct thread *td, struct pcb *pcb);