diff options
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/fpu/internal.h | 38 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/xstate.c | 39 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 4 |
4 files changed, 45 insertions, 38 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index de81ddf3b0b2..54605eb1631f 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -325,7 +325,7 @@ static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, | |||
325 | if (fpu->fpstate_active) { | 325 | if (fpu->fpstate_active) { |
326 | unsigned long fx_aligned, math_size; | 326 | unsigned long fx_aligned, math_size; |
327 | 327 | ||
328 | sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size); | 328 | sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size); |
329 | *fpstate = (struct _fpstate_ia32 __user *) sp; | 329 | *fpstate = (struct _fpstate_ia32 __user *) sp; |
330 | if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned, | 330 | if (copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned, |
331 | math_size) < 0) | 331 | math_size) < 0) |
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index d6cfbdafbab2..34fbf95bbe14 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h | |||
@@ -53,6 +53,7 @@ extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); | |||
53 | */ | 53 | */ |
54 | extern void fpu__save(struct fpu *fpu); | 54 | extern void fpu__save(struct fpu *fpu); |
55 | extern void fpu__restore(void); | 55 | extern void fpu__restore(void); |
56 | extern int fpu__restore_sig(void __user *buf, int ia32_frame); | ||
56 | extern void fpu__drop(struct fpu *fpu); | 57 | extern void fpu__drop(struct fpu *fpu); |
57 | extern int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu); | 58 | extern int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu); |
58 | extern void fpu__reset(struct fpu *fpu); | 59 | extern void fpu__reset(struct fpu *fpu); |
@@ -497,25 +498,6 @@ static inline void switch_fpu_finish(struct fpu *new_fpu, fpu_switch_t fpu_switc | |||
497 | * Signal frame handlers... | 498 | * Signal frame handlers... |
498 | */ | 499 | */ |
499 | extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fx, int size); | 500 | extern int copy_fpstate_to_sigframe(void __user *buf, void __user *fx, int size); |
500 | extern int __fpu__restore_sig(void __user *buf, void __user *fx, int size); | ||
501 | |||
502 | static inline int xstate_sigframe_size(void) | ||
503 | { | ||
504 | return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size; | ||
505 | } | ||
506 | |||
507 | static inline int fpu__restore_sig(void __user *buf, int ia32_frame) | ||
508 | { | ||
509 | void __user *buf_fx = buf; | ||
510 | int size = xstate_sigframe_size(); | ||
511 | |||
512 | if (ia32_frame && use_fxsr()) { | ||
513 | buf_fx = buf + sizeof(struct i387_fsave_struct); | ||
514 | size += sizeof(struct i387_fsave_struct); | ||
515 | } | ||
516 | |||
517 | return __fpu__restore_sig(buf, buf_fx, size); | ||
518 | } | ||
519 | 501 | ||
520 | /* | 502 | /* |
521 | * Needs to be preemption-safe. | 503 | * Needs to be preemption-safe. |
@@ -565,20 +547,8 @@ static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) | |||
565 | } | 547 | } |
566 | } | 548 | } |
567 | 549 | ||
568 | static inline unsigned long | 550 | unsigned long |
569 | alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx, | 551 | fpu__alloc_mathframe(unsigned long sp, int ia32_frame, |
570 | unsigned long *size) | 552 | unsigned long *buf_fx, unsigned long *size); |
571 | { | ||
572 | unsigned long frame_size = xstate_sigframe_size(); | ||
573 | |||
574 | *buf_fx = sp = round_down(sp - frame_size, 64); | ||
575 | if (ia32_frame && use_fxsr()) { | ||
576 | frame_size += sizeof(struct i387_fsave_struct); | ||
577 | sp -= sizeof(struct i387_fsave_struct); | ||
578 | } | ||
579 | |||
580 | *size = frame_size; | ||
581 | return sp; | ||
582 | } | ||
583 | 553 | ||
584 | #endif /* _ASM_X86_FPU_INTERNAL_H */ | 554 | #endif /* _ASM_X86_FPU_INTERNAL_H */ |
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index ea514d6a34e8..810f080fadf3 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c | |||
@@ -388,7 +388,7 @@ static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only) | |||
388 | return frstor_user(buf); | 388 | return frstor_user(buf); |
389 | } | 389 | } |
390 | 390 | ||
391 | int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) | 391 | static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) |
392 | { | 392 | { |
393 | int ia32_fxstate = (buf != buf_fx); | 393 | int ia32_fxstate = (buf != buf_fx); |
394 | struct task_struct *tsk = current; | 394 | struct task_struct *tsk = current; |
@@ -482,6 +482,43 @@ int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) | |||
482 | return 0; | 482 | return 0; |
483 | } | 483 | } |
484 | 484 | ||
485 | static inline int xstate_sigframe_size(void) | ||
486 | { | ||
487 | return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size; | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Restore FPU state from a sigframe: | ||
492 | */ | ||
493 | int fpu__restore_sig(void __user *buf, int ia32_frame) | ||
494 | { | ||
495 | void __user *buf_fx = buf; | ||
496 | int size = xstate_sigframe_size(); | ||
497 | |||
498 | if (ia32_frame && use_fxsr()) { | ||
499 | buf_fx = buf + sizeof(struct i387_fsave_struct); | ||
500 | size += sizeof(struct i387_fsave_struct); | ||
501 | } | ||
502 | |||
503 | return __fpu__restore_sig(buf, buf_fx, size); | ||
504 | } | ||
505 | |||
506 | unsigned long | ||
507 | fpu__alloc_mathframe(unsigned long sp, int ia32_frame, | ||
508 | unsigned long *buf_fx, unsigned long *size) | ||
509 | { | ||
510 | unsigned long frame_size = xstate_sigframe_size(); | ||
511 | |||
512 | *buf_fx = sp = round_down(sp - frame_size, 64); | ||
513 | if (ia32_frame && use_fxsr()) { | ||
514 | frame_size += sizeof(struct i387_fsave_struct); | ||
515 | sp -= sizeof(struct i387_fsave_struct); | ||
516 | } | ||
517 | |||
518 | *size = frame_size; | ||
519 | |||
520 | return sp; | ||
521 | } | ||
485 | /* | 522 | /* |
486 | * Prepare the SW reserved portion of the fxsave memory layout, indicating | 523 | * Prepare the SW reserved portion of the fxsave memory layout, indicating |
487 | * the presence of the extended state information in the memory layout | 524 | * the presence of the extended state information in the memory layout |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 7416fa86f3c7..9554ca69a84e 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -219,8 +219,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, | |||
219 | } | 219 | } |
220 | 220 | ||
221 | if (fpu->fpstate_active) { | 221 | if (fpu->fpstate_active) { |
222 | sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32), | 222 | sp = fpu__alloc_mathframe(sp, config_enabled(CONFIG_X86_32), |
223 | &buf_fx, &math_size); | 223 | &buf_fx, &math_size); |
224 | *fpstate = (void __user *)sp; | 224 | *fpstate = (void __user *)sp; |
225 | } | 225 | } |
226 | 226 | ||