Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1992,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
00002        Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 /* Alan Modra <amodra@bigpond.net.au> rewrote the INLINE_SYSCALL macro */
00021 
00022 #ifndef _LINUX_POWERPC_SYSDEP_H
00023 #define _LINUX_POWERPC_SYSDEP_H 1
00024 
00025 #include <sysdeps/unix/powerpc/sysdep.h>
00026 #include <tls.h>
00027 
00028 /* Define __set_errno() for INLINE_SYSCALL macro below.  */
00029 #ifndef __ASSEMBLER__
00030 #include <errno.h>
00031 #endif
00032 
00033 /* Some systen calls got renamed over time, but retained the same semantics.
00034    Handle them here so they can be catched by both C and assembler stubs in
00035    glibc.  */
00036 
00037 #ifdef __NR_pread64
00038 # ifdef __NR_pread
00039 #  error "__NR_pread and __NR_pread64 both defined???"
00040 # endif
00041 # define __NR_pread __NR_pread64
00042 #endif
00043 
00044 #ifdef __NR_pwrite64
00045 # ifdef __NR_pwrite
00046 #  error "__NR_pwrite and __NR_pwrite64 both defined???"
00047 # endif
00048 # define __NR_pwrite __NR_pwrite64
00049 #endif
00050 
00051 /* For Linux we can use the system call table in the header file
00052        /usr/include/asm/unistd.h
00053    of the kernel.  But these symbols do not follow the SYS_* syntax
00054    so we have to redefine the `SYS_ify' macro here.  */
00055 #undef SYS_ify
00056 #ifdef __STDC__
00057 # define SYS_ify(syscall_name)     __NR_##syscall_name
00058 #else
00059 # define SYS_ify(syscall_name)     __NR_syscall_name
00060 #endif
00061 
00062 #ifdef __ASSEMBLER__
00063 
00064 /* This seems to always be the case on PPC.  */
00065 # define ALIGNARG(log2) log2
00066 /* For ELF we need the `.type' directive to make shared libs work right.  */
00067 # define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
00068 # define ASM_SIZE_DIRECTIVE(name) .size name,.-name
00069 
00070 #endif /* __ASSEMBLER__ */
00071 
00072 /* This version is for kernels that implement system calls that
00073    behave like function calls as far as register saving.
00074    It falls back to the syscall in the case that the vDSO doesn't
00075    exist or fails for ENOSYS */
00076 #ifdef SHARED
00077 # define INLINE_VSYSCALL(name, nr, args...) \
00078   ({                                                                 \
00079     __label__ out;                                                   \
00080     __label__ iserr;                                                 \
00081     INTERNAL_SYSCALL_DECL (sc_err);                                         \
00082     long int sc_ret;                                                 \
00083                                                                      \
00084     if (__vdso_##name != NULL)                                              \
00085       {                                                                     \
00086        sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args);   \
00087        if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                      \
00088          goto out;                                                   \
00089        if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS)               \
00090          goto iserr;                                                 \
00091       }                                                                     \
00092                                                                      \
00093     sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args);                   \
00094     if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                          \
00095       {                                                                     \
00096       iserr:                                                         \
00097         __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));              \
00098         sc_ret = -1L;                                                       \
00099       }                                                                     \
00100   out:                                                               \
00101     sc_ret;                                                          \
00102   })
00103 #else
00104 # define INLINE_VSYSCALL(name, nr, args...) \
00105   INLINE_SYSCALL (name, nr, ##args)
00106 #endif
00107 
00108 #ifdef SHARED
00109 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
00110   ({                                                                 \
00111     __label__ out;                                                   \
00112     long int v_ret;                                                  \
00113                                                                      \
00114     if (__vdso_##name != NULL)                                              \
00115       {                                                                     \
00116        v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);             \
00117        if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err)                           \
00118            || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS)                \
00119          goto out;                                                   \
00120       }                                                                     \
00121     v_ret = INTERNAL_SYSCALL (name, err, nr, ##args);                       \
00122   out:                                                               \
00123     v_ret;                                                           \
00124   })
00125 #else
00126 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
00127   INTERNAL_SYSCALL (name, err, nr, ##args)
00128 #endif
00129 
00130 /* This version is for internal uses when there is no desire
00131    to set errno */
00132 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...)       \
00133   ({                                                                 \
00134     long int sc_ret = ENOSYS;                                               \
00135                                                                      \
00136     if (__vdso_##name != NULL)                                              \
00137       sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);             \
00138     else                                                             \
00139       err = 1 << 28;                                                 \
00140     sc_ret;                                                          \
00141   })
00142 
00143 /* List of system calls which are supported as vsyscalls.  */
00144 #define HAVE_CLOCK_GETRES_VSYSCALL 1
00145 #define HAVE_CLOCK_GETTIME_VSYSCALL       1
00146 
00147 /* Define a macro which expands inline into the wrapper code for a system
00148    call. This use is for internal calls that do not need to handle errors
00149    normally. It will never touch errno. This returns just what the kernel
00150    gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
00151    the negation of the return value in the kernel gets reverted.  */
00152 
00153 #define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \
00154   ({                                                           \
00155     register void *r0  __asm__ ("r0");                                \
00156     register long int r3  __asm__ ("r3");                      \
00157     register long int r4  __asm__ ("r4");                      \
00158     register long int r5  __asm__ ("r5");                      \
00159     register long int r6  __asm__ ("r6");                      \
00160     register long int r7  __asm__ ("r7");                      \
00161     register long int r8  __asm__ ("r8");                      \
00162     LOADARGS_##nr (funcptr, args);                             \
00163     __asm__ __volatile__                                       \
00164       ("mtctr %0\n\t"                                                 \
00165        "bctrl\n\t"                                             \
00166        "mfcr  %0\n\t"                                                 \
00167        "0:"                                                    \
00168        : "=&r" (r0),                                           \
00169          "=&r" (r3), "=&r" (r4), "=&r" (r5),                          \
00170          "=&r" (r6), "=&r" (r7), "=&r" (r8)                           \
00171        : ASM_INPUT_##nr                                               \
00172        : "r9", "r10", "r11", "r12",                                   \
00173          "cr0", "ctr", "lr", "memory");                               \
00174          err = (long int) r0;                                         \
00175     (int) r3;                                                  \
00176   })
00177 
00178 #undef INLINE_SYSCALL
00179 
00180 /* This version is for kernels that implement system calls that
00181    behave like function calls as far as register saving.  */
00182 #define INLINE_SYSCALL(name, nr, args...)                      \
00183   ({                                                           \
00184     INTERNAL_SYSCALL_DECL (sc_err);                                   \
00185     long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args);      \
00186     if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                    \
00187       {                                                               \
00188         __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));        \
00189         sc_ret = -1L;                                                 \
00190       }                                                               \
00191     sc_ret;                                                    \
00192   })
00193 
00194 /* Define a macro which expands inline into the wrapper code for a system
00195    call. This use is for internal calls that do not need to handle errors
00196    normally. It will never touch errno. This returns just what the kernel
00197    gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
00198    the negation of the return value in the kernel gets reverted.  */
00199 
00200 #undef INTERNAL_SYSCALL
00201 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00202   ({                                                           \
00203     register long int r0  __asm__ ("r0");                      \
00204     register long int r3  __asm__ ("r3");                      \
00205     register long int r4  __asm__ ("r4");                      \
00206     register long int r5  __asm__ ("r5");                      \
00207     register long int r6  __asm__ ("r6");                      \
00208     register long int r7  __asm__ ("r7");                      \
00209     register long int r8  __asm__ ("r8");                      \
00210     LOADARGS_##nr (name, ##args);                              \
00211     __asm__ __volatile__                                       \
00212       ("sc\n\t"                                                       \
00213        "mfcr  %0\n\t"                                                 \
00214        "0:"                                                    \
00215        : "=&r" (r0),                                           \
00216          "=&r" (r3), "=&r" (r4), "=&r" (r5),                          \
00217          "=&r" (r6), "=&r" (r7), "=&r" (r8)                           \
00218        : ASM_INPUT_##nr                                               \
00219        : "r9", "r10", "r11", "r12",                                   \
00220          "cr0", "ctr", "memory");                              \
00221          err = r0;  \
00222     (int) r3;  \
00223   })
00224 #define INTERNAL_SYSCALL(name, err, nr, args...)               \
00225   INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, args)
00226 
00227 #undef INTERNAL_SYSCALL_DECL
00228 #define INTERNAL_SYSCALL_DECL(err) long int err
00229 
00230 #undef INTERNAL_SYSCALL_ERROR_P
00231 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
00232   ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
00233 
00234 #undef INTERNAL_SYSCALL_ERRNO
00235 #define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
00236 
00237 #define LOADARGS_0(name, dummy) \
00238        r0 = name
00239 #define LOADARGS_1(name, __arg1) \
00240        long int arg1 = (long int) (__arg1); \
00241        LOADARGS_0(name, 0); \
00242        extern void __illegally_sized_syscall_arg1 (void); \
00243        if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 8) \
00244          __illegally_sized_syscall_arg1 (); \
00245        r3 = arg1
00246 #define LOADARGS_2(name, __arg1, __arg2) \
00247        long int arg2 = (long int) (__arg2); \
00248        LOADARGS_1(name, __arg1); \
00249        extern void __illegally_sized_syscall_arg2 (void); \
00250        if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 8) \
00251          __illegally_sized_syscall_arg2 (); \
00252        r4 = arg2
00253 #define LOADARGS_3(name, __arg1, __arg2, __arg3) \
00254        long int arg3 = (long int) (__arg3); \
00255        LOADARGS_2(name, __arg1, __arg2); \
00256        extern void __illegally_sized_syscall_arg3 (void); \
00257        if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 8) \
00258          __illegally_sized_syscall_arg3 (); \
00259        r5 = arg3
00260 #define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
00261        long int arg4 = (long int) (__arg4); \
00262        LOADARGS_3(name, __arg1, __arg2, __arg3); \
00263        extern void __illegally_sized_syscall_arg4 (void); \
00264        if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 8) \
00265          __illegally_sized_syscall_arg4 (); \
00266        r6 = arg4
00267 #define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
00268        long int arg5 = (long int) (__arg5); \
00269        LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
00270        extern void __illegally_sized_syscall_arg5 (void); \
00271        if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 8) \
00272          __illegally_sized_syscall_arg5 (); \
00273        r7 = arg5
00274 #define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
00275        long int arg6 = (long int) (__arg6); \
00276        LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
00277        extern void __illegally_sized_syscall_arg6 (void); \
00278        if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 8) \
00279          __illegally_sized_syscall_arg6 (); \
00280        r8 = arg6
00281 
00282 #define ASM_INPUT_0 "0" (r0)
00283 #define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
00284 #define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
00285 #define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
00286 #define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
00287 #define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
00288 #define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
00289 
00290 
00291 /* Pointer mangling support.  */
00292 #if defined NOT_IN_libc && defined IS_IN_rtld
00293 /* We cannot use the thread descriptor because in ld.so we use setjmp
00294    earlier than the descriptor is initialized.  */
00295 #else
00296 # ifdef __ASSEMBLER__
00297 #  define PTR_MANGLE(reg, tmpreg) \
00298        ld     tmpreg,POINTER_GUARD(r13); \
00299        xor    reg,tmpreg,reg
00300 #  define PTR_MANGLE2(reg, tmpreg) \
00301        xor    reg,tmpreg,reg
00302 #  define PTR_MANGLE3(destreg, reg, tmpreg) \
00303        ld     tmpreg,POINTER_GUARD(r13); \
00304        xor    destreg,tmpreg,reg
00305 #  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
00306 #  define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
00307 #  define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg)
00308 # else
00309 #  define PTR_MANGLE(var) \
00310   (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
00311 #  define PTR_DEMANGLE(var) PTR_MANGLE (var)
00312 # endif
00313 #endif
00314 
00315 #endif /* linux/powerpc/powerpc64/sysdep.h */