base/include/asm-x86_64/rtai_fpu.h

Go to the documentation of this file.
00001 /*
00002  *   ARTI -- RTAI-compatible Adeos-based Real-Time Interface. Based on
00003  *   the original RTAI layer for x86.
00004  *
00005  *   Copyright (C) 1994 Linus Torvalds
00006  *   Copyright (C) 2000 Gareth Hughes <gareth@valinux.com>,
00007  *   Copyright (C) 2000 Pierre Cloutier <pcloutier@PoseidonControls.com>
00008  *   and others.
00009  *
00010  *   Porting to x86_64 architecture:
00011  *   Copyright &copy; 2005-2008 Paolo Mantegazza, \n
00012  *   Copyright &copy; 2005 Daniele Gasperini \n
00013  *
00014  *   This program is free software; you can redistribute it and/or modify
00015  *   it under the terms of the GNU General Public License as published by
00016  *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
00017  *   USA; either version 2 of the License, or (at your option) any later
00018  *   version.
00019  *
00020  *   This program is distributed in the hope that it will be useful,
00021  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *   GNU General Public License for more details.
00024  *
00025  *   You should have received a copy of the GNU General Public License
00026  *   along with this program; if not, write to the Free Software
00027  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00028  */
00029 
00030 #ifndef _RTAI_ASM_X8664_FPU_H
00031 #define _RTAI_ASM_X8664_FPU_H
00032 
00033 #ifndef __cplusplus
00034 #include <asm/processor.h>
00035 #endif /* !__cplusplus */
00036 
00037 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
00038 typedef union i387_union FPU_ENV;
00039 #define TASK_FPENV(tsk)  (&(tsk)->thread.i387.fxsave)
00040 #else
00041 typedef union thread_xstate FPU_ENV;
00042 #define TASK_FPENV(tsk)  (&(tsk)->thread.xstate->fxsave)
00043 #endif
00044    
00045 #ifdef CONFIG_RTAI_FPU_SUPPORT
00046 
00047 // RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL
00048 
00049 #define enable_fpu()  do { \
00050     __asm__ __volatile__ ("clts"); \
00051 } while(0)
00052 
00053 #define save_fpcr_and_enable_fpu(fpcr)  do { \
00054     fpcr = read_cr0(); \
00055     enable_fpu(); \
00056 } while (0)
00057 
00058 #define restore_fpcr(fpcr)  do { \
00059     if (fpcr & 8) { \
00060         unsigned long flags; \
00061         rtai_hw_save_flags_and_cli(flags); \
00062         fpcr = read_cr0(); \
00063         write_cr0(8 | fpcr); \
00064         rtai_hw_restore_flags(flags); \
00065     } \
00066 } while (0)
00067 
00068 // initialise the hard fpu unit directly
00069 #define init_hard_fpenv() do { \
00070     unsigned long __mxcsr; \
00071     __asm__ __volatile__ ("clts; fninit"); \
00072     __mxcsr = 0xffbfUL & 0x1f80UL; \
00073     __asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \
00074 } while (0)
00075 
00076 // initialise the given fpenv union, without touching the related hard fpu unit
00077 #define __init_fpenv(fpenv)  do { \
00078     memset(fpenv, 0, sizeof(struct i387_fxsave_struct)); \
00079     (fpenv)->cwd = 0x37f; \
00080     (fpenv)->mxcsr = 0x1f80; \
00081 } while (0)
00082 
00083 /* taken from Linux i387.h */
00084 
00085 static inline int __save_fpenv(struct i387_fxsave_struct __user *fx) 
00086 { 
00087     int err;
00088 
00089     asm volatile("1:  rex64/fxsave (%[fx])\n\t"
00090              "2:\n"
00091              ".section .fixup,\"ax\"\n"
00092              "3:  movl $-1,%[err]\n"
00093              "    jmp  2b\n"
00094              ".previous\n"
00095              ".section __ex_table,\"a\"\n"
00096              "   .align 8\n"
00097              "   .quad  1b,3b\n"
00098              ".previous"
00099              : [err] "=r" (err), "=m" (*fx)
00100              : [fx] "cdaSDb" (fx), "0" (0));
00101 
00102     return err;
00103 } 
00104 
00105 static inline int __restore_fpenv(struct i387_fxsave_struct *fx) 
00106 { 
00107     int err;
00108 
00109     asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
00110              "2:\n"
00111              ".section .fixup,\"ax\"\n"
00112              "3:  movl $-1,%[err]\n"
00113              "    jmp  2b\n"
00114              ".previous\n"
00115              ".section __ex_table,\"a\"\n"
00116              "   .align 8\n"
00117              "   .quad  1b,3b\n"
00118              ".previous"
00119              : [err] "=r" (err)
00120              : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
00121 
00122     return err;
00123 } 
00124 
00125 #define init_fpenv(fpenv)     do { __init_fpenv(&(fpenv).fxsave); } while (0)
00126 #define save_fpenv(fpenv)     do { __save_fpenv(&(fpenv).fxsave); } while (0)
00127 #define restore_fpenv(fpenv)  do { __restore_fpenv(&(fpenv).fxsave); } while (0)
00128 
00129 // FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI
00130 
00131 #define init_hard_fpu(lnxtsk)  do { \
00132     init_hard_fpenv(); \
00133     set_lnxtsk_uses_fpu(lnxtsk); \
00134     set_lnxtsk_using_fpu(lnxtsk); \
00135 } while (0)
00136 
00137 #define init_fpu(lnxtsk)  do { \
00138     __init_fpenv(TASK_FPENV(lnxtsk)); \
00139     set_lnxtsk_uses_fpu(lnxtsk); \
00140 } while (0)
00141 
00142 #define restore_fpu(lnxtsk)  do { \
00143     enable_fpu(); \
00144     __restore_fpenv(TASK_FPENV(lnxtsk)); \
00145     set_lnxtsk_using_fpu(lnxtsk); \
00146 } while (0)
00147 
00148 #else /* !CONFIG_RTAI_FPU_SUPPORT */
00149 
00150 #define enable_fpu()
00151 #define save_fpcr_and_enable_fpu(fpcr)
00152 #define restore_fpcr(fpcr)
00153 #define init_hard_fpenv()
00154 #define init_fpenv(fpenv)
00155 #define save_fpenv(fpenv)
00156 #define restore_fpenv(fpenv)
00157 #define init_hard_fpu(lnxtsk)
00158 #define init_fpu(lnxtsk)
00159 #define restore_fpu(lnxtsk)
00160 
00161 #endif /* CONFIG_RTAI_FPU_SUPPORT */
00162 
00163 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
00164 
00165 #define set_lnxtsk_uses_fpu(lnxtsk) \
00166         do { (lnxtsk)->used_math = 1; } while(0)
00167 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00168         do { (lnxtsk)->used_math = 0; } while(0)
00169 #define lnxtsk_uses_fpu(lnxtsk)  ((lnxtsk)->used_math)
00170 
00171 #define set_lnxtsk_using_fpu(lnxtsk) \
00172     do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00173 //  do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
00174 
00175 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) */
00176 
00177 
00178 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
00179 
00180 #define set_lnxtsk_uses_fpu(lnxtsk) \
00181         do { set_stopped_child_used_math(lnxtsk); } while(0)
00182 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00183         do { clear_stopped_child_used_math(lnxtsk); } while(0)
00184 #define lnxtsk_uses_fpu(lnxtsk)  (tsk_used_math(lnxtsk))
00185 
00186 #define set_lnxtsk_using_fpu(lnxtsk) \
00187     do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00188 //  do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
00189 
00190 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) */
00191 
00192 #endif /* !_RTAI_ASM_X8664_FPU_H */

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7