diff options
author | Roland McGrath <roland@redhat.com> | 2008-01-30 07:31:49 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:31:49 -0500 |
commit | ff0ebb23c6eedc9ac0d84638489d806b30bde8b0 (patch) | |
tree | 7f90ff2fd513818f7c839ed8f5c33ca14292ba2f /arch/x86/math-emu/fpu_entry.c | |
parent | cc927a25bd704448b18b095c658cbfdd79dab865 (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.c | 86 |
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 | ||
676 | int restore_i387_soft(void *s387, struct _fpstate __user *buf) | 675 | int 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 | ||
722 | int save_i387_soft(void *s387, struct _fpstate __user * buf) | 727 | int 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 | |||
765 | int 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 | |||
772 | int 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 | } |