.set push
SET_HARDFLOAT
cfc1 \tmp, fcr31
- s.d $f0, THREAD_FPR0_LS64(\thread)
- s.d $f2, THREAD_FPR2_LS64(\thread)
- s.d $f4, THREAD_FPR4_LS64(\thread)
- s.d $f6, THREAD_FPR6_LS64(\thread)
- s.d $f8, THREAD_FPR8_LS64(\thread)
- s.d $f10, THREAD_FPR10_LS64(\thread)
- s.d $f12, THREAD_FPR12_LS64(\thread)
- s.d $f14, THREAD_FPR14_LS64(\thread)
- s.d $f16, THREAD_FPR16_LS64(\thread)
- s.d $f18, THREAD_FPR18_LS64(\thread)
- s.d $f20, THREAD_FPR20_LS64(\thread)
- s.d $f22, THREAD_FPR22_LS64(\thread)
- s.d $f24, THREAD_FPR24_LS64(\thread)
- s.d $f26, THREAD_FPR26_LS64(\thread)
- s.d $f28, THREAD_FPR28_LS64(\thread)
- s.d $f30, THREAD_FPR30_LS64(\thread)
- swc1 $f0, THREAD_FPR0(\thread)
- swc1 $f1, THREAD_FPR1(\thread)
- swc1 $f2, THREAD_FPR2(\thread)
- swc1 $f3, THREAD_FPR3(\thread)
- swc1 $f4, THREAD_FPR4(\thread)
- swc1 $f5, THREAD_FPR5(\thread)
- swc1 $f6, THREAD_FPR6(\thread)
- swc1 $f7, THREAD_FPR7(\thread)
- swc1 $f8, THREAD_FPR8(\thread)
- swc1 $f9, THREAD_FPR9(\thread)
- swc1 $f10, THREAD_FPR10(\thread)
- swc1 $f11, THREAD_FPR11(\thread)
- swc1 $f12, THREAD_FPR12(\thread)
- swc1 $f13, THREAD_FPR13(\thread)
- swc1 $f14, THREAD_FPR14(\thread)
- swc1 $f15, THREAD_FPR15(\thread)
- swc1 $f16, THREAD_FPR16(\thread)
- swc1 $f17, THREAD_FPR17(\thread)
- swc1 $f18, THREAD_FPR18(\thread)
- swc1 $f19, THREAD_FPR19(\thread)
- swc1 $f20, THREAD_FPR20(\thread)
- swc1 $f21, THREAD_FPR21(\thread)
- swc1 $f22, THREAD_FPR22(\thread)
- swc1 $f23, THREAD_FPR23(\thread)
- swc1 $f24, THREAD_FPR24(\thread)
- swc1 $f25, THREAD_FPR25(\thread)
- swc1 $f26, THREAD_FPR26(\thread)
- swc1 $f27, THREAD_FPR27(\thread)
- swc1 $f28, THREAD_FPR28(\thread)
- swc1 $f29, THREAD_FPR29(\thread)
- swc1 $f30, THREAD_FPR30(\thread)
- swc1 $f31, THREAD_FPR31(\thread)
++ s.d $f0, THREAD_FPR0(\thread)
++ s.d $f2, THREAD_FPR2(\thread)
++ s.d $f4, THREAD_FPR4(\thread)
++ s.d $f6, THREAD_FPR6(\thread)
++ s.d $f8, THREAD_FPR8(\thread)
++ s.d $f10, THREAD_FPR10(\thread)
++ s.d $f12, THREAD_FPR12(\thread)
++ s.d $f14, THREAD_FPR14(\thread)
++ s.d $f16, THREAD_FPR16(\thread)
++ s.d $f18, THREAD_FPR18(\thread)
++ s.d $f20, THREAD_FPR20(\thread)
++ s.d $f22, THREAD_FPR22(\thread)
++ s.d $f24, THREAD_FPR24(\thread)
++ s.d $f26, THREAD_FPR26(\thread)
++ s.d $f28, THREAD_FPR28(\thread)
++ s.d $f30, THREAD_FPR30(\thread)
sw \tmp, THREAD_FCR31(\thread)
.set pop
.endm
.set push
SET_HARDFLOAT
lw \tmp, THREAD_FCR31(\thread)
- l.d $f0, THREAD_FPR0_LS64(\thread)
- l.d $f2, THREAD_FPR2_LS64(\thread)
- l.d $f4, THREAD_FPR4_LS64(\thread)
- l.d $f6, THREAD_FPR6_LS64(\thread)
- l.d $f8, THREAD_FPR8_LS64(\thread)
- l.d $f10, THREAD_FPR10_LS64(\thread)
- l.d $f12, THREAD_FPR12_LS64(\thread)
- l.d $f14, THREAD_FPR14_LS64(\thread)
- l.d $f16, THREAD_FPR16_LS64(\thread)
- l.d $f18, THREAD_FPR18_LS64(\thread)
- l.d $f20, THREAD_FPR20_LS64(\thread)
- l.d $f22, THREAD_FPR22_LS64(\thread)
- l.d $f24, THREAD_FPR24_LS64(\thread)
- l.d $f26, THREAD_FPR26_LS64(\thread)
- l.d $f28, THREAD_FPR28_LS64(\thread)
- l.d $f30, THREAD_FPR30_LS64(\thread)
- lwc1 $f0, THREAD_FPR0(\thread)
- lwc1 $f1, THREAD_FPR1(\thread)
- lwc1 $f2, THREAD_FPR2(\thread)
- lwc1 $f3, THREAD_FPR3(\thread)
- lwc1 $f4, THREAD_FPR4(\thread)
- lwc1 $f5, THREAD_FPR5(\thread)
- lwc1 $f6, THREAD_FPR6(\thread)
- lwc1 $f7, THREAD_FPR7(\thread)
- lwc1 $f8, THREAD_FPR8(\thread)
- lwc1 $f9, THREAD_FPR9(\thread)
- lwc1 $f10, THREAD_FPR10(\thread)
- lwc1 $f11, THREAD_FPR11(\thread)
- lwc1 $f12, THREAD_FPR12(\thread)
- lwc1 $f13, THREAD_FPR13(\thread)
- lwc1 $f14, THREAD_FPR14(\thread)
- lwc1 $f15, THREAD_FPR15(\thread)
- lwc1 $f16, THREAD_FPR16(\thread)
- lwc1 $f17, THREAD_FPR17(\thread)
- lwc1 $f18, THREAD_FPR18(\thread)
- lwc1 $f19, THREAD_FPR19(\thread)
- lwc1 $f20, THREAD_FPR20(\thread)
- lwc1 $f21, THREAD_FPR21(\thread)
- lwc1 $f22, THREAD_FPR22(\thread)
- lwc1 $f23, THREAD_FPR23(\thread)
- lwc1 $f24, THREAD_FPR24(\thread)
- lwc1 $f25, THREAD_FPR25(\thread)
- lwc1 $f26, THREAD_FPR26(\thread)
- lwc1 $f27, THREAD_FPR27(\thread)
- lwc1 $f28, THREAD_FPR28(\thread)
- lwc1 $f29, THREAD_FPR29(\thread)
- lwc1 $f30, THREAD_FPR30(\thread)
- lwc1 $f31, THREAD_FPR31(\thread)
++ l.d $f0, THREAD_FPR0(\thread)
++ l.d $f2, THREAD_FPR2(\thread)
++ l.d $f4, THREAD_FPR4(\thread)
++ l.d $f6, THREAD_FPR6(\thread)
++ l.d $f8, THREAD_FPR8(\thread)
++ l.d $f10, THREAD_FPR10(\thread)
++ l.d $f12, THREAD_FPR12(\thread)
++ l.d $f14, THREAD_FPR14(\thread)
++ l.d $f16, THREAD_FPR16(\thread)
++ l.d $f18, THREAD_FPR18(\thread)
++ l.d $f20, THREAD_FPR20(\thread)
++ l.d $f22, THREAD_FPR22(\thread)
++ l.d $f24, THREAD_FPR24(\thread)
++ l.d $f26, THREAD_FPR26(\thread)
++ l.d $f28, THREAD_FPR28(\thread)
++ l.d $f30, THREAD_FPR30(\thread)
ctc1 \tmp, fcr31
.set pop
.endm
#include <asm/byteorder.h>
#include <asm/cpu.h>
+#include <asm/cpu-info.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/mipsregs.h>
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
+ static void init_fp_ctx(struct task_struct *target)
+ {
+ /* If FP has been used then the target already has context */
+ if (tsk_used_math(target))
+ return;
+
+ /* Begin with data registers set to all 1s... */
+ memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
+
+ /* ...and FCSR zeroed */
+ target->thread.fpu.fcr31 = 0;
+
+ /*
+ * Record that the target has "used" math, such that the context
+ * just initialised, and any modifications made by the caller,
+ * aren't discarded.
+ */
+ set_stopped_child_used_math(target);
+ }
+
/*
* Called by kernel/ptrace.c when detaching..
*
{
union fpureg *fregs;
u64 fpr_val;
+ u32 fcr31;
+ u32 value;
+ u32 mask;
int i;
if (!access_ok(VERIFY_READ, data, 33 * 8))
return -EIO;
+ init_fp_ctx(child);
fregs = get_fpu_regs(child);
for (i = 0; i < 32; i++) {
set_fpr64(&fregs[i], 0, fpr_val);
}
- __get_user(child->thread.fpu.fcr31, data + 64);
- child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+ __get_user(value, data + 64);
+ fcr31 = child->thread.fpu.fcr31;
+ mask = current_cpu_data.fpu_msk31;
+ child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
/* FIR may not be written. */
/* XXX fcr31 */
+ init_fp_ctx(target);
+
if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&target->thread.fpu,
case FPR_BASE ... FPR_BASE + 31: {
union fpureg *fregs = get_fpu_regs(child);
- if (!tsk_used_math(child)) {
- /* FP not yet used */
- memset(&child->thread.fpu, ~0,
- sizeof(child->thread.fpu));
- child->thread.fpu.fcr31 = 0;
- }
+ init_fp_ctx(child);
#ifdef CONFIG_32BIT
if (test_thread_flag(TIF_32BIT_FPREGS)) {
/*