diff options
Diffstat (limited to 'arch/sh/kernel/cpu/sh2a/fpu.c')
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/fpu.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c index 6df2fb98eb30..d395ce5740e7 100644 --- a/arch/sh/kernel/cpu/sh2a/fpu.c +++ b/arch/sh/kernel/cpu/sh2a/fpu.c | |||
@@ -25,14 +25,12 @@ | |||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Save FPU registers onto task structure. | 27 | * Save FPU registers onto task structure. |
28 | * Assume called with FPU enabled (SR.FD=0). | ||
29 | */ | 28 | */ |
30 | void | 29 | void |
31 | save_fpu(struct task_struct *tsk, struct pt_regs *regs) | 30 | save_fpu(struct task_struct *tsk) |
32 | { | 31 | { |
33 | unsigned long dummy; | 32 | unsigned long dummy; |
34 | 33 | ||
35 | clear_tsk_thread_flag(tsk, TIF_USEDFPU); | ||
36 | enable_fpu(); | 34 | enable_fpu(); |
37 | asm volatile("sts.l fpul, @-%0\n\t" | 35 | asm volatile("sts.l fpul, @-%0\n\t" |
38 | "sts.l fpscr, @-%0\n\t" | 36 | "sts.l fpscr, @-%0\n\t" |
@@ -60,7 +58,6 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs) | |||
60 | : "memory"); | 58 | : "memory"); |
61 | 59 | ||
62 | disable_fpu(); | 60 | disable_fpu(); |
63 | release_fpu(regs); | ||
64 | } | 61 | } |
65 | 62 | ||
66 | static void | 63 | static void |
@@ -598,31 +595,31 @@ BUILD_TRAP_HANDLER(fpu_error) | |||
598 | struct task_struct *tsk = current; | 595 | struct task_struct *tsk = current; |
599 | TRAP_HANDLER_DECL; | 596 | TRAP_HANDLER_DECL; |
600 | 597 | ||
601 | save_fpu(tsk, regs); | 598 | __unlazy_fpu(tsk, regs); |
602 | if (ieee_fpe_handler(regs)) { | 599 | if (ieee_fpe_handler(regs)) { |
603 | tsk->thread.fpu.hard.fpscr &= | 600 | tsk->thread.fpu.hard.fpscr &= |
604 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); | 601 | ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); |
605 | grab_fpu(regs); | 602 | grab_fpu(regs); |
606 | restore_fpu(tsk); | 603 | restore_fpu(tsk); |
607 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | 604 | task_thread_info(tsk)->status |= TS_USEDFPU; |
608 | return; | 605 | return; |
609 | } | 606 | } |
610 | 607 | ||
611 | force_sig(SIGFPE, tsk); | 608 | force_sig(SIGFPE, tsk); |
612 | } | 609 | } |
613 | 610 | ||
614 | BUILD_TRAP_HANDLER(fpu_state_restore) | 611 | void fpu_state_restore(struct pt_regs *regs) |
615 | { | 612 | { |
616 | struct task_struct *tsk = current; | 613 | struct task_struct *tsk = current; |
617 | TRAP_HANDLER_DECL; | ||
618 | 614 | ||
619 | grab_fpu(regs); | 615 | grab_fpu(regs); |
620 | if (!user_mode(regs)) { | 616 | if (unlikely(!user_mode(regs))) { |
621 | printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); | 617 | printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); |
618 | BUG(); | ||
622 | return; | 619 | return; |
623 | } | 620 | } |
624 | 621 | ||
625 | if (used_math()) { | 622 | if (likely(used_math())) { |
626 | /* Using the FPU again. */ | 623 | /* Using the FPU again. */ |
627 | restore_fpu(tsk); | 624 | restore_fpu(tsk); |
628 | } else { | 625 | } else { |
@@ -630,5 +627,13 @@ BUILD_TRAP_HANDLER(fpu_state_restore) | |||
630 | fpu_init(); | 627 | fpu_init(); |
631 | set_used_math(); | 628 | set_used_math(); |
632 | } | 629 | } |
633 | set_tsk_thread_flag(tsk, TIF_USEDFPU); | 630 | task_thread_info(tsk)->status |= TS_USEDFPU; |
631 | tsk->fpu_counter++; | ||
632 | } | ||
633 | |||
634 | BUILD_TRAP_HANDLER(fpu_state_restore) | ||
635 | { | ||
636 | TRAP_HANDLER_DECL; | ||
637 | |||
638 | fpu_state_restore(regs); | ||
634 | } | 639 | } |