summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/ptrace.c
diff options
context:
space:
mode:
authorPaul Burton2014-01-27 16:23:07 +0100
committerRalf Baechle2014-03-26 23:09:10 +0100
commit72b22bbad1e7cff4645c0f05b4d573ac301d5157 (patch)
tree3c51d511969f55871797ee9665b1ec8e2c43b8fe /arch/mips/kernel/ptrace.c
parentMIPS: Don't assume 64-bit FP registers for dump_{,task_}fpu (diff)
downloadkernel-qcow2-linux-72b22bbad1e7cff4645c0f05b4d573ac301d5157.tar.gz
kernel-qcow2-linux-72b22bbad1e7cff4645c0f05b4d573ac301d5157.tar.xz
kernel-qcow2-linux-72b22bbad1e7cff4645c0f05b4d573ac301d5157.zip
MIPS: Don't assume 64-bit FP registers for FP regset
When we want to access 64-bit FP register values we can only treat consecutive registers as being consecutive in memory when the width of an FP register equals 64 bits. This assumption will not remain true once MSA support is introduced, so provide a code path which copies each 64 bit FP register value in turn when the width of an FP register differs from 64 bits. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6427/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/ptrace.c')
-rw-r--r--arch/mips/kernel/ptrace.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 7d97709e715f..4137a49eae26 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -304,10 +304,27 @@ static int fpr_get(struct task_struct *target,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
{
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu,
- 0, sizeof(elf_fpregset_t));
+ unsigned i;
+ int err;
+ u64 fpr_val;
+
/* XXX fcr31 */
+
+ if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+ err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &fpr_val, i * sizeof(elf_fpreg_t),
+ (i + 1) * sizeof(elf_fpreg_t));
+ if (err)
+ return err;
+ }
+
+ return 0;
}
static int fpr_set(struct task_struct *target,
@@ -315,10 +332,27 @@ static int fpr_set(struct task_struct *target,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
- return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.fpu,
- 0, sizeof(elf_fpregset_t));
+ unsigned i;
+ int err;
+ u64 fpr_val;
+
/* XXX fcr31 */
+
+ if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+
+ for (i = 0; i < NUM_FPU_REGS; i++) {
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &fpr_val, i * sizeof(elf_fpreg_t),
+ (i + 1) * sizeof(elf_fpreg_t));
+ if (err)
+ return err;
+ set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+ }
+
+ return 0;
}
enum mips_regset {