1 /* 2 * Copyright (C) 2002 MontaVista Software Inc. 3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 */ 10 #ifndef _ASM_FPU_H 11 #define _ASM_FPU_H 12 13 #include <linux/sched.h> 14 #include <linux/thread_info.h> 15 #include <linux/bitops.h> 16 17 #include <asm/mipsregs.h> 18 #include <asm/cpu.h> 19 #include <asm/cpu-features.h> 20 #include <asm/hazards.h> 21 #include <asm/processor.h> 22 #include <asm/current.h> 23 24 #ifdef CONFIG_MIPS_MT_FPAFF 25 #include <asm/mips_mt.h> 26 #endif 27 28 struct sigcontext; 29 struct sigcontext32; 30 31 extern void fpu_emulator_init_fpu(void); 32 extern void _init_fpu(void); 33 extern void _save_fp(struct task_struct *); 34 extern void _restore_fp(struct task_struct *); 35 36 #define __enable_fpu() \ 37 do { \ 38 set_c0_status(ST0_CU1); \ 39 enable_fpu_hazard(); \ 40 } while (0) 41 42 #define __disable_fpu() \ 43 do { \ 44 clear_c0_status(ST0_CU1); \ 45 disable_fpu_hazard(); \ 46 } while (0) 47 48 #define enable_fpu() \ 49 do { \ 50 if (cpu_has_fpu) \ 51 __enable_fpu(); \ 52 } while (0) 53 54 #define disable_fpu() \ 55 do { \ 56 if (cpu_has_fpu) \ 57 __disable_fpu(); \ 58 } while (0) 59 60 61 #define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) 62 __is_fpu_owner(void)63static inline int __is_fpu_owner(void) 64 { 65 return test_thread_flag(TIF_USEDFPU); 66 } 67 is_fpu_owner(void)68static inline int is_fpu_owner(void) 69 { 70 return cpu_has_fpu && __is_fpu_owner(); 71 } 72 __own_fpu(void)73static inline void __own_fpu(void) 74 { 75 __enable_fpu(); 76 KSTK_STATUS(current) |= ST0_CU1; 77 set_thread_flag(TIF_USEDFPU); 78 } 79 own_fpu_inatomic(int restore)80static inline void own_fpu_inatomic(int restore) 81 { 82 if (cpu_has_fpu && !__is_fpu_owner()) { 83 __own_fpu(); 84 if (restore) 85 _restore_fp(current); 86 } 87 } 88 own_fpu(int restore)89static inline void own_fpu(int restore) 90 { 91 preempt_disable(); 92 own_fpu_inatomic(restore); 93 preempt_enable(); 94 } 95 lose_fpu(int save)96static inline void lose_fpu(int save) 97 { 98 preempt_disable(); 99 if (is_fpu_owner()) { 100 if (save) 101 _save_fp(current); 102 KSTK_STATUS(current) &= ~ST0_CU1; 103 clear_thread_flag(TIF_USEDFPU); 104 __disable_fpu(); 105 } 106 preempt_enable(); 107 } 108 init_fpu(void)109static inline void init_fpu(void) 110 { 111 preempt_disable(); 112 if (cpu_has_fpu) { 113 __own_fpu(); 114 _init_fpu(); 115 } else { 116 fpu_emulator_init_fpu(); 117 } 118 preempt_enable(); 119 } 120 save_fp(struct task_struct * tsk)121static inline void save_fp(struct task_struct *tsk) 122 { 123 if (cpu_has_fpu) 124 _save_fp(tsk); 125 } 126 restore_fp(struct task_struct * tsk)127static inline void restore_fp(struct task_struct *tsk) 128 { 129 if (cpu_has_fpu) 130 _restore_fp(tsk); 131 } 132 get_fpu_regs(struct task_struct * tsk)133static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) 134 { 135 if (tsk == current) { 136 preempt_disable(); 137 if (is_fpu_owner()) 138 _save_fp(current); 139 preempt_enable(); 140 } 141 142 return tsk->thread.fpu.fpr; 143 } 144 145 #endif /* _ASM_FPU_H */ 146