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. */
00122 #define __xn_copy_from_user(task,dstP,srcP,n)  \
00123     ({ int err = __copy_from_user_inatomic(dstP,srcP,n); err; })
00124 #define __xn_copy_to_user(task,dstP,srcP,n)  \
00125     ({ int err = __copy_to_user_inatomic(dstP,srcP,n); err; })
00126 #define __xn_put_user(task,src,dstP)           __put_user(src,dstP)
00127 #define __xn_get_user(task,dst,srcP)           __get_user(dst,srcP)
00128 #define __xn_strncpy_from_user(task,dstP,srcP,n)    __strncpy_from_user(dstP,srcP,n)
00129 
00130 #define __xn_range_ok(task,addr,size) \
00131         ((unsigned long)(addr) <= (task)->thread.fs.seg \
00132          && ((size) == 0 || (size) - 1 <= (task)->thread.fs.seg - (unsigned long)(addr)))
00133 
00134 #define __xn_access_ok(task,type,addr,size)  __xn_range_ok((task),(addr),(size))
00135 
00136 /* Purposedly used inlines and not macros for the following routines
00137    so that we don't risk spurious side-effects on the value arg. */
00138 
00139 static inline void __xn_success_return(struct pt_regs *regs, int v) {
00140     __xn_reg_rval(regs) = v;
00141 }
00142 
00143 static inline void __xn_error_return(struct pt_regs *regs, int v) {
00144     /* We currently never set the SO bit for marking errors, even if
00145      * we always test it upon syscall return. */
00146     __xn_reg_rval(regs) = v;
00147 }
00148 
00149 static inline void __xn_status_return(struct pt_regs *regs, int v) {
00150     __xn_reg_rval(regs) = v;
00151 }
00152 
00153 static inline int __xn_interrupted_p(struct pt_regs *regs) {
00154     return __xn_reg_rval(regs) == -EINTR;
00155 }
00156 
00157 #else /* !__KERNEL__ */
00158 
00159 #define CONFIG_RTAI_HW_DIRECT_TSC 1
00160 
00161 static inline unsigned long long __xn_rdtsc (void)
00162 
00163 {
00164     union {
00165         unsigned long long t;
00166         unsigned long v[2];
00167     } u;
00168     unsigned long __tbu;
00169 
00170     __asm__ __volatile__ ("1: mftbu %0\n"
00171                           "mftb %1\n"
00172                           "mftbu %2\n"
00173                           "cmpw %2,%0\n"
00174                           "bne- 1b\n"
00175                           :"=r" (u.v[0]),
00176                           "=r" (u.v[1]),
00177                           "=r" (__tbu));
00178     return u.t;
00179 }
00180 
00181 #endif /* __KERNEL__ */
00182 
00183 #endif /* !_RTAI_ASM_PPC_SYSCALL_H */

Generated on Sat Sep 3 12:32:46 2005 for RTAI Fusion API by  doxygen 1.4.2