--- zzzz-none-000/linux-3.10.107/arch/mips/include/asm/fpu.h 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/arch/mips/include/asm/fpu.h 2021-11-10 11:53:53.000000000 +0000 @@ -29,35 +29,20 @@ struct sigcontext32; extern void fpu_emulator_init_fpu(void); -extern void _init_fpu(void); +extern int _init_fpu(void); extern void _save_fp(struct task_struct *); extern void _restore_fp(struct task_struct *); -#define __enable_fpu() \ +/* + * This macro is used only to obtain FIR from FPU and it seems + * like a BUG in 34K with single FPU affinity to VPE0. + */ +#define __enable_fpu() \ do { \ set_c0_status(ST0_CU1); \ enable_fpu_hazard(); \ } while (0) -#define __disable_fpu() \ -do { \ - clear_c0_status(ST0_CU1); \ - disable_fpu_hazard(); \ -} while (0) - -#define enable_fpu() \ -do { \ - if (cpu_has_fpu) \ - __enable_fpu(); \ -} while (0) - -#define disable_fpu() \ -do { \ - if (cpu_has_fpu) \ - __disable_fpu(); \ -} while (0) - - #define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) static inline int __is_fpu_owner(void) @@ -70,27 +55,58 @@ return cpu_has_fpu && __is_fpu_owner(); } -static inline void __own_fpu(void) +static inline int __own_fpu(void) { - __enable_fpu(); + int ret = 0; + +#if defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_MIPS64) + if (test_thread_flag(TIF_32BIT_REGS)) { + change_c0_status(ST0_CU1|ST0_FR,ST0_CU1); + KSTK_STATUS(current) |= ST0_CU1; + KSTK_STATUS(current) &= ~ST0_FR; + enable_fpu_hazard(); + if (read_c0_status() & ST0_FR) + ret = SIGFPE; + } else { + set_c0_status(ST0_CU1|ST0_FR); + KSTK_STATUS(current) |= ST0_CU1|ST0_FR; + enable_fpu_hazard(); + if (!(read_c0_status() & ST0_FR)) + ret = SIGFPE; + } +#else + if (!test_thread_flag(TIF_32BIT_REGS)) + return SIGFPE; /* core has no 64bit FPU, so ... */ + + set_c0_status(ST0_CU1); KSTK_STATUS(current) |= ST0_CU1; + enable_fpu_hazard(); +#endif set_thread_flag(TIF_USEDFPU); + return ret; } -static inline void own_fpu_inatomic(int restore) +static inline int own_fpu_inatomic(int restore) { + int ret = 0; + if (cpu_has_fpu && !__is_fpu_owner()) { - __own_fpu(); - if (restore) + ret =__own_fpu(); + if (restore && !ret) _restore_fp(current); } + return ret; } -static inline void own_fpu(int restore) +static inline int own_fpu(int restore) { + int ret; + preempt_disable(); - own_fpu_inatomic(restore); + ret = own_fpu_inatomic(restore); preempt_enable(); + + return ret; } static inline void lose_fpu(int save) @@ -101,21 +117,25 @@ _save_fp(current); KSTK_STATUS(current) &= ~ST0_CU1; clear_thread_flag(TIF_USEDFPU); - __disable_fpu(); + clear_c0_status(ST0_CU1); + disable_fpu_hazard(); } preempt_enable(); } -static inline void init_fpu(void) +static inline int init_fpu(void) { + int ret = 0; + preempt_disable(); - if (cpu_has_fpu) { - __own_fpu(); + if (cpu_has_fpu && !(ret = __own_fpu())) _init_fpu(); - } else { + else fpu_emulator_init_fpu(); - } + preempt_enable(); + + return ret; } static inline void save_fp(struct task_struct *tsk)