.. | .. |
---|
5 | 5 | |
---|
6 | 6 | #include <linux/compat.h> |
---|
7 | 7 | #include <linux/cpu.h> |
---|
| 8 | +#include <linux/pagemap.h> |
---|
8 | 9 | |
---|
9 | 10 | #include <asm/fpu/internal.h> |
---|
10 | 11 | #include <asm/fpu/signal.h> |
---|
.. | .. |
---|
61 | 62 | struct user_i387_ia32_struct env; |
---|
62 | 63 | struct _fpstate_32 __user *fp = buf; |
---|
63 | 64 | |
---|
| 65 | + fpregs_lock(); |
---|
| 66 | + if (!test_thread_flag(TIF_NEED_FPU_LOAD)) |
---|
| 67 | + copy_fxregs_to_kernel(&tsk->thread.fpu); |
---|
| 68 | + fpregs_unlock(); |
---|
| 69 | + |
---|
64 | 70 | convert_from_fxsr(&env, tsk); |
---|
65 | 71 | |
---|
66 | 72 | if (__copy_to_user(buf, &env, sizeof(env)) || |
---|
.. | .. |
---|
92 | 98 | return err; |
---|
93 | 99 | |
---|
94 | 100 | err |= __put_user(FP_XSTATE_MAGIC2, |
---|
95 | | - (__u32 *)(buf + fpu_user_xstate_size)); |
---|
| 101 | + (__u32 __user *)(buf + fpu_user_xstate_size)); |
---|
96 | 102 | |
---|
97 | 103 | /* |
---|
98 | 104 | * Read the xfeatures which we copied (directly from the cpu or |
---|
99 | 105 | * from the state in task struct) to the user buffers. |
---|
100 | 106 | */ |
---|
101 | | - err |= __get_user(xfeatures, (__u32 *)&x->header.xfeatures); |
---|
| 107 | + err |= __get_user(xfeatures, (__u32 __user *)&x->header.xfeatures); |
---|
102 | 108 | |
---|
103 | 109 | /* |
---|
104 | 110 | * For legacy compatible, we always set FP/SSE bits in the bit |
---|
.. | .. |
---|
113 | 119 | */ |
---|
114 | 120 | xfeatures |= XFEATURE_MASK_FPSSE; |
---|
115 | 121 | |
---|
116 | | - err |= __put_user(xfeatures, (__u32 *)&x->header.xfeatures); |
---|
| 122 | + err |= __put_user(xfeatures, (__u32 __user *)&x->header.xfeatures); |
---|
117 | 123 | |
---|
118 | 124 | return err; |
---|
119 | 125 | } |
---|
.. | .. |
---|
144 | 150 | * buf == buf_fx for 64-bit frames and 32-bit fsave frame. |
---|
145 | 151 | * buf != buf_fx for 32-bit frames with fxstate. |
---|
146 | 152 | * |
---|
147 | | - * If the fpu, extended register state is live, save the state directly |
---|
148 | | - * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise, |
---|
149 | | - * copy the thread's fpu state to the user frame starting at 'buf_fx'. |
---|
| 153 | + * Try to save it directly to the user frame with disabled page fault handler. |
---|
| 154 | + * If this fails then do the slow path where the FPU state is first saved to |
---|
| 155 | + * task's fpu->state and then copy it to the user frame pointed to by the |
---|
| 156 | + * aligned pointer 'buf_fx'. |
---|
150 | 157 | * |
---|
151 | 158 | * If this is a 32-bit frame with fxstate, put a fsave header before |
---|
152 | 159 | * the aligned state at 'buf_fx'. |
---|
.. | .. |
---|
156 | 163 | */ |
---|
157 | 164 | int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size) |
---|
158 | 165 | { |
---|
159 | | - struct fpu *fpu = ¤t->thread.fpu; |
---|
160 | | - struct xregs_state *xsave = &fpu->state.xsave; |
---|
161 | 166 | struct task_struct *tsk = current; |
---|
162 | 167 | int ia32_fxstate = (buf != buf_fx); |
---|
| 168 | + int ret; |
---|
163 | 169 | |
---|
164 | 170 | ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) || |
---|
165 | 171 | IS_ENABLED(CONFIG_IA32_EMULATION)); |
---|
166 | 172 | |
---|
167 | | - if (!access_ok(VERIFY_WRITE, buf, size)) |
---|
| 173 | + if (!static_cpu_has(X86_FEATURE_FPU)) { |
---|
| 174 | + struct user_i387_ia32_struct fp; |
---|
| 175 | + fpregs_soft_get(current, NULL, (struct membuf){.p = &fp, |
---|
| 176 | + .left = sizeof(fp)}); |
---|
| 177 | + return copy_to_user(buf, &fp, sizeof(fp)) ? -EFAULT : 0; |
---|
| 178 | + } |
---|
| 179 | + |
---|
| 180 | + if (!access_ok(buf, size)) |
---|
168 | 181 | return -EACCES; |
---|
| 182 | +retry: |
---|
| 183 | + /* |
---|
| 184 | + * Load the FPU registers if they are not valid for the current task. |
---|
| 185 | + * With a valid FPU state we can attempt to save the state directly to |
---|
| 186 | + * userland's stack frame which will likely succeed. If it does not, |
---|
| 187 | + * resolve the fault in the user memory and try again. |
---|
| 188 | + */ |
---|
| 189 | + fpregs_lock(); |
---|
| 190 | + if (test_thread_flag(TIF_NEED_FPU_LOAD)) |
---|
| 191 | + __fpregs_load_activate(); |
---|
169 | 192 | |
---|
170 | | - if (!static_cpu_has(X86_FEATURE_FPU)) |
---|
171 | | - return fpregs_soft_get(current, NULL, 0, |
---|
172 | | - sizeof(struct user_i387_ia32_struct), NULL, |
---|
173 | | - (struct _fpstate_32 __user *) buf) ? -1 : 1; |
---|
| 193 | + pagefault_disable(); |
---|
| 194 | + ret = copy_fpregs_to_sigframe(buf_fx); |
---|
| 195 | + pagefault_enable(); |
---|
| 196 | + fpregs_unlock(); |
---|
174 | 197 | |
---|
175 | | - if (fpu->initialized || using_compacted_format()) { |
---|
176 | | - /* Save the live register state to the user directly. */ |
---|
177 | | - if (copy_fpregs_to_sigframe(buf_fx)) |
---|
178 | | - return -1; |
---|
179 | | - /* Update the thread's fxstate to save the fsave header. */ |
---|
180 | | - if (ia32_fxstate) |
---|
181 | | - copy_fxregs_to_kernel(fpu); |
---|
182 | | - } else { |
---|
183 | | - /* |
---|
184 | | - * It is a *bug* if kernel uses compacted-format for xsave |
---|
185 | | - * area and we copy it out directly to a signal frame. It |
---|
186 | | - * should have been handled above by saving the registers |
---|
187 | | - * directly. |
---|
188 | | - */ |
---|
189 | | - if (boot_cpu_has(X86_FEATURE_XSAVES)) { |
---|
190 | | - WARN_ONCE(1, "x86/fpu: saving compacted-format xsave area to a signal frame!\n"); |
---|
191 | | - return -1; |
---|
192 | | - } |
---|
193 | | - |
---|
194 | | - fpstate_sanitize_xstate(fpu); |
---|
195 | | - if (__copy_to_user(buf_fx, xsave, fpu_user_xstate_size)) |
---|
196 | | - return -1; |
---|
| 198 | + if (ret) { |
---|
| 199 | + if (!fault_in_pages_writeable(buf_fx, fpu_user_xstate_size)) |
---|
| 200 | + goto retry; |
---|
| 201 | + return -EFAULT; |
---|
197 | 202 | } |
---|
198 | 203 | |
---|
199 | 204 | /* Save the fsave header for the 32-bit frames. */ |
---|
.. | .. |
---|
207 | 212 | } |
---|
208 | 213 | |
---|
209 | 214 | static inline void |
---|
210 | | -sanitize_restored_xstate(struct task_struct *tsk, |
---|
211 | | - struct user_i387_ia32_struct *ia32_env, |
---|
212 | | - u64 xfeatures, int fx_only) |
---|
| 215 | +sanitize_restored_user_xstate(union fpregs_state *state, |
---|
| 216 | + struct user_i387_ia32_struct *ia32_env, |
---|
| 217 | + u64 user_xfeatures, int fx_only) |
---|
213 | 218 | { |
---|
214 | | - struct xregs_state *xsave = &tsk->thread.fpu.state.xsave; |
---|
| 219 | + struct xregs_state *xsave = &state->xsave; |
---|
215 | 220 | struct xstate_header *header = &xsave->header; |
---|
216 | 221 | |
---|
217 | 222 | if (use_xsave()) { |
---|
218 | 223 | /* |
---|
219 | | - * Note: we don't need to zero the reserved bits in the |
---|
220 | | - * xstate_header here because we either didn't copy them at all, |
---|
221 | | - * or we checked earlier that they aren't set. |
---|
| 224 | + * Clear all feature bits which are not set in |
---|
| 225 | + * user_xfeatures and clear all extended features |
---|
| 226 | + * for fx_only mode. |
---|
222 | 227 | */ |
---|
| 228 | + u64 mask = fx_only ? XFEATURE_MASK_FPSSE : user_xfeatures; |
---|
223 | 229 | |
---|
224 | 230 | /* |
---|
225 | | - * Init the state that is not present in the memory |
---|
226 | | - * layout and not enabled by the OS. |
---|
| 231 | + * Supervisor state has to be preserved. The sigframe |
---|
| 232 | + * restore can only modify user features, i.e. @mask |
---|
| 233 | + * cannot contain them. |
---|
227 | 234 | */ |
---|
228 | | - if (fx_only) |
---|
229 | | - header->xfeatures = XFEATURE_MASK_FPSSE; |
---|
230 | | - else |
---|
231 | | - header->xfeatures &= xfeatures; |
---|
| 235 | + header->xfeatures &= mask | xfeatures_mask_supervisor(); |
---|
232 | 236 | } |
---|
233 | 237 | |
---|
234 | 238 | if (use_fxsr()) { |
---|
.. | .. |
---|
238 | 242 | */ |
---|
239 | 243 | xsave->i387.mxcsr &= mxcsr_feature_mask; |
---|
240 | 244 | |
---|
241 | | - convert_to_fxsr(tsk, ia32_env); |
---|
| 245 | + if (ia32_env) |
---|
| 246 | + convert_to_fxsr(&state->fxsave, ia32_env); |
---|
242 | 247 | } |
---|
243 | 248 | } |
---|
244 | 249 | |
---|
245 | 250 | /* |
---|
246 | 251 | * Restore the extended state if present. Otherwise, restore the FP/SSE state. |
---|
247 | 252 | */ |
---|
248 | | -static inline int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only) |
---|
| 253 | +static int copy_user_to_fpregs_zeroing(void __user *buf, u64 xbv, int fx_only) |
---|
249 | 254 | { |
---|
| 255 | + u64 init_bv; |
---|
| 256 | + int r; |
---|
| 257 | + |
---|
250 | 258 | if (use_xsave()) { |
---|
251 | | - if ((unsigned long)buf % 64 || fx_only) { |
---|
252 | | - u64 init_bv = xfeatures_mask & ~XFEATURE_MASK_FPSSE; |
---|
253 | | - copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); |
---|
254 | | - return copy_user_to_fxregs(buf); |
---|
255 | | - } else { |
---|
256 | | - u64 init_bv = xfeatures_mask & ~xbv; |
---|
257 | | - if (unlikely(init_bv)) |
---|
| 259 | + if (fx_only) { |
---|
| 260 | + init_bv = xfeatures_mask_user() & ~XFEATURE_MASK_FPSSE; |
---|
| 261 | + |
---|
| 262 | + r = copy_user_to_fxregs(buf); |
---|
| 263 | + if (!r) |
---|
258 | 264 | copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); |
---|
259 | | - return copy_user_to_xregs(buf, xbv); |
---|
| 265 | + return r; |
---|
| 266 | + } else { |
---|
| 267 | + init_bv = xfeatures_mask_user() & ~xbv; |
---|
| 268 | + |
---|
| 269 | + r = copy_user_to_xregs(buf, xbv); |
---|
| 270 | + if (!r && unlikely(init_bv)) |
---|
| 271 | + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); |
---|
| 272 | + return r; |
---|
260 | 273 | } |
---|
261 | 274 | } else if (use_fxsr()) { |
---|
262 | 275 | return copy_user_to_fxregs(buf); |
---|
.. | .. |
---|
266 | 279 | |
---|
267 | 280 | static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) |
---|
268 | 281 | { |
---|
| 282 | + struct user_i387_ia32_struct *envp = NULL; |
---|
| 283 | + int state_size = fpu_kernel_xstate_size; |
---|
269 | 284 | int ia32_fxstate = (buf != buf_fx); |
---|
270 | 285 | struct task_struct *tsk = current; |
---|
271 | 286 | struct fpu *fpu = &tsk->thread.fpu; |
---|
272 | | - int state_size = fpu_kernel_xstate_size; |
---|
273 | | - u64 xfeatures = 0; |
---|
| 287 | + struct user_i387_ia32_struct env; |
---|
| 288 | + u64 user_xfeatures = 0; |
---|
274 | 289 | int fx_only = 0; |
---|
275 | 290 | int ret = 0; |
---|
276 | 291 | |
---|
.. | .. |
---|
278 | 293 | IS_ENABLED(CONFIG_IA32_EMULATION)); |
---|
279 | 294 | |
---|
280 | 295 | if (!buf) { |
---|
281 | | - fpu__clear(fpu); |
---|
| 296 | + fpu__clear_user_states(fpu); |
---|
282 | 297 | return 0; |
---|
283 | 298 | } |
---|
284 | 299 | |
---|
285 | | - if (!access_ok(VERIFY_READ, buf, size)) { |
---|
| 300 | + if (!access_ok(buf, size)) { |
---|
286 | 301 | ret = -EACCES; |
---|
287 | | - goto out_err; |
---|
| 302 | + goto out; |
---|
288 | 303 | } |
---|
289 | | - |
---|
290 | | - fpu__initialize(fpu); |
---|
291 | 304 | |
---|
292 | 305 | if (!static_cpu_has(X86_FEATURE_FPU)) { |
---|
293 | | - ret = fpregs_soft_set(current, NULL, |
---|
294 | | - 0, sizeof(struct user_i387_ia32_struct), |
---|
295 | | - NULL, buf) != 0; |
---|
296 | | - if (ret) |
---|
297 | | - goto out_err; |
---|
298 | | - return 0; |
---|
| 306 | + ret = fpregs_soft_set(current, NULL, 0, |
---|
| 307 | + sizeof(struct user_i387_ia32_struct), |
---|
| 308 | + NULL, buf); |
---|
| 309 | + goto out; |
---|
299 | 310 | } |
---|
300 | 311 | |
---|
301 | 312 | if (use_xsave()) { |
---|
.. | .. |
---|
311 | 322 | trace_x86_fpu_xstate_check_failed(fpu); |
---|
312 | 323 | } else { |
---|
313 | 324 | state_size = fx_sw_user.xstate_size; |
---|
314 | | - xfeatures = fx_sw_user.xfeatures; |
---|
| 325 | + user_xfeatures = fx_sw_user.xfeatures; |
---|
315 | 326 | } |
---|
316 | 327 | } |
---|
317 | 328 | |
---|
318 | | - if (ia32_fxstate) { |
---|
| 329 | + if ((unsigned long)buf_fx % 64) |
---|
| 330 | + fx_only = 1; |
---|
| 331 | + |
---|
| 332 | + if (!ia32_fxstate) { |
---|
319 | 333 | /* |
---|
320 | | - * For 32-bit frames with fxstate, copy the user state to the |
---|
321 | | - * thread's fpu state, reconstruct fxstate from the fsave |
---|
322 | | - * header. Validate and sanitize the copied state. |
---|
| 334 | + * Attempt to restore the FPU registers directly from user |
---|
| 335 | + * memory. For that to succeed, the user access cannot cause |
---|
| 336 | + * page faults. If it does, fall back to the slow path below, |
---|
| 337 | + * going through the kernel buffer with the enabled pagefault |
---|
| 338 | + * handler. |
---|
323 | 339 | */ |
---|
324 | | - struct user_i387_ia32_struct env; |
---|
325 | | - int err = 0; |
---|
| 340 | + fpregs_lock(); |
---|
| 341 | + pagefault_disable(); |
---|
| 342 | + ret = copy_user_to_fpregs_zeroing(buf_fx, user_xfeatures, fx_only); |
---|
| 343 | + pagefault_enable(); |
---|
| 344 | + if (!ret) { |
---|
326 | 345 | |
---|
327 | | - /* |
---|
328 | | - * Drop the current fpu which clears fpu->initialized. This ensures |
---|
329 | | - * that any context-switch during the copy of the new state, |
---|
330 | | - * avoids the intermediate state from getting restored/saved. |
---|
331 | | - * Thus avoiding the new restored state from getting corrupted. |
---|
332 | | - * We will be ready to restore/save the state only after |
---|
333 | | - * fpu->initialized is again set. |
---|
334 | | - */ |
---|
335 | | - fpu__drop(fpu); |
---|
336 | | - |
---|
337 | | - if (using_compacted_format()) { |
---|
338 | | - err = copy_user_to_xstate(&fpu->state.xsave, buf_fx); |
---|
339 | | - } else { |
---|
340 | | - err = __copy_from_user(&fpu->state.xsave, buf_fx, state_size); |
---|
341 | | - |
---|
342 | | - if (!err && state_size > offsetof(struct xregs_state, header)) |
---|
343 | | - err = validate_xstate_header(&fpu->state.xsave.header); |
---|
| 346 | + /* |
---|
| 347 | + * Restore supervisor states: previous context switch |
---|
| 348 | + * etc has done XSAVES and saved the supervisor states |
---|
| 349 | + * in the kernel buffer from which they can be restored |
---|
| 350 | + * now. |
---|
| 351 | + * |
---|
| 352 | + * We cannot do a single XRSTORS here - which would |
---|
| 353 | + * be nice - because the rest of the FPU registers are |
---|
| 354 | + * being restored from a user buffer directly. The |
---|
| 355 | + * single XRSTORS happens below, when the user buffer |
---|
| 356 | + * has been copied to the kernel one. |
---|
| 357 | + */ |
---|
| 358 | + if (test_thread_flag(TIF_NEED_FPU_LOAD) && |
---|
| 359 | + xfeatures_mask_supervisor()) |
---|
| 360 | + copy_kernel_to_xregs(&fpu->state.xsave, |
---|
| 361 | + xfeatures_mask_supervisor()); |
---|
| 362 | + fpregs_mark_activate(); |
---|
| 363 | + fpregs_unlock(); |
---|
| 364 | + return 0; |
---|
344 | 365 | } |
---|
345 | 366 | |
---|
346 | | - if (err || __copy_from_user(&env, buf, sizeof(env))) { |
---|
347 | | - fpstate_init(&fpu->state); |
---|
348 | | - trace_x86_fpu_init_state(fpu); |
---|
349 | | - err = -1; |
---|
350 | | - } else { |
---|
351 | | - sanitize_restored_xstate(tsk, &env, xfeatures, fx_only); |
---|
352 | | - } |
---|
| 367 | + /* |
---|
| 368 | + * The above did an FPU restore operation, restricted to |
---|
| 369 | + * the user portion of the registers, and failed, but the |
---|
| 370 | + * microcode might have modified the FPU registers |
---|
| 371 | + * nevertheless. |
---|
| 372 | + * |
---|
| 373 | + * If the FPU registers do not belong to current, then |
---|
| 374 | + * invalidate the FPU register state otherwise the task might |
---|
| 375 | + * preempt current and return to user space with corrupted |
---|
| 376 | + * FPU registers. |
---|
| 377 | + * |
---|
| 378 | + * In case current owns the FPU registers then no further |
---|
| 379 | + * action is required. The fixup below will handle it |
---|
| 380 | + * correctly. |
---|
| 381 | + */ |
---|
| 382 | + if (test_thread_flag(TIF_NEED_FPU_LOAD)) |
---|
| 383 | + __cpu_invalidate_fpregs_state(); |
---|
353 | 384 | |
---|
354 | | - preempt_disable(); |
---|
355 | | - local_bh_disable(); |
---|
356 | | - fpu->initialized = 1; |
---|
357 | | - fpu__restore(fpu); |
---|
358 | | - local_bh_enable(); |
---|
359 | | - preempt_enable(); |
---|
360 | | - |
---|
361 | | - /* Failure is already handled */ |
---|
362 | | - return err; |
---|
| 385 | + fpregs_unlock(); |
---|
363 | 386 | } else { |
---|
364 | 387 | /* |
---|
365 | | - * For 64-bit frames and 32-bit fsave frames, restore the user |
---|
366 | | - * state to the registers directly (with exceptions handled). |
---|
| 388 | + * For 32-bit frames with fxstate, copy the fxstate so it can |
---|
| 389 | + * be reconstructed later. |
---|
367 | 390 | */ |
---|
368 | | - user_fpu_begin(); |
---|
369 | | - if (!copy_user_to_fpregs_zeroing(buf_fx, xfeatures, fx_only)) |
---|
370 | | - return 0; |
---|
371 | | - ret = -1; |
---|
| 391 | + ret = __copy_from_user(&env, buf, sizeof(env)); |
---|
| 392 | + if (ret) |
---|
| 393 | + goto out; |
---|
| 394 | + envp = &env; |
---|
372 | 395 | } |
---|
373 | 396 | |
---|
374 | | -out_err: |
---|
375 | | - fpu__clear(fpu); |
---|
| 397 | + /* |
---|
| 398 | + * By setting TIF_NEED_FPU_LOAD it is ensured that our xstate is |
---|
| 399 | + * not modified on context switch and that the xstate is considered |
---|
| 400 | + * to be loaded again on return to userland (overriding last_cpu avoids |
---|
| 401 | + * the optimisation). |
---|
| 402 | + */ |
---|
| 403 | + fpregs_lock(); |
---|
| 404 | + |
---|
| 405 | + if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { |
---|
| 406 | + |
---|
| 407 | + /* |
---|
| 408 | + * Supervisor states are not modified by user space input. Save |
---|
| 409 | + * current supervisor states first and invalidate the FPU regs. |
---|
| 410 | + */ |
---|
| 411 | + if (xfeatures_mask_supervisor()) |
---|
| 412 | + copy_supervisor_to_kernel(&fpu->state.xsave); |
---|
| 413 | + set_thread_flag(TIF_NEED_FPU_LOAD); |
---|
| 414 | + } |
---|
| 415 | + __fpu_invalidate_fpregs_state(fpu); |
---|
| 416 | + fpregs_unlock(); |
---|
| 417 | + |
---|
| 418 | + if (use_xsave() && !fx_only) { |
---|
| 419 | + u64 init_bv = xfeatures_mask_user() & ~user_xfeatures; |
---|
| 420 | + |
---|
| 421 | + ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx); |
---|
| 422 | + if (ret) |
---|
| 423 | + goto out; |
---|
| 424 | + |
---|
| 425 | + sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures, |
---|
| 426 | + fx_only); |
---|
| 427 | + |
---|
| 428 | + fpregs_lock(); |
---|
| 429 | + if (unlikely(init_bv)) |
---|
| 430 | + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); |
---|
| 431 | + |
---|
| 432 | + /* |
---|
| 433 | + * Restore previously saved supervisor xstates along with |
---|
| 434 | + * copied-in user xstates. |
---|
| 435 | + */ |
---|
| 436 | + ret = copy_kernel_to_xregs_err(&fpu->state.xsave, |
---|
| 437 | + user_xfeatures | xfeatures_mask_supervisor()); |
---|
| 438 | + |
---|
| 439 | + } else if (use_fxsr()) { |
---|
| 440 | + ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size); |
---|
| 441 | + if (ret) { |
---|
| 442 | + ret = -EFAULT; |
---|
| 443 | + goto out; |
---|
| 444 | + } |
---|
| 445 | + |
---|
| 446 | + sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures, |
---|
| 447 | + fx_only); |
---|
| 448 | + |
---|
| 449 | + fpregs_lock(); |
---|
| 450 | + if (use_xsave()) { |
---|
| 451 | + u64 init_bv; |
---|
| 452 | + |
---|
| 453 | + init_bv = xfeatures_mask_user() & ~XFEATURE_MASK_FPSSE; |
---|
| 454 | + copy_kernel_to_xregs(&init_fpstate.xsave, init_bv); |
---|
| 455 | + } |
---|
| 456 | + |
---|
| 457 | + ret = copy_kernel_to_fxregs_err(&fpu->state.fxsave); |
---|
| 458 | + } else { |
---|
| 459 | + ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size); |
---|
| 460 | + if (ret) |
---|
| 461 | + goto out; |
---|
| 462 | + |
---|
| 463 | + fpregs_lock(); |
---|
| 464 | + ret = copy_kernel_to_fregs_err(&fpu->state.fsave); |
---|
| 465 | + } |
---|
| 466 | + if (!ret) |
---|
| 467 | + fpregs_mark_activate(); |
---|
| 468 | + else |
---|
| 469 | + fpregs_deactivate(fpu); |
---|
| 470 | + fpregs_unlock(); |
---|
| 471 | + |
---|
| 472 | +out: |
---|
| 473 | + if (ret) |
---|
| 474 | + fpu__clear_user_states(fpu); |
---|
376 | 475 | return ret; |
---|
377 | 476 | } |
---|
378 | 477 | |
---|
.. | .. |
---|
427 | 526 | |
---|
428 | 527 | fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1; |
---|
429 | 528 | fx_sw_reserved.extended_size = size; |
---|
430 | | - fx_sw_reserved.xfeatures = xfeatures_mask; |
---|
| 529 | + fx_sw_reserved.xfeatures = xfeatures_mask_user(); |
---|
431 | 530 | fx_sw_reserved.xstate_size = fpu_user_xstate_size; |
---|
432 | 531 | |
---|
433 | 532 | if (IS_ENABLED(CONFIG_IA32_EMULATION) || |
---|