aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/xsave.c
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-10-07 17:04:28 -0400
committerH. Peter Anvin <hpa@zytor.com>2008-10-07 17:36:08 -0400
commit04944b793e18ece23f63c0252646b310c1845940 (patch)
treec8a99e14a910aedcd7147d5ccf2e63be5b26ca0a /arch/x86/kernel/xsave.c
parentf364eadab59b316ea0bd9f9bc01af0ad89065569 (diff)
x86: xsave: set FP, SSE bits in the xsave header in the user sigcontext
If a processor implementation discern that a processor state component is in its initialized state, it may modify the corresponding bit in the xsave header.xstate_bv as '0'. State in the memory layout setup by 'xsave' will be consistent with the bit values in the header. During signal handling, legacy applications may change the FP/SSE bits in the sigcontext memory layout without touching the FP/SSE header bits in the xsave header. So always set FP/SSE bits in the xsave header while saving the sigcontext state to the user space. During signal return, this will enable the kernel to capture any changes to the FP/SSE bits by the legacy applications which don't touch xsave headers. xsave aware apps can change the xstate_bv in the xsave header aswell as change any contents in the memory layout. xrestor as part of sigreturn will capture all the changes. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/xsave.c')
-rw-r--r--arch/x86/kernel/xsave.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 448fde96963c..2f98323716d9 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -114,6 +114,8 @@ int save_i387_xstate(void __user *buf)
114 114
115 if (task_thread_info(tsk)->status & TS_XSAVE) { 115 if (task_thread_info(tsk)->status & TS_XSAVE) {
116 struct _fpstate __user *fx = buf; 116 struct _fpstate __user *fx = buf;
117 struct _xstate __user *x = buf;
118 u64 xstate_bv;
117 119
118 err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, 120 err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
119 sizeof(struct _fpx_sw_bytes)); 121 sizeof(struct _fpx_sw_bytes));
@@ -121,6 +123,29 @@ int save_i387_xstate(void __user *buf)
121 err |= __put_user(FP_XSTATE_MAGIC2, 123 err |= __put_user(FP_XSTATE_MAGIC2,
122 (__u32 __user *) (buf + sig_xstate_size 124 (__u32 __user *) (buf + sig_xstate_size
123 - FP_XSTATE_MAGIC2_SIZE)); 125 - FP_XSTATE_MAGIC2_SIZE));
126
127 /*
128 * Read the xstate_bv which we copied (directly from the cpu or
129 * from the state in task struct) to the user buffers and
130 * set the FP/SSE bits.
131 */
132 err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv);
133
134 /*
135 * For legacy compatible, we always set FP/SSE bits in the bit
136 * vector while saving the state to the user context. This will
137 * enable us capturing any changes(during sigreturn) to
138 * the FP/SSE bits by the legacy applications which don't touch
139 * xstate_bv in the xsave header.
140 *
141 * xsave aware apps can change the xstate_bv in the xsave
142 * header as well as change any contents in the memory layout.
143 * xrestore as part of sigreturn will capture all the changes.
144 */
145 xstate_bv |= XSTATE_FPSSE;
146
147 err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv);
148
124 if (err) 149 if (err)
125 return err; 150 return err;
126 } 151 }