Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.21-rc7 179 lines 3.8 kB view raw
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 16#include <asm/mipsregs.h> 17#include <asm/cpu.h> 18#include <asm/cpu-features.h> 19#include <asm/bitops.h> 20#include <asm/processor.h> 21#include <asm/current.h> 22 23#ifdef CONFIG_MIPS_MT_FPAFF 24#include <asm/mips_mt.h> 25#endif 26 27struct sigcontext; 28struct sigcontext32; 29 30extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); 31extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); 32 33extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); 34extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); 35 36extern void fpu_emulator_init_fpu(void); 37extern void _init_fpu(void); 38extern void _save_fp(struct task_struct *); 39extern void _restore_fp(struct task_struct *); 40 41#if defined(CONFIG_CPU_SB1) 42#define __enable_fpu_hazard() \ 43do { \ 44 asm(".set push \n\t" \ 45 ".set mips64 \n\t" \ 46 ".set noreorder \n\t" \ 47 "ssnop \n\t" \ 48 "bnezl $0, .+4 \n\t" \ 49 "ssnop \n\t" \ 50 ".set pop"); \ 51} while (0) 52#else 53#define __enable_fpu_hazard() \ 54do { \ 55 asm("nop;nop;nop;nop"); /* max. hazard */ \ 56} while (0) 57#endif 58 59#define __enable_fpu() \ 60do { \ 61 set_c0_status(ST0_CU1); \ 62 __enable_fpu_hazard(); \ 63} while (0) 64 65#define __disable_fpu() \ 66do { \ 67 clear_c0_status(ST0_CU1); \ 68 /* We don't care about the c0 hazard here */ \ 69} while (0) 70 71#define __fpu_enabled() (read_c0_status() & ST0_CU1) 72 73#define enable_fpu() \ 74do { \ 75 if (cpu_has_fpu) \ 76 __enable_fpu(); \ 77} while (0) 78 79#define disable_fpu() \ 80do { \ 81 if (cpu_has_fpu) \ 82 __disable_fpu(); \ 83} while (0) 84 85 86#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) 87 88static inline int __is_fpu_owner(void) 89{ 90 return test_thread_flag(TIF_USEDFPU); 91} 92 93static inline int is_fpu_owner(void) 94{ 95 return cpu_has_fpu && __is_fpu_owner(); 96} 97 98static inline void __own_fpu(void) 99{ 100 __enable_fpu(); 101 KSTK_STATUS(current) |= ST0_CU1; 102 set_thread_flag(TIF_USEDFPU); 103} 104 105static 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); 112 } 113 preempt_enable(); 114} 115 116static inline void lose_fpu(int save) 117{ 118 preempt_disable(); 119 if (is_fpu_owner()) { 120 if (save) 121 _save_fp(current); 122 KSTK_STATUS(current) &= ~ST0_CU1; 123 clear_thread_flag(TIF_USEDFPU); 124 __disable_fpu(); 125 } 126 preempt_enable(); 127} 128 129static inline void init_fpu(void) 130{ 131 preempt_disable(); 132 if (cpu_has_fpu) { 133 __own_fpu(); 134 _init_fpu(); 135 } else { 136 fpu_emulator_init_fpu(); 137 } 138 preempt_enable(); 139} 140 141static inline void save_fp(struct task_struct *tsk) 142{ 143 if (cpu_has_fpu) 144 _save_fp(tsk); 145} 146 147static inline void restore_fp(struct task_struct *tsk) 148{ 149 if (cpu_has_fpu) 150 _restore_fp(tsk); 151} 152 153static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) 154{ 155 if (tsk == current) { 156 preempt_disable(); 157 if (is_fpu_owner()) 158 _save_fp(current); 159 preempt_enable(); 160 } 161 162 return tsk->thread.fpu.fpr; 163} 164 165static 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 173static 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 179#endif /* _ASM_FPU_H */