aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/i387.c
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2010-07-19 19:05:49 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2010-07-19 20:51:30 -0400
commit29104e101d710dd152f807978884643a52eca8b7 (patch)
tree03ab625528d91ad13d60a817c7885591fea197b3 /arch/x86/kernel/i387.c
parenta1488f8bf4d72ad724700f6e982469a1240e4264 (diff)
x86, xsave: Sync xsave memory layout with its header for user handling
With xsaveopt, if a processor implementation discern that a processor state component is in its initialized state it may modify the corresponding bit in the xsave_hdr.xstate_bv as '0', with out modifying the corresponding memory layout. Hence wHile presenting the xstate information to the user, we always ensure that the memory layout of a feature will be in the init state if the corresponding header bit is zero. This ensures the consistency and avoids the condition of the user seeing some some stale state in the memory layout during signal handling, debugging etc. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <20100719230205.351459480@sbs-t61.sc.intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel/i387.c')
-rw-r--r--arch/x86/kernel/i387.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 86cef6b32253..6106af9fd129 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -190,6 +190,8 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
190 if (ret) 190 if (ret)
191 return ret; 191 return ret;
192 192
193 sanitize_i387_state(target);
194
193 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 195 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
194 &target->thread.fpu.state->fxsave, 0, -1); 196 &target->thread.fpu.state->fxsave, 0, -1);
195} 197}
@@ -207,6 +209,8 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
207 if (ret) 209 if (ret)
208 return ret; 210 return ret;
209 211
212 sanitize_i387_state(target);
213
210 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 214 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
211 &target->thread.fpu.state->fxsave, 0, -1); 215 &target->thread.fpu.state->fxsave, 0, -1);
212 216
@@ -446,6 +450,8 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
446 -1); 450 -1);
447 } 451 }
448 452
453 sanitize_i387_state(target);
454
449 if (kbuf && pos == 0 && count == sizeof(env)) { 455 if (kbuf && pos == 0 && count == sizeof(env)) {
450 convert_from_fxsr(kbuf, target); 456 convert_from_fxsr(kbuf, target);
451 return 0; 457 return 0;
@@ -467,6 +473,8 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
467 if (ret) 473 if (ret)
468 return ret; 474 return ret;
469 475
476 sanitize_i387_state(target);
477
470 if (!HAVE_HWFP) 478 if (!HAVE_HWFP)
471 return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf); 479 return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
472 480
@@ -533,6 +541,9 @@ static int save_i387_xsave(void __user *buf)
533 struct _fpstate_ia32 __user *fx = buf; 541 struct _fpstate_ia32 __user *fx = buf;
534 int err = 0; 542 int err = 0;
535 543
544
545 sanitize_i387_state(tsk);
546
536 /* 547 /*
537 * For legacy compatible, we always set FP/SSE bits in the bit 548 * For legacy compatible, we always set FP/SSE bits in the bit
538 * vector while saving the state to the user context. 549 * vector while saving the state to the user context.