syscall.h

00001 /*
00002  * Copyright (C) 2001,2002,2003,2004 Philippe Gerum <rpm@xenomai.org>.
00003  *
00004  * RTAI/fusion is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published
00006  * by the Free Software Foundation; either version 2 of the License,
00007  * or (at your option) any later version.
00008  *
00009  * RTAI/fusion is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with RTAI/fusion; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00017  * 02111-1307, USA.
00018  */
00019 
00020 #ifndef _RTAI_ASM_PPC_SYSCALL_H
00021 #define _RTAI_ASM_PPC_SYSCALL_H
00022 
00023 #include <rtai_config.h>
00024 #include <asm/ptrace.h>
00025 #include <nucleus/asm-generic/syscall.h>
00026 
00027 /*
00028  * Some of the following macros have been adapted from Linux's
00029  * implementation of the syscall mechanism in <asm-ppc/unistd.h>:
00030  *
00031  * The following code defines an inline syscall mechanism used by
00032  * RTAI/fusion's real-time interfaces to invoke the skin module
00033  * services in kernel space.
00034  */
00035 
00036 #define XENOMAI_DO_SYSCALL(nr, id, op, args...)                 \
00037   ({                                                            \
00038         register unsigned long __sc_0  __asm__ ("r0");          \
00039         register unsigned long __sc_3  __asm__ ("r3");          \
00040         register unsigned long __sc_4  __asm__ ("r4");          \
00041         register unsigned long __sc_5  __asm__ ("r5");          \
00042         register unsigned long __sc_6  __asm__ ("r6");          \
00043         register unsigned long __sc_7  __asm__ ("r7");          \
00044                                                                 \
00045         LOADARGS_##nr(__xn_mux_code(id,op), args);              \
00046         __asm__ __volatile__                                    \
00047                 ("sc           \n\t"                            \
00048                  "mfcr %0      "                                \
00049                 : "=&r" (__sc_0),                               \
00050                   "=&r" (__sc_3),  "=&r" (__sc_4),              \
00051                   "=&r" (__sc_5),  "=&r" (__sc_6),              \
00052                   "=&r" (__sc_7)                                \
00053                 : ASM_INPUT_##nr                                \
00054                 : "cr0", "ctr", "memory",                       \
00055                   "r8", "r9", "r10","r11", "r12");              \
00056         (int)((__sc_0 & (1 << 28)) ? -__sc_3 : __sc_3);         \
00057   })
00058 
00059 #define LOADARGS_0(muxcode, dummy...)                           \
00060         __sc_0 = muxcode
00061 #define LOADARGS_1(muxcode, arg1)                               \
00062         LOADARGS_0(muxcode);                                    \
00063         __sc_3 = (unsigned long) (arg1)
00064 #define LOADARGS_2(muxcode, arg1, arg2)                         \
00065         LOADARGS_1(muxcode, arg1);                              \
00066         __sc_4 = (unsigned long) (arg2)
00067 #define LOADARGS_3(muxcode, arg1, arg2, arg3)                   \
00068         LOADARGS_2(muxcode, arg1, arg2);                        \
00069         __sc_5 = (unsigned long) (arg3)
00070 #define LOADARGS_4(muxcode, arg1, arg2, arg3, arg4)             \
00071         LOADARGS_3(muxcode, arg1, arg2, arg3);                  \
00072         __sc_6 = (unsigned long) (arg4)
00073 #define LOADARGS_5(muxcode, arg1, arg2, arg3, arg4, arg5)       \
00074         LOADARGS_4(muxcode, arg1, arg2, arg3, arg4);            \
00075         __sc_7 = (unsigned long) (arg5)
00076 
00077 #define ASM_INPUT_0 "0" (__sc_0)
00078 #define ASM_INPUT_1 ASM_INPUT_0, "1" (__sc_3)
00079 #define ASM_INPUT_2 ASM_INPUT_1, "2" (__sc_4)
00080 #define ASM_INPUT_3 ASM_INPUT_2, "3" (__sc_5)
00081 #define ASM_INPUT_4 ASM_INPUT_3, "4" (__sc_6)
00082 #define ASM_INPUT_5 ASM_INPUT_4, "5" (__sc_7)
00083 
00084 /* Register mapping for accessing syscall args. */
00085 
00086 #define __xn_reg_mux(regs)    ((regs)->gpr[0])
00087 #define __xn_reg_rval(regs)   ((regs)->gpr[3])
00088 #define __xn_reg_arg1(regs)   ((regs)->gpr[3])
00089 #define __xn_reg_arg2(regs)   ((regs)->gpr[4])
00090 #define __xn_reg_arg3(regs)   ((regs)->gpr[5])
00091 #define __xn_reg_arg4(regs)   ((regs)->gpr[6])
00092 #define __xn_reg_arg5(regs)   ((regs)->gpr[7])
00093 
00094 #define __xn_reg_mux_p(regs)        ((__xn_reg_mux(regs) & 0xffff) == __xn_sys_mux)
00095 #define __xn_mux_id(regs)           ((__xn_reg_mux(regs) >> 16) & 0xff)
00096 #define __xn_mux_op(regs)           ((__xn_reg_mux(regs) >> 24) & 0xff)
00097 #define __xn_mux_code(id,op)        ((op << 24)|((id << 16) & 0xff0000)|(__xn_sys_mux & 0xffff))
00098 
00099 #define XENOMAI_SYSCALL0(op)                XENOMAI_DO_SYSCALL(0,0,op)
00100 #define XENOMAI_SYSCALL1(op,a1)             XENOMAI_DO_SYSCALL(1,0,op,a1)
00101 #define XENOMAI_SYSCALL2(op,a1,a2)          XENOMAI_DO_SYSCALL(2,0,op,a1,a2)
00102 #define XENOMAI_SYSCALL3(op,a1,a2,a3)       XENOMAI_DO_SYSCALL(3,0,op,a1,a2,a3)
00103 #define XENOMAI_SYSCALL4(op,a1,a2,a3,a4)    XENOMAI_DO_SYSCALL(4,0,op,a1,a2,a3,a4)
00104 #define XENOMAI_SYSCALL5(op,a1,a2,a3,a4,a5) XENOMAI_DO_SYSCALL(5,0,op,a1,a2,a3,a4,a5)
00105 
00106 #define XENOMAI_SKINCALL0(id,op)                XENOMAI_DO_SYSCALL(0,id,op)
00107 #define XENOMAI_SKINCALL1(id,op,a1)             XENOMAI_DO_SYSCALL(1,id,op,a1)
00108 #define XENOMAI_SKINCALL2(id,op,a1,a2)          XENOMAI_DO_SYSCALL(2,id,op,a1,a2)
00109 #define XENOMAI_SKINCALL3(id,op,a1,a2,a3)       XENOMAI_DO_SYSCALL(3,id,op,a1,a2,a3)
00110 #define XENOMAI_SKINCALL4(id,op,a1,a2,a3,a4)    XENOMAI_DO_SYSCALL(4,id,op,a1,a2,a3,a4)
00111 #define XENOMAI_SKINCALL5(id,op,a1,a2,a3,a4,a5) XENOMAI_DO_SYSCALL(5,id,op,a1,a2,a3,a4,a5)
00112 
00113 #ifdef __KERNEL__
00114 
00115 #include <linux/errno.h>
00116 #include <asm/uaccess.h>
00117 
00118 /* Our own set of copy-to/from-user macros which must bypass
00119    might_sleep() checks. The caller cannot fault and is expected to
00120    have checked for bad range before using the copy macros, so we
00121    should not have to care about the result. The apparently
00122    preposterous do-while bracketing just helps silencing GCC's
00123    "warn_unused_result" attribute on the related kernel macros. */
00124 #define __xn_copy_from_user(task,dstP,srcP,n)  \
00125 do { \
00126     if (__copy_from_user_inatomic(dstP,srcP,n)) \
00127         ; \
00128 } while(0)
00129 #define __xn_copy_to_user(task,dstP,srcP,n)  \
00130 do { \
00131     if (__copy_to_user_inatomic(dstP,srcP,n)) \
00132         ; \
00133 } while(0)
00134 #define __xn_put_user(task,src,dstP)           __put_user(src,dstP)
00135 #define __xn_get_user(task,dst,srcP)           __get_user(dst,srcP)
00136 
00137 #define __xn_range_ok(task,addr,size) \
00138         ((addr) <= (task)->thread.fs.seg \
00139          && ((size) == 0 || (size) - 1 <= (task)->thread.fs.seg - (addr)))
00140 
00141 #define __xn_access_ok(task,type,addr,size)  __xn_range_ok(task,(unsigned long)addr,size)
00142 
00143 /* Purposedly used inlines and not macros for the following routines
00144    so that we don't risk spurious side-effects on the value arg. */
00145 
00146 static inline void __xn_success_return(struct pt_regs *regs, int v) {
00147     __xn_reg_rval(regs) = v;
00148 }
00149 
00150 static inline void __xn_error_return(struct pt_regs *regs, int v) {
00151     /* We currently never set the SO bit for marking errors, even if
00152      * we always test it upon syscall return. */
00153     __xn_reg_rval(regs) = v;
00154 }
00155 
00156 static inline void __xn_status_return(struct pt_regs *regs, int v) {
00157     __xn_reg_rval(regs) = v;
00158 }
00159 
00160 static inline int __xn_interrupted_p(struct pt_regs *regs) {
00161     return __xn_reg_rval(regs) == -EINTR;
00162 }
00163 
00164 #define __xn_canonicalize_args(task,regs) do { } while(0)
00165 
00166 #else /* !__KERNEL__ */
00167 
00168 #define CONFIG_RTAI_HW_DIRECT_TSC 1
00169 
00170 static inline unsigned long long __xn_rdtsc (void)
00171 
00172 {
00173     union {
00174         unsigned long long t;
00175         unsigned long v[2];
00176     } u;
00177     unsigned long __tbu;
00178 
00179     __asm__ __volatile__ ("1: mftbu %0\n"
00180                           "mftb %1\n"
00181                           "mftbu %2\n"
00182                           "cmpw %2,%0\n"
00183                           "bne- 1b\n"
00184                           :"=r" (u.v[0]),
00185                           "=r" (u.v[1]),
00186                           "=r" (__tbu));
00187     return u.t;
00188 }
00189 
00190 #endif /* __KERNEL__ */
00191 
00192 #endif /* !_RTAI_ASM_PPC_SYSCALL_H */

Generated on Wed Jun 22 22:54:02 2005 for RTAI Fusion API by  doxygen 1.4.1