Merge branch '4.1-fp' into mips-for-linux-next
authorRalf Baechle <ralf@linux-mips.org>
Mon, 13 Apr 2015 14:01:37 +0000 (16:01 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 13 Apr 2015 14:01:37 +0000 (16:01 +0200)
1  2 
arch/mips/include/asm/asmmacro-32.h
arch/mips/include/asm/fpu.h
arch/mips/kernel/genex.S
arch/mips/kernel/ptrace.c

index 8deb906df72445436bf8efe1ef7d9551e18b9eaa,80386470d3a4414da1a6ff17d14b624ddd417ad7..0ef39ad0f2d4487e58b90f3409183c01bf605509
        .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
index 83d50d563a0f5d5c556ac78cd16352af25958684,b104ad9d655f2da157544fcf783a225377cb996d..084780b355aa51ee00fff050f49dab33b07d0f5d
@@@ -30,7 -30,7 +30,7 @@@
  struct sigcontext;
  struct sigcontext32;
  
 -extern void _init_fpu(void);
 +extern void _init_fpu(unsigned int);
  extern void _save_fp(struct task_struct *);
  extern void _restore_fp(struct task_struct *);
  
@@@ -48,6 -48,12 +48,12 @@@ enum fpu_mode 
  #define FPU_FR_MASK           0x1
  };
  
+ #define __disable_fpu()                                                       \
+ do {                                                                  \
+       clear_c0_status(ST0_CU1);                                       \
+       disable_fpu_hazard();                                           \
+ } while (0)
  static inline int __enable_fpu(enum fpu_mode mode)
  {
        int fr;
@@@ -86,7 -92,12 +92,12 @@@ fr_common
                enable_fpu_hazard();
  
                /* check FR has the desired value */
-               return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
+               if (!!(read_c0_status() & ST0_FR) == !!fr)
+                       return 0;
+               /* unsupported FR value */
+               __disable_fpu();
+               return SIGFPE;
  
        default:
                BUG();
        return SIGFPE;
  }
  
- #define __disable_fpu()                                                       \
- do {                                                                  \
-       clear_c0_status(ST0_CU1);                                       \
-       disable_fpu_hazard();                                           \
- } while (0)
  #define clear_fpu_owner()     clear_thread_flag(TIF_USEDFPU)
  
  static inline int __is_fpu_owner(void)
@@@ -170,6 -175,7 +175,7 @@@ static inline void lose_fpu(int save
                }
                disable_msa();
                clear_thread_flag(TIF_USEDMSA);
+               __disable_fpu();
        } else if (is_fpu_owner()) {
                if (save)
                        _save_fp(current);
  
  static inline int init_fpu(void)
  {
 +      unsigned int fcr31 = current->thread.fpu.fcr31;
        int ret = 0;
  
        if (cpu_has_fpu) {
                        return ret;
  
                if (!cpu_has_fre) {
 -                      _init_fpu();
 +                      _init_fpu(fcr31);
  
                        return 0;
                }
                config5 = clear_c0_config5(MIPS_CONF5_FRE);
                enable_fpu_hazard();
  
 -              _init_fpu();
 +              _init_fpu(fcr31);
  
                /* Restore FRE */
                write_c0_config5(config5);
diff --combined arch/mips/kernel/genex.S
index 07c4a25b16eac6a5945393892d45446c102997da,86e22422d08c8975962b4ed46b9dcd8023939872..50e9db6f6cba1bd09cfd0ed73dd3a1da00db2225
@@@ -360,7 -360,7 +360,7 @@@ NESTED(nmi_handler, PT_SIZE, sp
        .set    mips1
        SET_HARDFLOAT
        cfc1    a1, fcr31
 -      li      a2, ~(0x3f << 12)
 +      li      a2, ~FPU_CSR_ALL_X
        and     a2, a1
        ctc1    a2, fcr31
        .set    pop
        STI
        .endm
  
+       .macro  __build_clear_msa_fpe
+       _cfcmsa a1, MSA_CSR
+       li      a2, ~(0x3f << 12)
+       and     a1, a1, a2
+       _ctcmsa MSA_CSR, a1
+       TRACE_IRQS_ON
+       STI
+       .endm
        .macro  __build_clear_ade
        MFC0    t0, CP0_BADVADDR
        PTR_S   t0, PT_BVADDR(sp)
        BUILD_HANDLER cpu cpu sti silent                /* #11 */
        BUILD_HANDLER ov ov sti silent                  /* #12 */
        BUILD_HANDLER tr tr sti silent                  /* #13 */
-       BUILD_HANDLER msa_fpe msa_fpe sti silent        /* #14 */
+       BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent    /* #14 */
        BUILD_HANDLER fpe fpe fpe silent                /* #15 */
        BUILD_HANDLER ftlb ftlb none silent             /* #16 */
        BUILD_HANDLER msa msa sti silent                /* #21 */
index 6d1e3f8005f79dc2506012249c7e87462322c5a1,7da6e324dd354a77991c4fe2dd998c07b998d956..d544e774eea6b1b6e0f811099290600b1fc5b534
@@@ -32,7 -32,6 +32,7 @@@
  
  #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..
   *
@@@ -138,14 -157,12 +158,15 @@@ int ptrace_setfpregs(struct task_struc
  {
        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.  */
  
@@@ -445,6 -460,8 +466,8 @@@ static int fpr_set(struct task_struct *
  
        /* 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,
@@@ -666,12 -683,7 +689,7 @@@ long arch_ptrace(struct task_struct *ch
                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)) {
                                /*