/* * 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); }
/* * setup the xstate image representing the init state */ static void __init setup_xstate_init(void) { setup_xstate_features(); /* * Setup init_xstate_buf to represent the init state of * all the features managed by the xsave */ init_xstate_buf = alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct)); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; clts(); /* * Init all the features state with header_bv being 0x0 */ xrstor_state(init_xstate_buf, -1); /* * Dump the init state again. This is to identify the init state * of any feature which is not represented by all zero's. */ xsave_state(init_xstate_buf, -1); stts(); }
static void __init setup_xstate_init(void) { setup_xstate_features(); /* */ init_xstate_buf = alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct)); init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; clts(); /* */ xrstor_state(init_xstate_buf, -1); /* */ xsave_state(init_xstate_buf, -1); stts(); }