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
This commit is contained in:
parent
f9343dacbd
commit
b24de3ac40
@ -176,10 +176,6 @@ static void get_fpcontext(struct thread *td, mcontext_t *mcp,
|
||||
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 *regs)
|
||||
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 fpreg *fpregs)
|
||||
#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 fpreg *fpregs)
|
||||
|
||||
#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 */
|
||||
|
@ -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,
|
||||
|
@ -1159,6 +1159,102 @@ fpusave(addr)
|
||||
fnsave(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
|
||||
|
Loading…
Reference in New Issue
Block a user