aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/xsave.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/xsave.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/xsave.c')
-rw-r--r--arch/x86/kernel/xsave.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 4993caa4181c..368047c8d507 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -24,6 +24,76 @@ struct _fpx_sw_bytes fx_sw_reserved_ia32;
24static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; 24static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
25 25
26/* 26/*
27 * If a processor implementation discern that a processor state component is
28 * in its initialized state it may modify the corresponding bit in the
29 * xsave_hdr.xstate_bv as '0', with out modifying the corresponding memory
30 * layout in the case of xsaveopt. While presenting the xstate information to
31 * the user, we always ensure that the memory layout of a feature will be in
32 * the init state if the corresponding header bit is zero. This is to ensure
33 * that the user doesn't see some stale state in the memory layout during
34 * signal handling, debugging etc.
35 */
36void __sanitize_i387_state(struct task_struct *tsk)
37{
38 u64 xstate_bv;
39 int feature_bit = 0x2;
40 struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave;
41
42 if (!fx)
43 return;
44
45 BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU);
46
47 xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
48
49 /*
50 * None of the feature bits are in init state. So nothing else
51 * to do for us, as the memory layout is upto date.
52 */
53 if ((xstate_bv & pcntxt_mask) == pcntxt_mask)
54 return;
55
56 /*
57 * FP is in init state
58 */
59 if (!(xstate_bv & XSTATE_FP)) {
60 fx->cwd = 0x37f;
61 fx->swd = 0;
62 fx->twd = 0;
63 fx->fop = 0;
64 fx->rip = 0;
65 fx->rdp = 0;
66 memset(&fx->st_space[0], 0, 128);
67 }
68
69 /*
70 * SSE is in init state
71 */
72 if (!(xstate_bv & XSTATE_SSE))
73 memset(&fx->xmm_space[0], 0, 256);
74
75 xstate_bv = (pcntxt_mask & ~xstate_bv) >> 2;
76
77 /*
78 * Update all the other memory layouts for which the corresponding
79 * header bit is in the init state.
80 */
81 while (xstate_bv) {
82 if (xstate_bv & 0x1) {
83 int offset = xstate_offsets[feature_bit];
84 int size = xstate_sizes[feature_bit];
85
86 memcpy(((void *) fx) + offset,
87 ((void *) init_xstate_buf) + offset,
88 size);
89 }
90
91 xstate_bv >>= 1;
92 feature_bit++;
93 }
94}
95
96/*
27 * Check for the presence of extended state information in the 97 * Check for the presence of extended state information in the
28 * user fpstate pointer in the sigcontext. 98 * user fpstate pointer in the sigcontext.
29 */ 99 */
@@ -112,6 +182,7 @@ int save_i387_xstate(void __user *buf)
112 task_thread_info(tsk)->status &= ~TS_USEDFPU; 182 task_thread_info(tsk)->status &= ~TS_USEDFPU;
113 stts(); 183 stts();
114 } else { 184 } else {
185 sanitize_i387_state(tsk);
115 if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, 186 if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
116 xstate_size)) 187 xstate_size))
117 return -1; 188 return -1;
@@ -333,10 +404,26 @@ static void setup_xstate_features(void)
333 */ 404 */
334static void __init setup_xstate_init(void) 405static void __init setup_xstate_init(void)
335{ 406{
407 setup_xstate_features();
408
409 /*
410 * Setup init_xstate_buf to represent the init state of
411 * all the features managed by the xsave
412 */
336 init_xstate_buf = alloc_bootmem(xstate_size); 413 init_xstate_buf = alloc_bootmem(xstate_size);
337 init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT; 414 init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
338 415
339 setup_xstate_features(); 416 clts();
417 /*
418 * Init all the features state with header_bv being 0x0
419 */
420 xrstor_state(init_xstate_buf, -1);
421 /*
422 * Dump the init state again. This is to identify the init state
423 * of any feature which is not represented by all zero's.
424 */
425 xsave_state(init_xstate_buf, -1);
426 stts();
340} 427}
341 428
342/* 429/*