diff options
-rw-r--r-- | arch/mips/kernel/ptrace.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 510452812594..7da6e324dd35 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -46,6 +46,26 @@ | |||
46 | #define CREATE_TRACE_POINTS | 46 | #define CREATE_TRACE_POINTS |
47 | #include <trace/events/syscalls.h> | 47 | #include <trace/events/syscalls.h> |
48 | 48 | ||
49 | static void init_fp_ctx(struct task_struct *target) | ||
50 | { | ||
51 | /* If FP has been used then the target already has context */ | ||
52 | if (tsk_used_math(target)) | ||
53 | return; | ||
54 | |||
55 | /* Begin with data registers set to all 1s... */ | ||
56 | memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr)); | ||
57 | |||
58 | /* ...and FCSR zeroed */ | ||
59 | target->thread.fpu.fcr31 = 0; | ||
60 | |||
61 | /* | ||
62 | * Record that the target has "used" math, such that the context | ||
63 | * just initialised, and any modifications made by the caller, | ||
64 | * aren't discarded. | ||
65 | */ | ||
66 | set_stopped_child_used_math(target); | ||
67 | } | ||
68 | |||
49 | /* | 69 | /* |
50 | * Called by kernel/ptrace.c when detaching.. | 70 | * Called by kernel/ptrace.c when detaching.. |
51 | * | 71 | * |
@@ -142,6 +162,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) | |||
142 | if (!access_ok(VERIFY_READ, data, 33 * 8)) | 162 | if (!access_ok(VERIFY_READ, data, 33 * 8)) |
143 | return -EIO; | 163 | return -EIO; |
144 | 164 | ||
165 | init_fp_ctx(child); | ||
145 | fregs = get_fpu_regs(child); | 166 | fregs = get_fpu_regs(child); |
146 | 167 | ||
147 | for (i = 0; i < 32; i++) { | 168 | for (i = 0; i < 32; i++) { |
@@ -439,6 +460,8 @@ static int fpr_set(struct task_struct *target, | |||
439 | 460 | ||
440 | /* XXX fcr31 */ | 461 | /* XXX fcr31 */ |
441 | 462 | ||
463 | init_fp_ctx(target); | ||
464 | |||
442 | if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) | 465 | if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) |
443 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 466 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
444 | &target->thread.fpu, | 467 | &target->thread.fpu, |
@@ -660,12 +683,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
660 | case FPR_BASE ... FPR_BASE + 31: { | 683 | case FPR_BASE ... FPR_BASE + 31: { |
661 | union fpureg *fregs = get_fpu_regs(child); | 684 | union fpureg *fregs = get_fpu_regs(child); |
662 | 685 | ||
663 | if (!tsk_used_math(child)) { | 686 | init_fp_ctx(child); |
664 | /* FP not yet used */ | ||
665 | memset(&child->thread.fpu, ~0, | ||
666 | sizeof(child->thread.fpu)); | ||
667 | child->thread.fpu.fcr31 = 0; | ||
668 | } | ||
669 | #ifdef CONFIG_32BIT | 687 | #ifdef CONFIG_32BIT |
670 | if (test_thread_flag(TIF_32BIT_FPREGS)) { | 688 | if (test_thread_flag(TIF_32BIT_FPREGS)) { |
671 | /* | 689 | /* |