base/include/asm-x86_64/rtai_lxrt.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1999-2008 Paolo Mantegazza <mantegazza@aero.polimi.it>
00003  * extensions for user space modules are jointly copyrighted (2000) with:
00004  *      Pierre Cloutier <pcloutier@poseidoncontrols.com>,
00005  *      Steve Papacharalambous <stevep@zentropix.com>.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
00019  */
00020 
00021 #ifndef _RTAI_ASM_X8664_LXRT_H
00022 #define _RTAI_ASM_X8664_LXRT_H
00023 
00024 #include <linux/version.h>
00025 
00026 #include <asm/rtai_vectors.h>
00027 
00028 #ifdef CONFIG_RTAI_LXRT_USE_LINUX_SYSCALL
00029 #define USE_LINUX_SYSCALL
00030 #else
00031 #undef USE_LINUX_SYSCALL
00032 #endif
00033 
00034 #ifndef NR_syscalls
00035 #include <asm/asm-offsets.h>
00036 #define NR_syscalls __NR_syscall_max
00037 #endif
00038 
00039 #define RTAI_SYSCALL_NR      0x70000000
00040 
00041 #if defined(__KERNEL__) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
00042 
00043 #define RT_REG_ORIG_AX           orig_ax
00044 #define RT_REG_SP                sp
00045 #define RT_REG_SS                ss
00046 #define RT_REG_FLAGS             flags
00047 #define RT_REG_IP                ip
00048 #define RT_REG_CS                cs
00049 #define RT_REG_BP                bp
00050 #define RT_REG_BX                bx
00051 #define RT_REG_CX                cx
00052 
00053 #define RTAI_SYSCALL_CODE     di
00054 #define RTAI_SYSCALL_ARGS     si
00055 #define RTAI_SYSCALL_RETPNT   dx
00056 
00057 #define LINUX_SYSCALL_NR      RT_REG_ORIG_AX
00058 #define LINUX_SYSCALL_REG1    di
00059 #define LINUX_SYSCALL_REG2    si
00060 #define LINUX_SYSCALL_REG3    dx
00061 #define LINUX_SYSCALL_REG4    r10
00062 #define LINUX_SYSCALL_REG5    r8
00063 #define LINUX_SYSCALL_REG6    r9
00064 #define LINUX_SYSCALL_RETREG  ax
00065 #define LINUX_SYSCALL_FLAGS   RT_REG_FLAGS
00066 
00067 #else
00068 
00069 #define RT_REG_ORIG_AX           orig_rax
00070 #define RT_REG_SP                rsp
00071 #define RT_REG_SS                ss
00072 #define RT_REG_FLAGS             eflags
00073 #define RT_REG_IP                rip
00074 #define RT_REG_CS                cs
00075 #define RT_REG_BP                rbp
00076 #define RT_REG_BX                rbx
00077 #define RT_REG_CX                rcx
00078 
00079 #define RTAI_SYSCALL_CODE     rdi
00080 #define RTAI_SYSCALL_ARGS     rsi
00081 #define RTAI_SYSCALL_RETPNT   rdx
00082 
00083 
00084 #define LINUX_SYSCALL_NR      RT_REG_ORIG_AX
00085 #define LINUX_SYSCALL_REG1    rdi
00086 #define LINUX_SYSCALL_REG2    rsi
00087 #define LINUX_SYSCALL_REG3    rdx
00088 #define LINUX_SYSCALL_REG4    r10
00089 #define LINUX_SYSCALL_REG5    r8
00090 #define LINUX_SYSCALL_REG6    r9
00091 #define LINUX_SYSCALL_RETREG  rax
00092 #define LINUX_SYSCALL_FLAGS   RT_REG_FLAGS
00093 
00094 #endif
00095 
00096 #define LXRT_DO_IMMEDIATE_LINUX_SYSCALL(regs) \
00097     do { \
00098         regs->RT_REG_CX = regs->r10; \
00099         regs->LINUX_SYSCALL_RETREG = ((asmlinkage int (*)(long, ...))sys_call_table[regs->LINUX_SYSCALL_RETREG])(regs->LINUX_SYSCALL_REG1, regs->LINUX_SYSCALL_REG2, regs->LINUX_SYSCALL_REG3, regs->RT_REG_CX, regs->LINUX_SYSCALL_RETREG, regs->r8, regs->r9, regs->r10, regs->r11, regs->RT_REG_BX, regs->RT_REG_BP, regs->r12, regs->r13, regs->r14, regs->r15); \
00100     } while (0)
00101 
00102 #define SET_LXRT_RETVAL_IN_SYSCALL(regs, retval) \
00103     do { \
00104                 if (regs->RTAI_SYSCALL_RETPNT) { \
00105             rt_copy_to_user((void *)regs->RTAI_SYSCALL_RETPNT, &retval, sizeof(retval)); \
00106         } \
00107     } while (0)
00108 
00109 #define LOW  0
00110 #define HIGH 1
00111 
00112 #if defined(CONFIG_RTAI_RTC_FREQ) && CONFIG_RTAI_RTC_FREQ >= 2
00113 
00114 #define TIMER_NAME        "RTC"
00115 #define HRT_LINUX_TIMER_NAME  "rtc"
00116 #define TIMER_FREQ        CONFIG_RTAI_RTC_FREQ
00117 #define TIMER_LATENCY     0
00118 #define TIMER_SETUP_TIME  0
00119 #define ONESHOT_SPAN      0
00120 
00121 #else /* CONFIG_RTAI_RTC_FREQ == 0 */
00122 
00123 #ifdef CONFIG_X86_LOCAL_APIC
00124 
00125 #define TIMER_NAME        "APIC"
00126 #define TIMER_TYPE  1
00127 #define HRT_LINUX_TIMER_NAME  "lapic"
00128 #define FAST_TO_READ_TSC
00129 #define TIMER_FREQ        RTAI_FREQ_APIC
00130 #define TIMER_LATENCY     RTAI_LATENCY_APIC
00131 #define TIMER_SETUP_TIME  RTAI_SETUP_TIME_APIC
00132 #define ONESHOT_SPAN      (CPU_FREQ/(CONFIG_RTAI_CAL_FREQS_FACT + 2)) //(0x7FFFFFFFLL*(CPU_FREQ/TIMER_FREQ))
00133 #ifdef CONFIG_GENERIC_CLOCKEVENTS
00134 #define USE_LINUX_TIMER
00135 #define update_linux_timer(cpuid) \
00136         do { hal_pend_uncond(LOCAL_TIMER_IPI, cpuid); } while (0)
00137 #else /* !CONFIG_GENERIC_CLOCKEVENTS */
00138 #define update_linux_timer(cpuid)
00139 #endif /* CONFIG_GENERIC_CLOCKEVENTS */
00140 
00141 #else /* !CONFIG_X86_LOCAL_APIC */
00142 
00143 #define USE_LINUX_TIMER
00144 #define TIMER_NAME        "8254-PIT"
00145 #define TIMER_TYPE  0
00146 #define HRT_LINUX_TIMER_NAME  "pit"
00147 #define TIMER_FREQ        RTAI_FREQ_8254
00148 #define TIMER_LATENCY     RTAI_LATENCY_8254
00149 #define TIMER_SETUP_TIME  RTAI_SETUP_TIME_8254
00150 #define ONESHOT_SPAN      ((0x7FFF*(CPU_FREQ/TIMER_FREQ))/(CONFIG_RTAI_CAL_FREQS_FACT + 1)) //(0x7FFF*(CPU_FREQ/TIMER_FREQ))
00151 #define update_linux_timer(cpuid)  hal_pend_uncond(TIMER_8254_IRQ, cpuid)
00152 
00153 #endif /* CONFIG_X86_LOCAL_APIC */
00154 
00155 #endif /* CONFIG_RTAI_RTC_FREQ != 0 */
00156 
00157 union rtai_lxrt_t {
00158     RTIME rt;
00159     long i[1];
00160     void *v[1];
00161 };
00162 
00163 #ifdef __cplusplus
00164 extern "C" {
00165 #endif /* __cplusplus */
00166 
00167 #ifdef __KERNEL__
00168 
00169 #include <asm/segment.h>
00170 #include <asm/mmu_context.h>
00171 
00172 static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid)
00173 {
00174     extern void *context_switch(void *, void *, void *);
00175 /* REMARK: the line below is not needed in i386, why should it be so if both
00176    math_restore do a "clts" before orring TS_USEDFPU in status ?????          */
00177     if (task_thread_info(prev)->status & TS_USEDFPU) clts();
00178 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
00179     prev->fpu_counter = 0;
00180 #endif
00181     context_switch(NULL, prev, next);
00182 }
00183 
00184 #if 0
00185 #define IN_INTERCEPT_IRQ_ENABLE()   do { rtai_hw_sti(); } while (0)
00186 #define IN_INTERCEPT_IRQ_DISABLE()  do { rtai_hw_cli(); } while (0)
00187 #else
00188 #define IN_INTERCEPT_IRQ_ENABLE()   do { } while (0)
00189 #define IN_INTERCEPT_IRQ_DISABLE()  do { } while (0)
00190 #endif
00191 
00192 #if 0 // optimised (?)
00193 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00194 {
00195     lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/ + (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP, GFP_KERNEL);
00196     *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00197 //  memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), sizeof(struct thread_info));
00198     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (void *)(lnxtsk->thread.RT_REG_SP), (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP);
00199 }
00200 
00201 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00202 {
00203     lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00204 //  memcpy((void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), sizeof(struct thread_info));
00205     memcpy((void *)lnxtsk->thread.RT_REG_SP, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct)/* + sizeof(struct thread_info)*/, (lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)) + THREAD_SIZE - lnxtsk->thread.RT_REG_SP);
00206 }
00207 #else  // brute force
00208 static inline void kthread_fun_set_jump(struct task_struct *lnxtsk)
00209 {
00210     lnxtsk->rtai_tskext(TSKEXT2) = kmalloc(sizeof(struct thread_struct) + THREAD_SIZE, GFP_KERNEL);
00211     *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2)) = lnxtsk->thread;
00212     memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), THREAD_SIZE);
00213 }
00214 
00215 static inline void kthread_fun_long_jump(struct task_struct *lnxtsk)
00216 {
00217     lnxtsk->thread = *((struct thread_struct *)lnxtsk->rtai_tskext(TSKEXT2));
00218     memcpy((void *)(lnxtsk->thread.RT_REG_SP & ~(THREAD_SIZE - 1)), lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), THREAD_SIZE);
00219 }
00220 #endif
00221 
00222 #define rt_copy_from_user(a, b, c)  \
00223         ( { int ret = __copy_from_user_inatomic(a, b, c); ret; } )
00224 
00225 #define rt_copy_to_user(a, b, c)  \
00226         ( { int ret = __copy_to_user_inatomic(a, b, c); ret; } )
00227 
00228 #define rt_put_user  __put_user
00229 #define rt_get_user  __get_user
00230 
00231 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
00232 
00233 #define rt_strncpy_from_user(a, b, c)  \
00234         ( { int ret = strncpy_from_user(a, b, c); ret; } )
00235 
00236 #else
00237 
00238 /*
00239  * From Linux lib/usercopy.c.
00240  */
00241 
00242 #define __do_strncpy_from_user(dst,src,count,res)              \
00243 do {                                       \
00244     long __d0, __d1, __d2;                         \
00245     __asm__ __volatile__(                          \
00246         "   testq %1,%1\n"                     \
00247         "   jz 2f\n"                       \
00248         "0: lodsb\n"                       \
00249         "   stosb\n"                       \
00250         "   testb %%al,%%al\n"                 \
00251         "   jz 1f\n"                       \
00252         "   decq %1\n"                     \
00253         "   jnz 0b\n"                      \
00254         "1: subq %1,%0\n"                      \
00255         "2:\n"                             \
00256         ".section .fixup,\"ax\"\n"                 \
00257         "3: movq %5,%0\n"                      \
00258         "   jmp 2b\n"                      \
00259         ".previous\n"                          \
00260         ".section __ex_table,\"a\"\n"                  \
00261         "   .align 8\n"                    \
00262         "   .quad 0b,3b\n"                     \
00263         ".previous"                        \
00264         : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),      \
00265           "=&D" (__d2)                         \
00266         : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
00267         : "memory");                           \
00268 } while (0)
00269 
00270 static inline long rt_strncpy_from_user(char *dst, const char __user *src, long count)
00271 {
00272     long res;
00273     __do_strncpy_from_user(dst, src, count, res);
00274     return res;
00275 }
00276 
00277 #endif
00278 
00279 //#define RTAI_DO_LINUX_SIGNAL
00280 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
00281 extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
00282 #define RT_DO_SIGNAL(regs)  do_signal(regs, NULL)
00283 #else
00284 __attribute__((regparm(3))) void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags);
00285 #define RT_DO_SIGNAL(regs)  do_notify_resume(regs, NULL, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK));
00286 #endif
00287 
00288 #else /* !__KERNEL__ */
00289 
00290 /* NOTE: Keep the following routines unfold: this is a compiler
00291    compatibility issue. */
00292 
00293 #include <sys/syscall.h>
00294 #include <unistd.h>
00295 
00296 static union rtai_lxrt_t _rtai_lxrt(long srq, void *arg)
00297 {
00298     union rtai_lxrt_t retval;
00299 #if 1 //def USE_LINUX_SYSCALL
00300     syscall(RTAI_SYSCALL_NR, srq, arg, &retval);
00301 #else
00302     RTAI_DO_TRAP(RTAI_SYS_VECTOR, retval, srq, arg);
00303 #endif
00304     return retval;
00305 }
00306 
00307 static inline union rtai_lxrt_t rtai_lxrt(long dynx, long lsize, long srq, void *arg)
00308 {
00309     return _rtai_lxrt(ENCODE_LXRT_REQ(dynx, srq, lsize), arg);
00310 }
00311 
00312 #define rtai_iopl()  do { extern int iopl(int); iopl(3); } while (0)
00313 
00314 #endif /* __KERNEL__ */
00315 
00316 #ifdef __cplusplus
00317 }
00318 #endif /* __cplusplus */
00319 
00320 #endif /* !_RTAI_ASM_X8664_LXRT_H */

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