static inline int save_user_xstate(struct xsave_struct __user *buf) { int err; if (use_xsave()) err = xsave_user(buf); else if (use_fxsr()) err = fxsave_user((struct i387_fxsave_struct __user *) buf); else err = fsave_user((struct i387_fsave_struct __user *) buf); if (unlikely(err) && __clear_user(buf, xstate_size)) err = -EFAULT; return err; }
int save_i387_xstate(void __user *buf) { struct task_struct *tsk = current; int err = 0; if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); if (!used_math()) return 0; if (user_has_fpu()) { if (use_xsave()) err = xsave_user(buf); else err = fxsave_user(buf); if (err) return err; user_fpu_end(); } else { sanitize_i387_state(tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, xstate_size)) return -1; } clear_used_math(); /* trigger finit */ if (use_xsave()) { struct _fpstate __user *fx = buf; struct _xstate __user *x = buf; u64 xstate_bv; err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, sizeof(struct _fpx_sw_bytes)); err |= __put_user(FP_XSTATE_MAGIC2, (__u32 __user *) (buf + sig_xstate_size - FP_XSTATE_MAGIC2_SIZE)); /* * Read the xstate_bv which we copied (directly from the cpu or * from the state in task struct) to the user buffers and * set the FP/SSE bits. */ err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); /* * For legacy compatible, we always set FP/SSE bits in the bit * vector while saving the state to the user context. This will * enable us capturing any changes(during sigreturn) to * the FP/SSE bits by the legacy applications which don't touch * xstate_bv in the xsave header. * * xsave aware apps can change the xstate_bv in the xsave * header as well as change any contents in the memory layout. * xrestore as part of sigreturn will capture all the changes. */ xstate_bv |= XSTATE_FPSSE; err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); if (err) return err; } return 1; }
int save_i387_xstate(void __user *buf) { struct task_struct *tsk = current; int err = 0; if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); if (!used_math()) return 0; if (user_has_fpu()) { if (use_xsave()) err = xsave_user(buf); else err = fxsave_user(buf); if (err) return err; user_fpu_end(); } else { sanitize_i387_state(tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, xstate_size)) return -1; } clear_used_math(); /* */ if (use_xsave()) { struct _fpstate __user *fx = buf; struct _xstate __user *x = buf; u64 xstate_bv; err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, sizeof(struct _fpx_sw_bytes)); err |= __put_user(FP_XSTATE_MAGIC2, (__u32 __user *) (buf + sig_xstate_size - FP_XSTATE_MAGIC2_SIZE)); /* */ err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); /* */ xstate_bv |= XSTATE_FPSSE; err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); if (err) return err; } return 1; }