aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2010-06-22 19:23:37 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2010-07-06 19:31:04 -0400
commit8e221b6db4477643fefc885a97ea9889ac733140 (patch)
tree96f87079865607c26e5a3ca3eab908187bec1fbf /arch
parent815c4163b6c8ebf8152f42b0a5fd015cfdcedc78 (diff)
x86: Avoid unnecessary __clear_user() and xrstor in signal handling
fxsave/xsave doesn't touch all the bytes in the memory layout used by these instructions. Specifically SW reserved (bytes 464..511) fields in the fxsave frame and the reserved fields in the xsave header. To present a clean context for the signal handling, just clear these fields instead of clearing the complete fxsave/xsave memory layout, when we dump these registers directly to the user signal frame. Also avoid the call to second xrstor (which inits the state not passed in the signal frame) in restore_user_xstate() if all the state has already been restored by the first xrstor. These changes improve the performance of signal handling(by ~3-5% as measured by the lat_sig). Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <1277249017.2847.85.camel@sbs-t61.sc.intel.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/i387.h9
-rw-r--r--arch/x86/include/asm/xsave.h10
-rw-r--r--arch/x86/kernel/xsave.c12
3 files changed, 21 insertions, 10 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index c991b3a7b904..0f1cf5d53dd8 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -127,6 +127,15 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
127{ 127{
128 int err; 128 int err;
129 129
130 /*
131 * Clear the bytes not touched by the fxsave and reserved
132 * for the SW usage.
133 */
134 err = __clear_user(&fx->sw_reserved,
135 sizeof(struct _fpx_sw_bytes));
136 if (unlikely(err))
137 return -EFAULT;
138
130 asm volatile("1: rex64/fxsave (%[fx])\n\t" 139 asm volatile("1: rex64/fxsave (%[fx])\n\t"
131 "2:\n" 140 "2:\n"
132 ".section .fixup,\"ax\"\n" 141 ".section .fixup,\"ax\"\n"
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index 2c4390cae228..30dfc81804d5 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -59,6 +59,16 @@ static inline int fpu_xrstor_checking(struct fpu *fpu)
59static inline int xsave_user(struct xsave_struct __user *buf) 59static inline int xsave_user(struct xsave_struct __user *buf)
60{ 60{
61 int err; 61 int err;
62
63 /*
64 * Clear the xsave header first, so that reserved fields are
65 * initialized to zero.
66 */
67 err = __clear_user(&buf->xsave_hdr,
68 sizeof(struct xsave_hdr_struct));
69 if (unlikely(err))
70 return -EFAULT;
71
62 __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n" 72 __asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
63 "2:\n" 73 "2:\n"
64 ".section .fixup,\"ax\"\n" 74 ".section .fixup,\"ax\"\n"
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 37e68fc5e24a..6e73db1b7b4e 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -91,14 +91,6 @@ int save_i387_xstate(void __user *buf)
91 return 0; 91 return 0;
92 92
93 if (task_thread_info(tsk)->status & TS_USEDFPU) { 93 if (task_thread_info(tsk)->status & TS_USEDFPU) {
94 /*
95 * Start with clearing the user buffer. This will present a
96 * clean context for the bytes not touched by the fxsave/xsave.
97 */
98 err = __clear_user(buf, sig_xstate_size);
99 if (err)
100 return err;
101
102 if (use_xsave()) 94 if (use_xsave())
103 err = xsave_user(buf); 95 err = xsave_user(buf);
104 else 96 else
@@ -184,8 +176,8 @@ static int restore_user_xstate(void __user *buf)
184 * init the state skipped by the user. 176 * init the state skipped by the user.
185 */ 177 */
186 mask = pcntxt_mask & ~mask; 178 mask = pcntxt_mask & ~mask;
187 179 if (unlikely(mask))
188 xrstor_state(init_xstate_buf, mask); 180 xrstor_state(init_xstate_buf, mask);
189 181
190 return 0; 182 return 0;
191 183