Date: Mon, 29 Jun 2015 12:06:37 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284926 - in head/sys/i386: i386 include isa Message-ID: <201506291206.t5TC6b2w088731@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Mon Jun 29 12:06:36 2015 New Revision: 284926 URL: https://svnweb.freebsd.org/changeset/base/284926 Log: Provide npx_get_fsave(9) and npx_set_fsave(9) functions to obtain and restore the FPU state from the format of machine FSAVE area. The intended use is for ABI emulators to provide FSAVE-formatted FPU state to usermode requiring it, while kernel could use FXSAVE due to XMM/XSAVE. The core functionality to convert from/to FXSAVE format is shared with the fill_fpregs_xmm() and set_fpregs_xmm(). Move the later functions to npx.c and rename them to npx_fill_fpregs_xmm() and npx_set_fpregs_xmm(). They differ from nptx_get/set_fsave(9) since our mcontext contains padding to be zeroed or ignored. fill_fpregs() and set_fpregs() could be converted to use the new interface, but there are small differences to handle. Sponsored by: The FreeBSD Foundation MFC after: 1 week Modified: head/sys/i386/i386/machdep.c head/sys/i386/include/npx.h head/sys/i386/isa/npx.c Modified: head/sys/i386/i386/machdep.c ============================================================================== --- head/sys/i386/i386/machdep.c Mon Jun 29 10:35:00 2015 (r284925) +++ head/sys/i386/i386/machdep.c Mon Jun 29 12:06:36 2015 (r284926) @@ -176,10 +176,6 @@ static void get_fpcontext(struct thread char *xfpusave, size_t xfpusave_len); static int set_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpustate, size_t xfpustate_len); -#ifdef CPU_ENABLE_SSE -static void set_fpregs_xmm(struct save87 *, struct savexmm *); -static void fill_fpregs_xmm(struct savexmm *, struct save87 *); -#endif /* CPU_ENABLE_SSE */ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); /* Intel ICH registers */ @@ -2952,58 +2948,6 @@ set_regs(struct thread *td, struct reg * return (0); } -#ifdef CPU_ENABLE_SSE -static void -fill_fpregs_xmm(sv_xmm, sv_87) - struct savexmm *sv_xmm; - struct save87 *sv_87; -{ - register struct env87 *penv_87 = &sv_87->sv_env; - register struct envxmm *penv_xmm = &sv_xmm->sv_env; - int i; - - bzero(sv_87, sizeof(*sv_87)); - - /* FPU control/status */ - penv_87->en_cw = penv_xmm->en_cw; - penv_87->en_sw = penv_xmm->en_sw; - penv_87->en_tw = penv_xmm->en_tw; - penv_87->en_fip = penv_xmm->en_fip; - penv_87->en_fcs = penv_xmm->en_fcs; - penv_87->en_opcode = penv_xmm->en_opcode; - penv_87->en_foo = penv_xmm->en_foo; - penv_87->en_fos = penv_xmm->en_fos; - - /* FPU registers */ - for (i = 0; i < 8; ++i) - sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc; -} - -static void -set_fpregs_xmm(sv_87, sv_xmm) - struct save87 *sv_87; - struct savexmm *sv_xmm; -{ - register struct env87 *penv_87 = &sv_87->sv_env; - register struct envxmm *penv_xmm = &sv_xmm->sv_env; - int i; - - /* FPU control/status */ - penv_xmm->en_cw = penv_87->en_cw; - penv_xmm->en_sw = penv_87->en_sw; - penv_xmm->en_tw = penv_87->en_tw; - penv_xmm->en_fip = penv_87->en_fip; - penv_xmm->en_fcs = penv_87->en_fcs; - penv_xmm->en_opcode = penv_87->en_opcode; - penv_xmm->en_foo = penv_87->en_foo; - penv_xmm->en_fos = penv_87->en_fos; - - /* FPU registers */ - for (i = 0; i < 8; ++i) - sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i]; -} -#endif /* CPU_ENABLE_SSE */ - int fill_fpregs(struct thread *td, struct fpreg *fpregs) { @@ -3018,7 +2962,7 @@ fill_fpregs(struct thread *td, struct fp #endif #ifdef CPU_ENABLE_SSE if (cpu_fxsr) - fill_fpregs_xmm(&get_pcb_user_save_td(td)->sv_xmm, + npx_fill_fpregs_xmm(&get_pcb_user_save_td(td)->sv_xmm, (struct save87 *)fpregs); else #endif /* CPU_ENABLE_SSE */ @@ -3033,7 +2977,7 @@ set_fpregs(struct thread *td, struct fpr #ifdef CPU_ENABLE_SSE if (cpu_fxsr) - set_fpregs_xmm((struct save87 *)fpregs, + npx_set_fpregs_xmm((struct save87 *)fpregs, &get_pcb_user_save_td(td)->sv_xmm); else #endif /* CPU_ENABLE_SSE */ Modified: head/sys/i386/include/npx.h ============================================================================== --- head/sys/i386/include/npx.h Mon Jun 29 10:35:00 2015 (r284925) +++ head/sys/i386/include/npx.h Mon Jun 29 12:06:36 2015 (r284926) @@ -67,6 +67,11 @@ void npxsuspend(union savefpu *addr); int npxtrap_x87(void); int npxtrap_sse(void); void npxuserinited(struct thread *); +void npx_get_fsave(void *); +int npx_set_fsave(void *); +void npx_fill_fpregs_xmm(struct savexmm *, struct save87 *); +void npx_set_fpregs_xmm(struct save87 *, struct savexmm *); + struct fpu_kern_ctx *fpu_kern_alloc_ctx(u_int flags); void fpu_kern_free_ctx(struct fpu_kern_ctx *ctx); int fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, Modified: head/sys/i386/isa/npx.c ============================================================================== --- head/sys/i386/isa/npx.c Mon Jun 29 10:35:00 2015 (r284925) +++ head/sys/i386/isa/npx.c Mon Jun 29 12:06:36 2015 (r284926) @@ -1160,6 +1160,102 @@ fpusave(addr) } #ifdef CPU_ENABLE_SSE +static void +npx_fill_fpregs_xmm1(struct savexmm *sv_xmm, struct save87 *sv_87) +{ + struct env87 *penv_87; + struct envxmm *penv_xmm; + int i; + + penv_87 = &sv_87->sv_env; + penv_xmm = &sv_xmm->sv_env; + + /* FPU control/status */ + penv_87->en_cw = penv_xmm->en_cw; + penv_87->en_sw = penv_xmm->en_sw; + penv_87->en_tw = penv_xmm->en_tw; + penv_87->en_fip = penv_xmm->en_fip; + penv_87->en_fcs = penv_xmm->en_fcs; + penv_87->en_opcode = penv_xmm->en_opcode; + penv_87->en_foo = penv_xmm->en_foo; + penv_87->en_fos = penv_xmm->en_fos; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc; +} + +void +npx_fill_fpregs_xmm(struct savexmm *sv_xmm, struct save87 *sv_87) +{ + + bzero(sv_87, sizeof(*sv_87)); + npx_fill_fpregs_xmm1(sv_xmm, sv_87); +} + +void +npx_set_fpregs_xmm(struct save87 *sv_87, struct savexmm *sv_xmm) +{ + struct env87 *penv_87; + struct envxmm *penv_xmm; + int i; + + penv_87 = &sv_87->sv_env; + penv_xmm = &sv_xmm->sv_env; + + /* FPU control/status */ + penv_xmm->en_cw = penv_87->en_cw; + penv_xmm->en_sw = penv_87->en_sw; + penv_xmm->en_tw = penv_87->en_tw; + penv_xmm->en_fip = penv_87->en_fip; + penv_xmm->en_fcs = penv_87->en_fcs; + penv_xmm->en_opcode = penv_87->en_opcode; + penv_xmm->en_foo = penv_87->en_foo; + penv_xmm->en_fos = penv_87->en_fos; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i]; +} +#endif /* CPU_ENABLE_SSE */ + +void +npx_get_fsave(void *addr) +{ + struct thread *td; + union savefpu *sv; + + td = curthread; + npxgetregs(td); + sv = get_pcb_user_save_td(td); +#ifdef CPU_ENABLE_SSE + if (cpu_fxsr) + npx_fill_fpregs_xmm1(&sv->sv_xmm, addr); + else +#endif + bcopy(sv, addr, sizeof(struct env87) + + sizeof(struct fpacc87[8])); +} + +int +npx_set_fsave(void *addr) +{ + union savefpu sv; + int error; + + bzero(&sv, sizeof(sv)); +#ifdef CPU_ENABLE_SSE + if (cpu_fxsr) + npx_set_fpregs_xmm(addr, &sv.sv_xmm); + else +#endif + bcopy(addr, &sv, sizeof(struct env87) + + sizeof(struct fpacc87[8])); + error = npxsetregs(curthread, &sv, NULL, 0); + return (error); +} + +#ifdef CPU_ENABLE_SSE /* * On AuthenticAMD processors, the fxrstor instruction does not restore * the x87's stored last instruction pointer, last data pointer, and last
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506291206.t5TC6b2w088731>