aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/math-emu/fpu_entry.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-01-30 07:31:49 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:31:49 -0500
commitff0ebb23c6eedc9ac0d84638489d806b30bde8b0 (patch)
tree7f90ff2fd513818f7c839ed8f5c33ca14292ba2f /arch/x86/math-emu/fpu_entry.c
parentcc927a25bd704448b18b095c658cbfdd79dab865 (diff)
x86: x86 user_regset math_emu
This converts the ptrace/signal accessors for i387 math_emu state to the user_regset interface style, and calls these from the old interfaces. It also cleans up math_emulate's ptrace check to be a single-step check, which is what it really wants. Signed-off-by: Roland McGrath <roland@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/math-emu/fpu_entry.c')
-rw-r--r--arch/x86/math-emu/fpu_entry.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c
index 377c60dfa2f0..cfbdaa1532ce 100644
--- a/arch/x86/math-emu/fpu_entry.c
+++ b/arch/x86/math-emu/fpu_entry.c
@@ -25,10 +25,11 @@
25 +---------------------------------------------------------------------------*/ 25 +---------------------------------------------------------------------------*/
26 26
27#include <linux/signal.h> 27#include <linux/signal.h>
28#include <linux/ptrace.h> 28#include <linux/regset.h>
29 29
30#include <asm/uaccess.h> 30#include <asm/uaccess.h>
31#include <asm/desc.h> 31#include <asm/desc.h>
32#include <asm/user.h>
32 33
33#include "fpu_system.h" 34#include "fpu_system.h"
34#include "fpu_emu.h" 35#include "fpu_emu.h"
@@ -198,9 +199,7 @@ asmlinkage void math_emulate(long arg)
198 code_limit = 0xffffffff; 199 code_limit = 0xffffffff;
199 } 200 }
200 201
201 FPU_lookahead = 1; 202 FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
202 if (current->ptrace & PT_PTRACED)
203 FPU_lookahead = 0;
204 203
205 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP, 204 if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
206 &addr_modes.override)) { 205 &addr_modes.override)) {
@@ -673,31 +672,37 @@ void math_abort(struct info *info, unsigned int signal)
673#define sstatus_word() \ 672#define sstatus_word() \
674 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top)) 673 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
675 674
676int restore_i387_soft(void *s387, struct _fpstate __user *buf) 675int fpregs_soft_set(struct task_struct *target,
676 const struct user_regset *regset,
677 unsigned int pos, unsigned int count,
678 const void *kbuf, const void __user *ubuf)
677{ 679{
678 u_char __user *d = (u_char __user *) buf; 680 struct i387_soft_struct *s387 = &target->thread.i387.soft;
681 void *space = s387->st_space;
682 int ret;
679 int offset, other, i, tags, regnr, tag, newtop; 683 int offset, other, i, tags, regnr, tag, newtop;
680 684
681 RE_ENTRANT_CHECK_OFF; 685 RE_ENTRANT_CHECK_OFF;
682 FPU_access_ok(VERIFY_READ, d, 7 * 4 + 8 * 10); 686 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
683 if (__copy_from_user(&S387->cwd, d, 7 * 4)) 687 offsetof(struct i387_soft_struct, st_space));
684 return -1;
685 RE_ENTRANT_CHECK_ON; 688 RE_ENTRANT_CHECK_ON;
686 689
687 d += 7 * 4; 690 if (ret)
691 return ret;
688 692
689 S387->ftop = (S387->swd >> SW_Top_Shift) & 7; 693 S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
690 offset = (S387->ftop & 7) * 10; 694 offset = (S387->ftop & 7) * 10;
691 other = 80 - offset; 695 other = 80 - offset;
692 696
693 RE_ENTRANT_CHECK_OFF; 697 RE_ENTRANT_CHECK_OFF;
698
694 /* Copy all registers in stack order. */ 699 /* Copy all registers in stack order. */
695 if (__copy_from_user(((u_char *) & S387->st_space) + offset, d, other)) 700 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
696 return -1; 701 space + offset, 0, other);
697 if (offset) 702 if (!ret && offset)
698 if (__copy_from_user 703 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
699 ((u_char *) & S387->st_space, d + other, offset)) 704 space, 0, offset);
700 return -1; 705
701 RE_ENTRANT_CHECK_ON; 706 RE_ENTRANT_CHECK_ON;
702 707
703 /* The tags may need to be corrected now. */ 708 /* The tags may need to be corrected now. */
@@ -716,16 +721,21 @@ int restore_i387_soft(void *s387, struct _fpstate __user *buf)
716 } 721 }
717 S387->twd = tags; 722 S387->twd = tags;
718 723
719 return 0; 724 return ret;
720} 725}
721 726
722int save_i387_soft(void *s387, struct _fpstate __user * buf) 727int fpregs_soft_get(struct task_struct *target,
728 const struct user_regset *regset,
729 unsigned int pos, unsigned int count,
730 void *kbuf, void __user *ubuf)
723{ 731{
724 u_char __user *d = (u_char __user *) buf; 732 struct i387_soft_struct *s387 = &target->thread.i387.soft;
733 const void *space = s387->st_space;
734 int ret;
725 int offset = (S387->ftop & 7) * 10, other = 80 - offset; 735 int offset = (S387->ftop & 7) * 10, other = 80 - offset;
726 736
727 RE_ENTRANT_CHECK_OFF; 737 RE_ENTRANT_CHECK_OFF;
728 FPU_access_ok(VERIFY_WRITE, d, 7 * 4 + 8 * 10); 738
729#ifdef PECULIAR_486 739#ifdef PECULIAR_486
730 S387->cwd &= ~0xe080; 740 S387->cwd &= ~0xe080;
731 /* An 80486 sets nearly all of the reserved bits to 1. */ 741 /* An 80486 sets nearly all of the reserved bits to 1. */
@@ -735,21 +745,33 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
735 S387->fcs &= ~0xf8000000; 745 S387->fcs &= ~0xf8000000;
736 S387->fos |= 0xffff0000; 746 S387->fos |= 0xffff0000;
737#endif /* PECULIAR_486 */ 747#endif /* PECULIAR_486 */
738 if (__copy_to_user(d, &S387->cwd, 7 * 4))
739 return -1;
740 RE_ENTRANT_CHECK_ON;
741 748
742 d += 7 * 4; 749 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
750 offsetof(struct i387_soft_struct, st_space));
743 751
744 RE_ENTRANT_CHECK_OFF;
745 /* Copy all registers in stack order. */ 752 /* Copy all registers in stack order. */
746 if (__copy_to_user(d, ((u_char *) & S387->st_space) + offset, other)) 753 if (!ret)
747 return -1; 754 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
748 if (offset) 755 space + offset, 0, other);
749 if (__copy_to_user 756 if (!ret)
750 (d + other, (u_char *) & S387->st_space, offset)) 757 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
751 return -1; 758 space, 0, offset);
759
752 RE_ENTRANT_CHECK_ON; 760 RE_ENTRANT_CHECK_ON;
753 761
754 return 1; 762 return ret;
763}
764
765int save_i387_soft(void *s387, struct _fpstate __user *buf)
766{
767 return fpregs_soft_get(current, NULL,
768 0, sizeof(struct user_i387_struct),
769 NULL, buf) ? -1 : 1;
770}
771
772int restore_i387_soft(void *s387, struct _fpstate __user *buf)
773{
774 return fpregs_soft_set(current, NULL,
775 0, sizeof(struct user_i387_struct),
776 NULL, buf) ? -1 : 1;
755} 777}