Blame view

arch/mips/include/asm/fpu.h 4.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
  /*
   * Copyright (C) 2002 MontaVista Software Inc.
   * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
   */
  #ifndef _ASM_FPU_H
  #define _ASM_FPU_H
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
  #include <linux/sched.h>
  #include <linux/thread_info.h>
1977f0327   Jiri Slaby   remove asm/bitops...
14
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  
  #include <asm/mipsregs.h>
  #include <asm/cpu.h>
  #include <asm/cpu-features.h>
e0cc3a42e   Ralf Baechle   MIPS: math-emu: I...
19
  #include <asm/fpu_emulator.h>
0b6249567   Chris Dearman   [MIPS] FPU hazard...
20
  #include <asm/hazards.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
  #include <asm/processor.h>
  #include <asm/current.h>
33c771ba5   Paul Burton   MIPS: save/disabl...
23
  #include <asm/msa.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

f088fc84f   Ralf Baechle   [MIPS] FPU affini...
25
26
27
  #ifdef CONFIG_MIPS_MT_FPAFF
  #include <asm/mips_mt.h>
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  struct sigcontext;
  struct sigcontext32;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
  extern void _init_fpu(void);
  extern void _save_fp(struct task_struct *);
  extern void _restore_fp(struct task_struct *);
597ce1723   Paul Burton   MIPS: Support for...
33
34
  /*
   * This enum specifies a mode in which we want the FPU to operate, for cores
4227a2d4e   Paul Burton   MIPS: Support for...
35
36
   * which implement the Status.FR bit. Note that the bottom bit of the value
   * purposefully matches the desired value of the Status.FR bit.
597ce1723   Paul Burton   MIPS: Support for...
37
38
39
   */
  enum fpu_mode {
  	FPU_32BIT = 0,		/* FR = 0 */
4227a2d4e   Paul Burton   MIPS: Support for...
40
  	FPU_64BIT,		/* FR = 1, FRE = 0 */
597ce1723   Paul Burton   MIPS: Support for...
41
  	FPU_AS_IS,
4227a2d4e   Paul Burton   MIPS: Support for...
42
43
44
  	FPU_HYBRID,		/* FR = 1, FRE = 1 */
  
  #define FPU_FR_MASK		0x1
597ce1723   Paul Burton   MIPS: Support for...
45
46
47
48
49
50
51
52
53
54
55
56
  };
  
  static inline int __enable_fpu(enum fpu_mode mode)
  {
  	int fr;
  
  	switch (mode) {
  	case FPU_AS_IS:
  		/* just enable the FPU in its current mode */
  		set_c0_status(ST0_CU1);
  		enable_fpu_hazard();
  		return 0;
4227a2d4e   Paul Burton   MIPS: Support for...
57
58
59
60
61
  	case FPU_HYBRID:
  		if (!cpu_has_fre)
  			return SIGFPE;
  
  		/* set FRE */
d33e6fe3c   Ralf Baechle   MIPS: FRE: Use se...
62
  		set_c0_config5(MIPS_CONF5_FRE);
4227a2d4e   Paul Burton   MIPS: Support for...
63
  		goto fr_common;
597ce1723   Paul Burton   MIPS: Support for...
64
  	case FPU_64BIT:
f5868f05d   Paul Bolle   MIPS: Replace CON...
65
  #if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
597ce1723   Paul Burton   MIPS: Support for...
66
67
68
69
70
  		/* we only have a 32-bit FPU */
  		return SIGFPE;
  #endif
  		/* fall through */
  	case FPU_32BIT:
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
71
72
  		if (cpu_has_fre) {
  			/* clear FRE */
d33e6fe3c   Ralf Baechle   MIPS: FRE: Use se...
73
  			clear_c0_config5(MIPS_CONF5_FRE);
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
74
  		}
4227a2d4e   Paul Burton   MIPS: Support for...
75
  fr_common:
597ce1723   Paul Burton   MIPS: Support for...
76
  		/* set CU1 & change FR appropriately */
4227a2d4e   Paul Burton   MIPS: Support for...
77
  		fr = (int)mode & FPU_FR_MASK;
597ce1723   Paul Burton   MIPS: Support for...
78
79
80
81
82
83
84
85
86
  		change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0));
  		enable_fpu_hazard();
  
  		/* check FR has the desired value */
  		return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
  
  	default:
  		BUG();
  	}
97b8b16bf   Aaro Koskinen   MIPS: fpu.h: Fix ...
87
88
  
  	return SIGFPE;
597ce1723   Paul Burton   MIPS: Support for...
89
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
  
  #define __disable_fpu()							\
  do {									\
  	clear_c0_status(ST0_CU1);					\
703422879   Ralf Baechle   MIPS: Whitespace ...
94
  	disable_fpu_hazard();						\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  } while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  #define clear_fpu_owner()	clear_thread_flag(TIF_USEDFPU)
1d74f6bc8   Ralf Baechle   __compute_return_...
97
98
99
100
  static inline int __is_fpu_owner(void)
  {
  	return test_thread_flag(TIF_USEDFPU);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
  static inline int is_fpu_owner(void)
  {
1d74f6bc8   Ralf Baechle   __compute_return_...
103
  	return cpu_has_fpu && __is_fpu_owner();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  }
597ce1723   Paul Burton   MIPS: Support for...
105
  static inline int __own_fpu(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  {
597ce1723   Paul Burton   MIPS: Support for...
107
108
  	enum fpu_mode mode;
  	int ret;
4227a2d4e   Paul Burton   MIPS: Support for...
109
110
111
112
  	if (test_thread_flag(TIF_HYBRID_FPREGS))
  		mode = FPU_HYBRID;
  	else
  		mode = !test_thread_flag(TIF_32BIT_FPREGS);
597ce1723   Paul Burton   MIPS: Support for...
113
114
115
  	ret = __enable_fpu(mode);
  	if (ret)
  		return ret;
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
116
  	KSTK_STATUS(current) |= ST0_CU1;
4227a2d4e   Paul Burton   MIPS: Support for...
117
  	if (mode == FPU_64BIT || mode == FPU_HYBRID)
597ce1723   Paul Burton   MIPS: Support for...
118
119
120
  		KSTK_STATUS(current) |= ST0_FR;
  	else /* mode == FPU_32BIT */
  		KSTK_STATUS(current) &= ~ST0_FR;
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
121
  	set_thread_flag(TIF_USEDFPU);
597ce1723   Paul Burton   MIPS: Support for...
122
  	return 0;
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
123
  }
597ce1723   Paul Burton   MIPS: Support for...
124
  static inline int own_fpu_inatomic(int restore)
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
125
  {
597ce1723   Paul Burton   MIPS: Support for...
126
  	int ret = 0;
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
127
  	if (cpu_has_fpu && !__is_fpu_owner()) {
597ce1723   Paul Burton   MIPS: Support for...
128
129
  		ret = __own_fpu();
  		if (restore && !ret)
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
130
  			_restore_fp(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	}
597ce1723   Paul Burton   MIPS: Support for...
132
  	return ret;
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
133
  }
597ce1723   Paul Burton   MIPS: Support for...
134
  static inline int own_fpu(int restore)
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
135
  {
597ce1723   Paul Burton   MIPS: Support for...
136
  	int ret;
faea62346   Atsushi Nemoto   [MIPS] Retry {sav...
137
  	preempt_disable();
597ce1723   Paul Burton   MIPS: Support for...
138
  	ret = own_fpu_inatomic(restore);
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
139
  	preempt_enable();
597ce1723   Paul Burton   MIPS: Support for...
140
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  }
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
142
  static inline void lose_fpu(int save)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  {
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
144
  	preempt_disable();
33c771ba5   Paul Burton   MIPS: save/disabl...
145
146
147
  	if (is_msa_enabled()) {
  		if (save) {
  			save_msa(current);
842dfc11e   Manuel Lauss   MIPS: Fix build w...
148
149
  			current->thread.fpu.fcr31 =
  					read_32bit_cp1_register(CP1_STATUS);
33c771ba5   Paul Burton   MIPS: save/disabl...
150
151
152
153
  		}
  		disable_msa();
  		clear_thread_flag(TIF_USEDMSA);
  	} else if (is_fpu_owner()) {
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
154
155
  		if (save)
  			_save_fp(current);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
  		__disable_fpu();
  	}
33c771ba5   Paul Burton   MIPS: save/disabl...
158
159
  	KSTK_STATUS(current) &= ~ST0_CU1;
  	clear_thread_flag(TIF_USEDFPU);
53dc80287   Atsushi Nemoto   [MIPS] FPU owners...
160
  	preempt_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  }
597ce1723   Paul Burton   MIPS: Support for...
162
  static inline int init_fpu(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  {
597ce1723   Paul Burton   MIPS: Support for...
164
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  	if (cpu_has_fpu) {
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
166
  		unsigned int config5;
597ce1723   Paul Burton   MIPS: Support for...
167
  		ret = __own_fpu();
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
168
169
  		if (ret)
  			return ret;
4227a2d4e   Paul Burton   MIPS: Support for...
170

b0c34f615   Ralf Baechle   MIPS: Do not fidd...
171
  		if (!cpu_has_fre) {
597ce1723   Paul Burton   MIPS: Support for...
172
  			_init_fpu();
4227a2d4e   Paul Burton   MIPS: Support for...
173

b0c34f615   Ralf Baechle   MIPS: Do not fidd...
174
  			return 0;
4227a2d4e   Paul Burton   MIPS: Support for...
175
  		}
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
176

b0c34f615   Ralf Baechle   MIPS: Do not fidd...
177
178
179
180
181
182
  		/*
  		 * Ensure FRE is clear whilst running _init_fpu, since
  		 * single precision FP instructions are used. If FRE
  		 * was set then we'll just end up initialising all 32
  		 * 64b registers.
  		 */
d33e6fe3c   Ralf Baechle   MIPS: FRE: Use se...
183
  		config5 = clear_c0_config5(MIPS_CONF5_FRE);
b0c34f615   Ralf Baechle   MIPS: Do not fidd...
184
185
186
187
188
189
190
  		enable_fpu_hazard();
  
  		_init_fpu();
  
  		/* Restore FRE */
  		write_c0_config5(config5);
  		enable_fpu_hazard();
e0cc3a42e   Ralf Baechle   MIPS: math-emu: I...
191
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  		fpu_emulator_init_fpu();
597ce1723   Paul Burton   MIPS: Support for...
193

597ce1723   Paul Burton   MIPS: Support for...
194
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
201
202
203
204
205
206
207
  }
  
  static inline void save_fp(struct task_struct *tsk)
  {
  	if (cpu_has_fpu)
  		_save_fp(tsk);
  }
  
  static inline void restore_fp(struct task_struct *tsk)
  {
  	if (cpu_has_fpu)
  		_restore_fp(tsk);
  }
bbd426f54   Paul Burton   MIPS: Simplify FP...
208
  static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  {
e04582b7b   Atsushi Nemoto   [MIPS] Make sure ...
210
211
212
  	if (tsk == current) {
  		preempt_disable();
  		if (is_fpu_owner())
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  			_save_fp(current);
e04582b7b   Atsushi Nemoto   [MIPS] Make sure ...
214
  		preempt_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  	}
eae89076e   Atsushi Nemoto   [MIPS] Unify mips...
216
  	return tsk->thread.fpu.fpr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
  }
  
  #endif /* _ASM_FPU_H */