aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-01-27 10:23:07 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-03-26 18:09:10 -0400
commit72b22bbad1e7cff4645c0f05b4d573ac301d5157 (patch)
tree3c51d511969f55871797ee9665b1ec8e2c43b8fe
parent6cec7c4ad79f8fd66574044adfa284b20ee7c4fd (diff)
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>
-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,
304 unsigned int pos, unsigned int count, 304 unsigned int pos, unsigned int count,
305 void *kbuf, void __user *ubuf) 305 void *kbuf, void __user *ubuf)
306{ 306{
307 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 307 unsigned i;
308 &target->thread.fpu, 308 int err;
309 0, sizeof(elf_fpregset_t)); 309 u64 fpr_val;
310
310 /* XXX fcr31 */ 311 /* XXX fcr31 */
312
313 if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
314 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
315 &target->thread.fpu,
316 0, sizeof(elf_fpregset_t));
317
318 for (i = 0; i < NUM_FPU_REGS; i++) {
319 fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
320 err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
321 &fpr_val, i * sizeof(elf_fpreg_t),
322 (i + 1) * sizeof(elf_fpreg_t));
323 if (err)
324 return err;
325 }
326
327 return 0;
311} 328}
312 329
313static int fpr_set(struct task_struct *target, 330static int fpr_set(struct task_struct *target,
@@ -315,10 +332,27 @@ static int fpr_set(struct task_struct *target,
315 unsigned int pos, unsigned int count, 332 unsigned int pos, unsigned int count,
316 const void *kbuf, const void __user *ubuf) 333 const void *kbuf, const void __user *ubuf)
317{ 334{
318 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 335 unsigned i;
319 &target->thread.fpu, 336 int err;
320 0, sizeof(elf_fpregset_t)); 337 u64 fpr_val;
338
321 /* XXX fcr31 */ 339 /* XXX fcr31 */
340
341 if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
342 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
343 &target->thread.fpu,
344 0, sizeof(elf_fpregset_t));
345
346 for (i = 0; i < NUM_FPU_REGS; i++) {
347 err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
348 &fpr_val, i * sizeof(elf_fpreg_t),
349 (i + 1) * sizeof(elf_fpreg_t));
350 if (err)
351 return err;
352 set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
353 }
354
355 return 0;
322} 356}
323 357
324enum mips_regset { 358enum mips_regset {