/* * Restore the extended state if present. Otherwise, restore the FP/SSE state. */ static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only) { if (use_xsave()) { if ((unsigned long)buf % 64 || fx_only) { u64 init_bv = pcntxt_mask & ~XSTATE_FPSSE; xrstor_state(init_xstate_buf, init_bv); return fxrstor_user(buf); } else { u64 init_bv = pcntxt_mask & ~xbv; if (unlikely(init_bv)) xrstor_state(init_xstate_buf, init_bv); return xrestore_user(buf, xbv); } } else if (use_fxsr()) { return fxrstor_user(buf); } else return frstor_user(buf); }
/* * Restore the extended state if present. Otherwise, restore the FP/SSE * state. */ static int restore_user_xstate(void __user *buf) { struct _fpx_sw_bytes fx_sw_user; u64 mask; int err; if (((unsigned long)buf % 64) || check_for_xstate(buf, buf, &fx_sw_user)) goto fx_only; mask = fx_sw_user.xstate_bv; /* * restore the state passed by the user. */ err = xrestore_user(buf, mask); if (err) return err; /* * init the state skipped by the user. */ mask = pcntxt_mask & ~mask; if (unlikely(mask)) xrstor_state(init_xstate_buf, mask); return 0; fx_only: /* * couldn't find the extended state information in the * memory layout. Restore just the FP/SSE and init all * the other extended state. */ xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); return fxrstor_checking((struct i387_fxsave_struct __force_kernel *)buf); }
static int restore_user_xstate(void __user *buf) { struct _fpx_sw_bytes fx_sw_user; u64 mask; int err; if (((unsigned long)buf % 64) || check_for_xstate(buf, buf, &fx_sw_user)) goto fx_only; mask = fx_sw_user.xstate_bv; /* */ err = xrestore_user(buf, mask); if (err) return err; /* */ mask = pcntxt_mask & ~mask; if (unlikely(mask)) xrstor_state(init_xstate_buf, mask); return 0; fx_only: /* */ xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE); return fxrstor_checking((__force struct i387_fxsave_struct *)buf); }