#include <asm/mipsregs.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/hazards.h>
#include <asm/bitops.h>
#include <asm/processor.h>
#include <asm/current.h>
struct sigcontext;
struct sigcontext32;
-extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
-extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
+extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
-extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc);
-extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc);
+extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
+extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
extern void fpu_emulator_init_fpu(void);
extern void _init_fpu(void);
extern void _save_fp(struct task_struct *);
extern void _restore_fp(struct task_struct *);
-#if defined(CONFIG_CPU_SB1)
-#define __enable_fpu_hazard() \
-do { \
- asm(".set push \n\t" \
- ".set mips64 \n\t" \
- ".set noreorder \n\t" \
- "ssnop \n\t" \
- "bnezl $0, .+4 \n\t" \
- "ssnop \n\t" \
- ".set pop"); \
-} while (0)
-#else
-#define __enable_fpu_hazard() \
-do { \
- asm("nop;nop;nop;nop"); /* max. hazard */ \
-} while (0)
-#endif
-
#define __enable_fpu() \
do { \
set_c0_status(ST0_CU1); \
- __enable_fpu_hazard(); \
+ enable_fpu_hazard(); \
} while (0)
#define __disable_fpu() \
do { \
clear_c0_status(ST0_CU1); \
- /* We don't care about the c0 hazard here */ \
+ disable_fpu_hazard(); \
} while (0)
#define enable_fpu() \
return cpu_has_fpu && __is_fpu_owner();
}
-static inline void own_fpu(void)
+static inline void __own_fpu(void)
{
- if (cpu_has_fpu) {
- __enable_fpu();
- KSTK_STATUS(current) |= ST0_CU1;
- set_thread_flag(TIF_USEDFPU);
+ __enable_fpu();
+ KSTK_STATUS(current) |= ST0_CU1;
+ set_thread_flag(TIF_USEDFPU);
+}
+
+static inline void own_fpu_inatomic(int restore)
+{
+ if (cpu_has_fpu && !__is_fpu_owner()) {
+ __own_fpu();
+ if (restore)
+ _restore_fp(current);
}
}
-static inline void lose_fpu(void)
+static inline void own_fpu(int restore)
{
- if (cpu_has_fpu) {
+ preempt_disable();
+ own_fpu_inatomic(restore);
+ preempt_enable();
+}
+
+static inline void lose_fpu(int save)
+{
+ preempt_disable();
+ if (is_fpu_owner()) {
+ if (save)
+ _save_fp(current);
KSTK_STATUS(current) &= ~ST0_CU1;
clear_thread_flag(TIF_USEDFPU);
__disable_fpu();
}
+ preempt_enable();
}
static inline void init_fpu(void)
{
+ preempt_disable();
if (cpu_has_fpu) {
+ __own_fpu();
_init_fpu();
} else {
fpu_emulator_init_fpu();
}
+ preempt_enable();
}
static inline void save_fp(struct task_struct *tsk)
static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
{
- if (cpu_has_fpu) {
- if ((tsk == current) && __is_fpu_owner())
+ if (tsk == current) {
+ preempt_disable();
+ if (is_fpu_owner())
_save_fp(current);
+ preempt_enable();
}
return tsk->thread.fpu.fpr;