aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/i387.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/i387.c')
-rw-r--r--arch/x86/kernel/i387.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index f2f8540a7f3d..7a8a193b5144 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -164,6 +164,11 @@ int init_fpu(struct task_struct *tsk)
164 return 0; 164 return 0;
165} 165}
166 166
167/*
168 * The xstateregs_active() routine is the same as the fpregs_active() routine,
169 * as the "regset->n" for the xstate regset will be updated based on the feature
170 * capabilites supported by the xsave.
171 */
167int fpregs_active(struct task_struct *target, const struct user_regset *regset) 172int fpregs_active(struct task_struct *target, const struct user_regset *regset)
168{ 173{
169 return tsk_used_math(target) ? regset->n : 0; 174 return tsk_used_math(target) ? regset->n : 0;
@@ -224,6 +229,84 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
224 return ret; 229 return ret;
225} 230}
226 231
232int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
233 unsigned int pos, unsigned int count,
234 void *kbuf, void __user *ubuf)
235{
236 int ret;
237
238 if (!cpu_has_xsave)
239 return -ENODEV;
240
241 ret = init_fpu(target);
242 if (ret)
243 return ret;
244
245 /*
246 * First copy the fxsave bytes 0..463.
247 */
248 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
249 &target->thread.xstate->xsave, 0,
250 offsetof(struct user_xstateregs,
251 i387.xstate_fx_sw));
252 if (ret)
253 return ret;
254
255 /*
256 * Copy the 48bytes defined by software.
257 */
258 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
259 xstate_fx_sw_bytes,
260 offsetof(struct user_xstateregs,
261 i387.xstate_fx_sw),
262 offsetof(struct user_xstateregs,
263 xsave_hdr));
264 if (ret)
265 return ret;
266
267 /*
268 * Copy the rest of xstate memory layout.
269 */
270 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
271 &target->thread.xstate->xsave.xsave_hdr,
272 offsetof(struct user_xstateregs,
273 xsave_hdr), -1);
274 return ret;
275}
276
277int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
278 unsigned int pos, unsigned int count,
279 const void *kbuf, const void __user *ubuf)
280{
281 int ret;
282 struct xsave_hdr_struct *xsave_hdr;
283
284 if (!cpu_has_xsave)
285 return -ENODEV;
286
287 ret = init_fpu(target);
288 if (ret)
289 return ret;
290
291 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
292 &target->thread.xstate->xsave, 0, -1);
293
294 /*
295 * mxcsr reserved bits must be masked to zero for security reasons.
296 */
297 target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
298
299 xsave_hdr = &target->thread.xstate->xsave.xsave_hdr;
300
301 xsave_hdr->xstate_bv &= pcntxt_mask;
302 /*
303 * These bits must be zero.
304 */
305 xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
306
307 return ret;
308}
309
227#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION 310#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
228 311
229/* 312/*