]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / mips / mips64 / n32 / sysdep.h
index 55a405c87e348f8ac1ca3af5036f5bf431d7ca8e..0c32cc38516403f6ec929b1563cb2fa86ef3aca6 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
 
 #ifndef _LINUX_MIPS_SYSDEP_H
 #define _LINUX_MIPS_SYSDEP_H 1
 
 /* There is some commonality.  */
+#include <sysdeps/unix/sysv/linux/sysdep.h>
 #include <sysdeps/unix/mips/mips64/n32/sysdep.h>
 
+#include <tls.h>
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL.  */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
 /* For Linux we can use the system call table in the header file
        /usr/include/asm/unistd.h
    of the kernel.  But these symbols do not follow the SYS_* syntax
    so we have to redefine the `SYS_ify' macro here.  */
 #undef SYS_ify
-#ifdef __STDC__
-# define SYS_ify(syscall_name) __NR_N32_##syscall_name
-#else
-# define SYS_ify(syscall_name) __NR_N32_/**/syscall_name
-#endif
+#define SYS_ify(syscall_name)  __NR_##syscall_name
 
+#ifdef __ASSEMBLER__
+
+/* We don't want the label for the error handler to be visible in the symbol
+   table when we define it here.  */
+# define SYSCALL_ERROR_LABEL 99b
+
+#else   /* ! __ASSEMBLER__ */
+
+/* Convert X to a long long, without losing any bits if it is one
+   already or warning if it is a 32-bit pointer.  */
+#define ARGIFY(X) ((long long) (__typeof__ ((X) - (X))) (X))
 
-#ifndef __ASSEMBLER__
-#if 0 /* untested */
 /* Define a macro which expands into the inline wrapper code for a system
    call.  */
 #undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...)                               \
-  ({ INTERNAL_SYSCALL_DECL(err);                                       \
-     long result_var = INTERNAL_SYSCALL (name, err, nr, args);         \
-     if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) )                 \
-       {                                                                \
-         __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));       \
-         result_var = -1L;                                             \
-       }                                                                \
+#define INLINE_SYSCALL(name, nr, args...)                              \
+  ({ INTERNAL_SYSCALL_DECL (_sc_err);                                  \
+     long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args);     \
+     if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) )             \
+       {                                                               \
+        __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err));    \
+        result_var = -1L;                                              \
+       }                                                               \
      result_var; })
 
 #undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) long err
+#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
 
 #undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err)   ((long) (err))
+#define INTERNAL_SYSCALL_ERROR_P(val, err)   ((void) (val), (long) (err))
 
 #undef INTERNAL_SYSCALL_ERRNO
-#define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
+#define INTERNAL_SYSCALL_ERRNO(val, err)     ((void) (err), val)
+
+/* Note that the original Linux syscall restart convention required the
+   instruction immediately preceding SYSCALL to initialize $v0 with the
+   syscall number.  Then if a restart triggered, $v0 would have been
+   clobbered by the syscall interrupted, and needed to be reinititalized.
+   The kernel would decrement the PC by 4 before switching back to the
+   user mode so that $v0 had been reloaded before SYSCALL was executed
+   again.  This implied the place $v0 was loaded from must have been
+   preserved across a syscall, e.g. an immediate, static register, stack
+   slot, etc.
+
+   The convention was relaxed in Linux with a change applied to the kernel
+   GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
+   first appeared in the 2.6.36 release.  Since then the kernel has had
+   code that reloads $v0 upon syscall restart and resumes right at the
+   SYSCALL instruction, so no special arrangement is needed anymore.
+
+   For backwards compatibility with existing kernel binaries we support
+   the old convention by choosing the instruction preceding SYSCALL
+   carefully.  This also means we have to force a 32-bit encoding of the
+   microMIPS MOVE instruction if one is used.  */
+
+#ifdef __mips_micromips
+# define MOVE32 "move32"
+#else
+# define MOVE32 "move"
+#endif
 
 #undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...) internal_syscall##nr(name, err, args)
+#define INTERNAL_SYSCALL(name, err, nr, args...)                       \
+       internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t",        \
+                             "IK" (SYS_ify (name)),                    \
+                             0, err, args)
 
-#define internal_syscall0(name, err, dummy...)                                 \
-({                                                                     \
-       long _sys_result;                                               \
-                                                                       \
-       {                                                               \
-       register long __v0 asm("$2");                                   \
-       register long __a3 asm("$7");                                   \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %2\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set reorder"                                                  \
-       : "=r" (__v0), "=r" (__a3)                                      \
-       : "i" (SYS_ify(name))                                           \
-       : __SYSCALL_CLOBBERS);                                          \
-       err = __a3;                                                     \
-       _sys_result = __v0;                                             \
-       }                                                               \
-       _sys_result;                                                    \
-})
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                 \
+       internal_syscall##nr (MOVE32 "\t%0, %2\n\t",                    \
+                             "r" (__s0),                               \
+                             number, err, args)
 
-#define internal_syscall1(name, err, arg1)                             \
-({                                                                     \
+#define internal_syscall0(v0_init, input, number, err, dummy...)       \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a3 asm("$7");                              \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %3\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set reorder"                                                  \
-       : "=r" (__v0), "=r" (__a3)                                      \
-       : "r" (__a0), "i" (SYS_ify(name))                               \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a3 asm ("$7");                             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set reorder"                                                  \
+       : "=r" (__v0), "=r" (__a3)                                      \
+       : input                                                         \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall2(name, err, arg1, arg2)                       \
-({                                                                     \
+#define internal_syscall1(v0_init, input, number, err, arg1)           \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a3 asm("$7");                              \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %4\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "=r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "i" (SYS_ify(name))                   \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a3 asm ("$7");                             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set reorder"                                                  \
+       : "=r" (__v0), "=r" (__a3)                                      \
+       : input, "r" (__a0)                                             \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall3(name, err, arg1, arg2, arg3)                         \
-({                                                                     \
+#define internal_syscall2(v0_init, input, number, err, arg1, arg2)     \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a2 asm("$6") = (long long) arg3;           \
-       register long long __a3 asm("$7");                              \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %5\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "=r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name))       \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a1 asm ("$5") = ARGIFY (arg2);             \
+       register long long __a3 asm ("$7");                             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set\treorder"                                                 \
+       : "=r" (__v0), "=r" (__a3)                                      \
+       : input, "r" (__a0), "r" (__a1)                                 \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall4(name, err, arg1, arg2, arg3, arg4)           \
-({                                                                     \
+#define internal_syscall3(v0_init, input, number, err,                 \
+                         arg1, arg2, arg3)                             \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a2 asm("$6") = (long long) arg3;           \
-       register long long __a3 asm("$7") = (long long) arg4;           \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %5\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name))       \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a1 asm ("$5") = ARGIFY (arg2);             \
+       register long long __a2 asm ("$6") = ARGIFY (arg3);             \
+       register long long __a3 asm ("$7");                             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set\treorder"                                                 \
+       : "=r" (__v0), "=r" (__a3)                                      \
+       : input, "r" (__a0), "r" (__a1), "r" (__a2)                     \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall5(name, err, arg1, arg2, arg3, arg4, arg5)     \
-({                                                                     \
+#define internal_syscall4(v0_init, input, number, err,                 \
+                         arg1, arg2, arg3, arg4)                       \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a2 asm("$6") = (long long) arg3;           \
-       register long long __a3 asm("$7") = (long long) arg4;           \
-       register long long __a4 asm("$8") = (long long) arg5;           \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %5\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
-         "r" (__a4)                                                    \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a1 asm ("$5") = ARGIFY (arg2);             \
+       register long long __a2 asm ("$6") = ARGIFY (arg3);             \
+       register long long __a3 asm ("$7") = ARGIFY (arg4);             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set\treorder"                                                 \
+       : "=r" (__v0), "+r" (__a3)                                      \
+       : input, "r" (__a0), "r" (__a1), "r" (__a2)                     \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall6(name, err, arg1, arg2, arg3, arg4, arg5, arg6)\
-({                                                                     \
+#define internal_syscall5(v0_init, input, number, err,                 \
+                         arg1, arg2, arg3, arg4, arg5)                 \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a2 asm("$6") = (long long) arg3;           \
-       register long long __a3 asm("$7") = (long long) arg4;           \
-       register long long __a4 asm("$8") = (long long) arg5;           \
-       register long long __a5 asm("$9") = (long long) arg6;           \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %5\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
-         "r" (__a5), "r" (__a6)                                        \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a1 asm ("$5") = ARGIFY (arg2);             \
+       register long long __a2 asm ("$6") = ARGIFY (arg3);             \
+       register long long __a3 asm ("$7") = ARGIFY (arg4);             \
+       register long long __a4 asm ("$8") = ARGIFY (arg5);             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set\treorder"                                                 \
+       : "=r" (__v0), "+r" (__a3)                                      \
+       : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4)         \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define internal_syscall7(name, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
-({                                                                     \
+#define internal_syscall6(v0_init, input, number, err,                 \
+                         arg1, arg2, arg3, arg4, arg5, arg6)           \
+({                                                                     \
        long _sys_result;                                               \
                                                                        \
        {                                                               \
-       register long long __v0 asm("$2");                              \
-       register long long __a0 asm("$4") = (long long) arg1;           \
-       register long long __a1 asm("$5") = (long long) arg2;           \
-       register long long __a2 asm("$6") = (long long) arg3;           \
-       register long long __a3 asm("$7") = (long long) arg4;           \
-       register long long __a4 asm("$8") = (long long) arg5;           \
-       register long long __a5 asm("$9") = (long long) arg6;           \
-       register long long __a6 asm("$10") = (long long) arg7;          \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "li\t$2, %5\t\t\t# " #name "\n\t"                               \
-       "syscall\n\t"                                                   \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)),      \
-         "r" (__a5), "r" (__a6), "r" (__a7)                            \
-       : __SYSCALL_CLOBBERS);                                          \
+       register long long __s0 asm ("$16") __attribute__ ((unused))    \
+         = (number);                                                   \
+       register long long __v0 asm ("$2");                             \
+       register long long __a0 asm ("$4") = ARGIFY (arg1);             \
+       register long long __a1 asm ("$5") = ARGIFY (arg2);             \
+       register long long __a2 asm ("$6") = ARGIFY (arg3);             \
+       register long long __a3 asm ("$7") = ARGIFY (arg4);             \
+       register long long __a4 asm ("$8") = ARGIFY (arg5);             \
+       register long long __a5 asm ("$9") = ARGIFY (arg6);             \
+       __asm__ volatile (                                              \
+       ".set\tnoreorder\n\t"                                           \
+       v0_init                                                         \
+       "syscall\n\t"                                                   \
+       ".set\treorder"                                                 \
+       : "=r" (__v0), "+r" (__a3)                                      \
+       : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4),        \
+         "r" (__a5)                                                    \
+       : __SYSCALL_CLOBBERS);                                          \
        err = __a3;                                                     \
        _sys_result = __v0;                                             \
        }                                                               \
        _sys_result;                                                    \
 })
 
-#define __SYSCALL_CLOBBERS "$1", "$3", "$11", "$12", "$13", "$14", "$15", "$24", "$25"
-#endif /* untested */
+#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
+       "$14", "$15", "$24", "$25", "hi", "lo", "memory"
+
+/* Standard MIPS syscalls have an error flag, and return a positive errno
+   when the error flag is set. Emulate this behaviour for vsyscalls so that
+   the INTERNAL_SYSCALL_{ERROR_P,ERRNO} macros work correctly.  */
+#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...)              \
+  ({                                                                   \
+    long _ret = funcptr (args);                                                \
+    err = ((unsigned long) (_ret) >= (unsigned long) -4095L);          \
+    if (err)                                                           \
+      _ret = -_ret;                                                    \
+    _ret;                                                              \
+  })
+
+/* List of system calls which are supported as vsyscalls.  */
+#define HAVE_CLOCK_GETTIME_VSYSCALL    1
+#define HAVE_GETTIMEOFDAY_VSYSCALL     1
+
 #endif /* __ASSEMBLER__ */
 
+/* Pointer mangling is not yet supported for MIPS.  */
+#define PTR_MANGLE(var) (void) (var)
+#define PTR_DEMANGLE(var) (void) (var)
+
 #endif /* linux/mips/sysdep.h */