Mercurial > illumos > illumos-gate
diff usr/src/uts/intel/ia32/os/archdep.c @ 13146:8315ff49e22e
6958308 XSAVE/XRSTOR mechanism to save and restore processor state
Contributed by Lejun Zhu <lejun.zhu@intel.com>
author | Kuriakose Kuruvilla <kuriakose.kuruvilla@oracle.com> |
---|---|
date | Mon, 16 Aug 2010 19:36:08 -0700 |
parents | ab9ae749152f |
children | 2b3b7ee313ef |
line wrap: on
line diff
--- a/usr/src/uts/intel/ia32/os/archdep.c Mon Aug 16 18:05:48 2010 -0700 +++ b/usr/src/uts/intel/ia32/os/archdep.c Mon Aug 16 19:36:08 2010 -0700 @@ -62,6 +62,7 @@ #include <sys/dtrace.h> #include <sys/brand.h> #include <sys/machbrand.h> +#include <sys/cmn_err.h> extern const struct fnsave_state x87_initial; extern const struct fxsave_state sse_initial; @@ -278,41 +279,43 @@ */ fp_free(fpu, 0); } -#if !defined(__amd64) - if (fp_kind == __FP_SSE) { -#endif - fpregset_to_fxsave(fp, &fpu->fpu_regs.kfpu_u.kfpu_fx); - fpu->fpu_regs.kfpu_xstatus = - fp->fp_reg_set.fpchip_state.xstatus; -#if !defined(__amd64) - } else - bcopy(fp, &fpu->fpu_regs.kfpu_u.kfpu_fn, - sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); + } + /* + * Else: if we are trying to change the FPU state of a thread which + * hasn't yet initialized floating point, store the state in + * the pcb and indicate that the state is valid. When the + * thread enables floating point, it will use this state instead + * of the default state. + */ + + switch (fp_save_mech) { +#if defined(__i386) + case FP_FNSAVE: + bcopy(fp, &fpu->fpu_regs.kfpu_u.kfpu_fn, + sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); + break; #endif - fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; - fpu->fpu_flags |= FPU_VALID; - } else { - /* - * If we are trying to change the FPU state of a thread which - * hasn't yet initialized floating point, store the state in - * the pcb and indicate that the state is valid. When the - * thread enables floating point, it will use this state instead - * of the default state. - */ -#if !defined(__amd64) - if (fp_kind == __FP_SSE) { -#endif - fpregset_to_fxsave(fp, &fpu->fpu_regs.kfpu_u.kfpu_fx); - fpu->fpu_regs.kfpu_xstatus = - fp->fp_reg_set.fpchip_state.xstatus; -#if !defined(__amd64) - } else - bcopy(fp, &fpu->fpu_regs.kfpu_u.kfpu_fn, - sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); -#endif - fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; - fpu->fpu_flags |= FPU_VALID; + case FP_FXSAVE: + fpregset_to_fxsave(fp, &fpu->fpu_regs.kfpu_u.kfpu_fx); + fpu->fpu_regs.kfpu_xstatus = + fp->fp_reg_set.fpchip_state.xstatus; + break; + + case FP_XSAVE: + fpregset_to_fxsave(fp, + &fpu->fpu_regs.kfpu_u.kfpu_xs.xs_fxsave); + fpu->fpu_regs.kfpu_xstatus = + fp->fp_reg_set.fpchip_state.xstatus; + fpu->fpu_regs.kfpu_u.kfpu_xs.xs_xstate_bv |= + (XFEATURE_LEGACY_FP | XFEATURE_SSE); + break; + default: + panic("Invalid fp_save_mech"); + /*NOTREACHED*/ } + + fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; + fpu->fpu_flags |= FPU_VALID; } /* @@ -349,32 +352,54 @@ /* * Cases 1 and 3. */ -#if !defined(__amd64) - if (fp_kind == __FP_SSE) { + switch (fp_save_mech) { +#if defined(__i386) + case FP_FNSAVE: + bcopy(&fpu->fpu_regs.kfpu_u.kfpu_fn, fp, + sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); + break; #endif + case FP_FXSAVE: fxsave_to_fpregset(&fpu->fpu_regs.kfpu_u.kfpu_fx, fp); fp->fp_reg_set.fpchip_state.xstatus = fpu->fpu_regs.kfpu_xstatus; -#if !defined(__amd64) - } else - bcopy(&fpu->fpu_regs.kfpu_u.kfpu_fn, fp, - sizeof (fpu->fpu_regs.kfpu_u.kfpu_fn)); -#endif + break; + case FP_XSAVE: + fxsave_to_fpregset( + &fpu->fpu_regs.kfpu_u.kfpu_xs.xs_fxsave, fp); + fp->fp_reg_set.fpchip_state.xstatus = + fpu->fpu_regs.kfpu_xstatus; + break; + default: + panic("Invalid fp_save_mech"); + /*NOTREACHED*/ + } fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; } else { /* * Case 2. */ -#if !defined(__amd64) - if (fp_kind == __FP_SSE) { + switch (fp_save_mech) { +#if defined(__i386) + case FP_FNSAVE: + bcopy(&x87_initial, fp, sizeof (x87_initial)); + break; #endif + case FP_FXSAVE: + case FP_XSAVE: + /* + * For now, we don't have any AVX specific field in ABI. + * If we add any in the future, we need to initial them + * as well. + */ fxsave_to_fpregset(&sse_initial, fp); fp->fp_reg_set.fpchip_state.xstatus = fpu->fpu_regs.kfpu_xstatus; -#if !defined(__amd64) - } else - bcopy(&x87_initial, fp, sizeof (x87_initial)); -#endif + break; + default: + panic("Invalid fp_save_mech"); + /*NOTREACHED*/ + } fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; } kpreempt_enable();