diff options
| author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-10-07 17:04:28 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-07 17:36:08 -0400 |
| commit | 04944b793e18ece23f63c0252646b310c1845940 (patch) | |
| tree | c8a99e14a910aedcd7147d5ccf2e63be5b26ca0a | |
| parent | f364eadab59b316ea0bd9f9bc01af0ad89065569 (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>
| -rw-r--r-- | arch/x86/kernel/i387.c | 14 | ||||
| -rw-r--r-- | arch/x86/kernel/xsave.c | 25 |
2 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 45723f1fe198..1f20608d4ca8 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
| @@ -468,9 +468,23 @@ static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
| 468 | 468 | ||
| 469 | static int save_i387_xsave(void __user *buf) | 469 | static int save_i387_xsave(void __user *buf) |
| 470 | { | 470 | { |
| 471 | struct task_struct *tsk = current; | ||
| 471 | struct _fpstate_ia32 __user *fx = buf; | 472 | struct _fpstate_ia32 __user *fx = buf; |
| 472 | int err = 0; | 473 | int err = 0; |
| 473 | 474 | ||
| 475 | /* | ||
| 476 | * For legacy compatible, we always set FP/SSE bits in the bit | ||
| 477 | * vector while saving the state to the user context. | ||
| 478 | * This will enable us capturing any changes(during sigreturn) to | ||
| 479 | * the FP/SSE bits by the legacy applications which don't touch | ||
| 480 | * xstate_bv in the xsave header. | ||
| 481 | * | ||
| 482 | * xsave aware applications can change the xstate_bv in the xsave | ||
| 483 | * header as well as change any contents in the memory layout. | ||
| 484 | * xrestore as part of sigreturn will capture all the changes. | ||
| 485 | */ | ||
| 486 | tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; | ||
| 487 | |||
| 474 | if (save_i387_fxsave(fx) < 0) | 488 | if (save_i387_fxsave(fx) < 0) |
| 475 | return -1; | 489 | return -1; |
| 476 | 490 | ||
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 | } |
