diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-03-09 11:07:45 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-03-16 21:03:26 -0400 |
commit | 53dc80287da43b75df2fe2658651d3c5160dad8e (patch) | |
tree | 3c4c97534c379709cd2a1dae5b90df626349f21d /include | |
parent | c6a2f4679331206ef5d353fc9a6cda2fa4aef8c6 (diff) |
[MIPS] FPU ownership management & preemption fixes
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-mips/cpu-features.h | 3 | ||||
-rw-r--r-- | include/asm-mips/cpu-info.h | 1 | ||||
-rw-r--r-- | include/asm-mips/fpu.h | 54 | ||||
-rw-r--r-- | include/asm-mips/thread_info.h | 1 |
4 files changed, 48 insertions, 11 deletions
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h index eadca266f159..5e4bed123b48 100644 --- a/include/asm-mips/cpu-features.h +++ b/include/asm-mips/cpu-features.h | |||
@@ -40,6 +40,9 @@ | |||
40 | #endif | 40 | #endif |
41 | #ifndef cpu_has_fpu | 41 | #ifndef cpu_has_fpu |
42 | #define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) | 42 | #define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) |
43 | #define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU) | ||
44 | #else | ||
45 | #define raw_cpu_has_fpu cpu_has_fpu | ||
43 | #endif | 46 | #endif |
44 | #ifndef cpu_has_32fpr | 47 | #ifndef cpu_has_32fpr |
45 | #define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) | 48 | #define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) |
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index 610d0cdeaa9e..22fe8453fcc7 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h | |||
@@ -87,6 +87,7 @@ struct cpuinfo_mips { | |||
87 | 87 | ||
88 | extern struct cpuinfo_mips cpu_data[]; | 88 | extern struct cpuinfo_mips cpu_data[]; |
89 | #define current_cpu_data cpu_data[smp_processor_id()] | 89 | #define current_cpu_data cpu_data[smp_processor_id()] |
90 | #define raw_current_cpu_data cpu_data[raw_smp_processor_id()] | ||
90 | 91 | ||
91 | extern void cpu_probe(void); | 92 | extern void cpu_probe(void); |
92 | extern void cpu_report(void); | 93 | extern void cpu_report(void); |
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h index efef843b93f0..4e12d1f9534f 100644 --- a/include/asm-mips/fpu.h +++ b/include/asm-mips/fpu.h | |||
@@ -27,11 +27,11 @@ | |||
27 | struct sigcontext; | 27 | struct sigcontext; |
28 | struct sigcontext32; | 28 | struct sigcontext32; |
29 | 29 | ||
30 | extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); | 30 | extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); |
31 | extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); | 31 | extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); |
32 | 32 | ||
33 | extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); | 33 | extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); |
34 | extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); | 34 | extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); |
35 | 35 | ||
36 | extern void fpu_emulator_init_fpu(void); | 36 | extern void fpu_emulator_init_fpu(void); |
37 | extern void _init_fpu(void); | 37 | extern void _init_fpu(void); |
@@ -68,6 +68,8 @@ do { \ | |||
68 | /* We don't care about the c0 hazard here */ \ | 68 | /* We don't care about the c0 hazard here */ \ |
69 | } while (0) | 69 | } while (0) |
70 | 70 | ||
71 | #define __fpu_enabled() (read_c0_status() & ST0_CU1) | ||
72 | |||
71 | #define enable_fpu() \ | 73 | #define enable_fpu() \ |
72 | do { \ | 74 | do { \ |
73 | if (cpu_has_fpu) \ | 75 | if (cpu_has_fpu) \ |
@@ -93,31 +95,47 @@ static inline int is_fpu_owner(void) | |||
93 | return cpu_has_fpu && __is_fpu_owner(); | 95 | return cpu_has_fpu && __is_fpu_owner(); |
94 | } | 96 | } |
95 | 97 | ||
96 | static inline void own_fpu(void) | 98 | static inline void __own_fpu(void) |
97 | { | 99 | { |
98 | if (cpu_has_fpu) { | 100 | __enable_fpu(); |
99 | __enable_fpu(); | 101 | KSTK_STATUS(current) |= ST0_CU1; |
100 | KSTK_STATUS(current) |= ST0_CU1; | 102 | set_thread_flag(TIF_USEDFPU); |
101 | set_thread_flag(TIF_USEDFPU); | 103 | } |
104 | |||
105 | static inline void own_fpu(int restore) | ||
106 | { | ||
107 | preempt_disable(); | ||
108 | if (cpu_has_fpu && !__is_fpu_owner()) { | ||
109 | __own_fpu(); | ||
110 | if (restore) | ||
111 | _restore_fp(current); | ||
102 | } | 112 | } |
113 | preempt_enable(); | ||
103 | } | 114 | } |
104 | 115 | ||
105 | static inline void lose_fpu(void) | 116 | static inline void lose_fpu(int save) |
106 | { | 117 | { |
107 | if (cpu_has_fpu) { | 118 | preempt_disable(); |
119 | if (is_fpu_owner()) { | ||
120 | if (save) | ||
121 | _save_fp(current); | ||
108 | KSTK_STATUS(current) &= ~ST0_CU1; | 122 | KSTK_STATUS(current) &= ~ST0_CU1; |
109 | clear_thread_flag(TIF_USEDFPU); | 123 | clear_thread_flag(TIF_USEDFPU); |
110 | __disable_fpu(); | 124 | __disable_fpu(); |
111 | } | 125 | } |
126 | preempt_enable(); | ||
112 | } | 127 | } |
113 | 128 | ||
114 | static inline void init_fpu(void) | 129 | static inline void init_fpu(void) |
115 | { | 130 | { |
131 | preempt_disable(); | ||
116 | if (cpu_has_fpu) { | 132 | if (cpu_has_fpu) { |
133 | __own_fpu(); | ||
117 | _init_fpu(); | 134 | _init_fpu(); |
118 | } else { | 135 | } else { |
119 | fpu_emulator_init_fpu(); | 136 | fpu_emulator_init_fpu(); |
120 | } | 137 | } |
138 | preempt_enable(); | ||
121 | } | 139 | } |
122 | 140 | ||
123 | static inline void save_fp(struct task_struct *tsk) | 141 | static inline void save_fp(struct task_struct *tsk) |
@@ -144,4 +162,18 @@ static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) | |||
144 | return tsk->thread.fpu.fpr; | 162 | return tsk->thread.fpu.fpr; |
145 | } | 163 | } |
146 | 164 | ||
165 | static inline void enable_fp_in_kernel(void) | ||
166 | { | ||
167 | set_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
168 | /* make sure CU1 and FPU ownership are consistent */ | ||
169 | if (!__is_fpu_owner() && __fpu_enabled()) | ||
170 | __disable_fpu(); | ||
171 | } | ||
172 | |||
173 | static inline void disable_fp_in_kernel(void) | ||
174 | { | ||
175 | BUG_ON(!__is_fpu_owner() && __fpu_enabled()); | ||
176 | clear_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
177 | } | ||
178 | |||
147 | #endif /* _ASM_FPU_H */ | 179 | #endif /* _ASM_FPU_H */ |
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index fbcda8204473..6cf05f4a4e7e 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h | |||
@@ -119,6 +119,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); | |||
119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
120 | #define TIF_MEMDIE 18 | 120 | #define TIF_MEMDIE 18 |
121 | #define TIF_FREEZE 19 | 121 | #define TIF_FREEZE 19 |
122 | #define TIF_ALLOW_FP_IN_KERNEL 20 | ||
122 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ | 123 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ |
123 | 124 | ||
124 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 125 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |