diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/i387.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/xsave.h | 10 | ||||
-rw-r--r-- | arch/x86/kernel/xsave.c | 12 |
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) | |||
59 | static inline int xsave_user(struct xsave_struct __user *buf) | 59 | static 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 | ||