00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00138 #define update_linux_timer(cpuid)
00139 #endif
00140
00141 #else
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
00154
00155 #endif
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
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
00176
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) + (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
00198 memcpy(lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (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
00205 memcpy((void *)lnxtsk->thread.RT_REG_SP, lnxtsk->rtai_tskext(TSKEXT2) + sizeof(struct thread_struct), (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
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
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
00289
00290
00291
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
00315
00316 #ifdef __cplusplus
00317 }
00318 #endif
00319
00320 #endif