syscall.h

00001 /*
00002  * Copyright (C) 2001,2002,2003 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_I386_SYSCALL_H
00021 #define _RTAI_ASM_I386_SYSCALL_H
00022 
00023 #include <rtai_config.h>
00024 #include <asm/ptrace.h>
00025 #include <nucleus/asm-generic/syscall.h>
00026 
00027 #ifndef __KERNEL__
00028 
00029 #ifdef CONFIG_RTAI_HW_X86_VSYSCALL
00030 
00031 #include <asm/unistd.h>
00032 #include <sys/prctl.h>
00033 #include <errno.h>
00034 
00035 /* Make the syscall through the vsyscall support. In order to keep it
00036    simple and efficient, we don't attempt to directly map and jump to
00037    the vsyscall DSO, but we rather cheat the prctl(2) system call,
00038    intercepting any invocation to it which bears a specific RTAI
00039    signature in the "option" argument. Invocations that match the
00040    signature are processed by RTAI, others are simply relayed
00041    untouched to the Linux kernel.
00042 
00043    If the glibc - real-time apps are linked against - actually uses
00044    the vsyscall DSO, then the prctl() support routine will too, and
00045    our syscalls will in turn be dispatched through the
00046    sysenter/sysexit fast system call instructions. A few things to
00047    note:
00048 
00049    1) We make sure that the value mangled through __xn_mux_code(id,op)
00050    cannot match any legitimate operation code Linux defines for its
00051    prctl(2) service, so that the RTAI nucleus can always identify RTAI
00052    system calls flowing among the regular Linux ones.
00053 
00054    2) Calls with more than four args have two of them fetched from the
00055    caller's memory instead of being conveyed into registers.
00056    Fortunately, such calls are seldom. Would future benchmarks prove
00057    that the performance gain using sysenter/sysexit is less than the
00058    cost of fetching back those arguments, the five-args call form
00059    would then be converted back to using "int 0x80", which is still
00060    usable in parallel to the sysenter path. */
00061    
00062 #define XENOMAI_SKIN_MUX(nr, id, op, args...) \
00063   ({                                          \
00064     int resultvar;                            \
00065     ARGDCL_##nr(args);                        \
00066     resultvar = prctl(__xn_mux_code(id,op) ARGFMT_##nr(args)); \
00067     resultvar == -1 ? -errno : resultvar; })
00068 
00069 #define XENOMAI_SYS_MUX(nr, op, args...) XENOMAI_SKIN_MUX(nr, 0, op, args) 
00070 
00071 #define __ul(x)  ((unsigned long)(x))
00072 
00073 #define ARGDCL_0()
00074 #define ARGFMT_0() \
00075         , 0, 0, 0, 0
00076 #define ARGDCL_1(arg1)
00077 #define ARGFMT_1(arg1) \
00078         , 0, 0, 0, __ul(arg1)
00079 #define ARGDCL_2(arg1, arg2)
00080 #define ARGFMT_2(arg1, arg2) \
00081         , __ul(arg2), 0, 0, __ul(arg1)
00082 #define ARGDCL_3(arg1, arg2, arg3)
00083 #define ARGFMT_3(arg1, arg2, arg3) \
00084         , __ul(arg2), __ul(arg3), 0, __ul(arg1)
00085 #define ARGDCL_4(arg1, arg2, arg3, arg4)
00086 #define ARGFMT_4(arg1, arg2, arg3, arg4) \
00087         , __ul(arg2), __ul(arg3), __ul(arg4), __ul(arg1)
00088 #define ARGDCL_5(arg1, arg2, arg3, arg4, arg5)  \
00089         unsigned long xargs[2] = { __ul(arg1), __ul(arg5) }
00090 #define ARGFMT_5(arg1, arg2, arg3, arg4, arg5) \
00091         | 0x8000, __ul(arg2), __ul(arg3), __ul(arg4), __ul(xargs)
00092 
00093 #else /* !CONFIG_RTAI_HW_X86_VSYSCALL -- use "int 0x80" */
00094 
00095 /*
00096  * Some of the following macros have been adapted from glibc's syscall
00097  * mechanism implementation:
00098  * Copyright (C) 1992,1993,1995-2000,2002,2003 Free Software Foundation, Inc.
00099  * Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
00100  *
00101  * The following code defines an inline syscall mechanism used by
00102  * RTAI/fusion's real-time interfaces to invoke the skin module services
00103  * in kernel space.
00104  */
00105 
00106 asm (".L__X'%ebx = 1\n\t"
00107      ".L__X'%ecx = 2\n\t"
00108      ".L__X'%edx = 2\n\t"
00109      ".L__X'%eax = 3\n\t"
00110      ".L__X'%esi = 3\n\t"
00111      ".L__X'%edi = 3\n\t"
00112      ".L__X'%ebp = 3\n\t"
00113      ".L__X'%esp = 3\n\t"
00114      ".macro bpushl name reg\n\t"
00115      ".if 1 - \\name\n\t"
00116      ".if 2 - \\name\n\t"
00117      "pushl %ebx\n\t"
00118      ".else\n\t"
00119      "xchgl \\reg, %ebx\n\t"
00120      ".endif\n\t"
00121      ".endif\n\t"
00122      ".endm\n\t"
00123      ".macro bpopl name reg\n\t"
00124      ".if 1 - \\name\n\t"
00125      ".if 2 - \\name\n\t"
00126      "popl %ebx\n\t"
00127      ".else\n\t"
00128      "xchgl \\reg, %ebx\n\t"
00129      ".endif\n\t"
00130      ".endif\n\t"
00131      ".endm\n\t"
00132      ".macro bmovl name reg\n\t"
00133      ".if 1 - \\name\n\t"
00134      ".if 2 - \\name\n\t"
00135      "movl \\reg, %ebx\n\t"
00136      ".endif\n\t"
00137      ".endif\n\t"
00138      ".endm\n\t");
00139 
00140 #define XENOMAI_SYS_MUX(nr, op, args...) \
00141   ({                                                                  \
00142     unsigned resultvar;                                               \
00143     asm volatile (                                                    \
00144     LOADARGS_##nr                                                     \
00145     "movl %1, %%eax\n\t"                                              \
00146     "int $0x80\n\t"                                                   \
00147     RESTOREARGS_##nr                                                  \
00148     : "=a" (resultvar)                                                \
00149     : "i" (__xn_mux_code(0,op)) ASMFMT_##nr(args) : "memory", "cc");  \
00150     (int) resultvar; })
00151 
00152 #define XENOMAI_SKIN_MUX(nr, id, op, args...) \
00153   ({                                                                  \
00154     int muxcode = __xn_mux_code(id,op);                               \
00155     unsigned resultvar;                                               \
00156     asm volatile (                                                    \
00157     LOADARGS_##nr                                                     \
00158     "movl %1, %%eax\n\t"                                              \
00159     "int $0x80\n\t"                                                   \
00160     RESTOREARGS_##nr                                                  \
00161     : "=a" (resultvar)                                                \
00162     : "m" (muxcode) ASMFMT_##nr(args) : "memory", "cc");              \
00163     (int) resultvar; })
00164 
00165 #define LOADARGS_0
00166 #define LOADARGS_1 \
00167     "bpushl .L__X'%k2, %k2\n\t" \
00168     "bmovl .L__X'%k2, %k2\n\t"
00169 #define LOADARGS_2      LOADARGS_1
00170 #define LOADARGS_3      LOADARGS_1
00171 #define LOADARGS_4      LOADARGS_1
00172 #define LOADARGS_5      LOADARGS_1
00173 
00174 #define RESTOREARGS_0
00175 #define RESTOREARGS_1 \
00176     "bpopl .L__X'%k2, %k2\n\t"
00177 #define RESTOREARGS_2   RESTOREARGS_1
00178 #define RESTOREARGS_3   RESTOREARGS_1
00179 #define RESTOREARGS_4   RESTOREARGS_1
00180 #define RESTOREARGS_5   RESTOREARGS_1
00181 
00182 #define ASMFMT_0()
00183 #define ASMFMT_1(arg1) \
00184         , "acdSD" (arg1)
00185 #define ASMFMT_2(arg1, arg2) \
00186         , "adSD" (arg1), "c" (arg2)
00187 #define ASMFMT_3(arg1, arg2, arg3) \
00188         , "aSD" (arg1), "c" (arg2), "d" (arg3)
00189 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
00190         , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
00191 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
00192         , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
00193 
00194 #endif /* CONFIG_RTAI_HW_X86_VSYSCALL */
00195 
00196 #endif /* !__KERNEL__ */
00197 
00198 /* Register mapping for accessing syscall args. */
00199 
00200 #define __xn_reg_mux(regs)    ((regs)->orig_eax)
00201 #define __xn_reg_rval(regs)   ((regs)->eax)
00202 #define __xn_reg_arg1(regs)   ((regs)->ebx)
00203 #define __xn_reg_arg2(regs)   ((regs)->ecx)
00204 #define __xn_reg_arg3(regs)   ((regs)->edx)
00205 #define __xn_reg_arg4(regs)   ((regs)->esi)
00206 #define __xn_reg_arg5(regs)   ((regs)->edi)
00207 
00208 #define __xn_reg_mux_p(regs)  ((__xn_reg_mux(regs) & 0x7fff) == __xn_sys_mux)
00209 #define __xn_mux_id(regs)     ((__xn_reg_mux(regs) >> 16) & 0xff)
00210 #define __xn_mux_op(regs)     ((__xn_reg_mux(regs) >> 24) & 0xff)
00211 #define __xn_mux_code(id,op)  ((op << 24)|((id << 16) & 0xff0000)|(__xn_sys_mux & 0x7fff))
00212 
00213 #define XENOMAI_SYSCALL0(op)                XENOMAI_SYS_MUX(0,op)
00214 #define XENOMAI_SYSCALL1(op,a1)             XENOMAI_SYS_MUX(1,op,a1)
00215 #define XENOMAI_SYSCALL2(op,a1,a2)          XENOMAI_SYS_MUX(2,op,a1,a2)
00216 #define XENOMAI_SYSCALL3(op,a1,a2,a3)       XENOMAI_SYS_MUX(3,op,a1,a2,a3)
00217 #define XENOMAI_SYSCALL4(op,a1,a2,a3,a4)    XENOMAI_SYS_MUX(4,op,a1,a2,a3,a4)
00218 #define XENOMAI_SYSCALL5(op,a1,a2,a3,a4,a5) XENOMAI_SYS_MUX(5,op,a1,a2,a3,a4,a5)
00219 
00220 #define XENOMAI_SKINCALL0(id,op)                XENOMAI_SKIN_MUX(0,id,op)
00221 #define XENOMAI_SKINCALL1(id,op,a1)             XENOMAI_SKIN_MUX(1,id,op,a1)
00222 #define XENOMAI_SKINCALL2(id,op,a1,a2)          XENOMAI_SKIN_MUX(2,id,op,a1,a2)
00223 #define XENOMAI_SKINCALL3(id,op,a1,a2,a3)       XENOMAI_SKIN_MUX(3,id,op,a1,a2,a3)
00224 #define XENOMAI_SKINCALL4(id,op,a1,a2,a3,a4)    XENOMAI_SKIN_MUX(4,id,op,a1,a2,a3,a4)
00225 #define XENOMAI_SKINCALL5(id,op,a1,a2,a3,a4,a5) XENOMAI_SKIN_MUX(5,id,op,a1,a2,a3,a4,a5)
00226 
00227 #ifdef __KERNEL__
00228 
00229 #include <linux/errno.h>
00230 #include <asm/uaccess.h>
00231 
00232 /* Our own set of copy-to/from-user macros which must bypass
00233    might_sleep() checks. The caller cannot fault and is expected to
00234    have checked for bad range before using the copy macros, so we
00235    should not have to care about the result. The apparently
00236    preposterous do-while bracketing just helps silencing GCC's
00237    "warn_unused_result" attribute on the related kernel macros. */
00238 #define __xn_copy_from_user(task,dstP,srcP,n)  \
00239 do { \
00240     if (__copy_from_user_inatomic(dstP,srcP,n)) \
00241         ; \
00242 } while(0)
00243 #define __xn_copy_to_user(task,dstP,srcP,n)  \
00244 do { \
00245     if (__copy_to_user_inatomic(dstP,srcP,n)) \
00246         ; \
00247 } while(0)
00248 #define __xn_put_user(task,src,dstP)           __put_user(src,dstP)
00249 #define __xn_get_user(task,dst,srcP)           __get_user(dst,srcP)
00250 
00251 #define __xn_range_ok(task,addr,size) ({ \
00252         unsigned long flag,sum; \
00253         asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
00254                 :"=&r" (flag), "=r" (sum) \
00255                 :"1" (addr),"g" ((int)(size)),"g" ((task)->thread_info->addr_limit.seg)); \
00256         flag; })
00257 
00258 /* WP bit must work for using the shadow support, so we only need
00259    trivial range checking here. */
00260 #define __xn_access_ok(task,type,addr,size)    (__xn_range_ok(task,addr,size) == 0)
00261 
00262 /* Purposedly used inlines and not macros for the following routines
00263    so that we don't risk spurious side-effects on the value arg. */
00264 
00265 static inline void __xn_success_return(struct pt_regs *regs, int v) {
00266     __xn_reg_rval(regs) = v;
00267 }
00268 
00269 static inline void __xn_error_return(struct pt_regs *regs, int v) {
00270     __xn_reg_rval(regs) = v;
00271 }
00272 
00273 static inline void __xn_status_return(struct pt_regs *regs, int v) {
00274     __xn_reg_rval(regs) = v;
00275 }
00276 
00277 static inline int __xn_interrupted_p(struct pt_regs *regs) {
00278     return __xn_reg_rval(regs) == -EINTR;
00279 }
00280 
00281 #ifdef CONFIG_RTAI_HW_X86_VSYSCALL
00282 
00283 #define __xn_canonicalize_args(task,regs) \
00284 do { \
00285  if (__xn_reg_mux(regs) == __NR_prctl && \
00286      ((__xn_reg_arg1(regs) & 0x7fff) == __xn_sys_mux)) { \
00287      __xn_reg_mux(regs) = __xn_reg_arg1(regs); \
00288      if (__xn_reg_arg1(regs) & 0x8000) { \
00289          unsigned long xargs[2]; \
00290          __xn_copy_from_user(task,xargs,(void *)__xn_reg_arg5(regs),sizeof(xargs)); \
00291          __xn_reg_arg1(regs) = xargs[0];        \
00292          __xn_reg_arg5(regs) = xargs[1];        \
00293      } \
00294      else \
00295         __xn_reg_arg1(regs) = __xn_reg_arg5(regs); \
00296  } \
00297 } while(0)
00298 
00299 #else /* !CONFIG_RTAI_HW_X86_VSYSCALL */
00300 
00301 #define __xn_canonicalize_args(task,regs) do { } while(0)
00302 
00303 #endif /* CONFIG_RTAI_HW_X86_VSYSCALL */
00304 
00305 #else /* !__KERNEL__ */
00306 
00307 #ifdef CONFIG_X86_TSC
00308 
00309 #define CONFIG_RTAI_HW_DIRECT_TSC 1
00310 
00311 static inline unsigned long long __xn_rdtsc (void)
00312 
00313 {
00314     unsigned long long t;
00315     __asm__ __volatile__( "rdtsc" : "=A" (t));
00316     return t;
00317 }
00318 
00319 #endif  /* CONFIG_X86_TSC */
00320 
00321 #endif /* __KERNEL__ */
00322 
00323 #endif /* !_RTAI_ASM_I386_SYSCALL_H */

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