]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
MIPS/o32: Fix internal_syscall5/6/7
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 29 Aug 2017 17:31:08 +0000 (18:31 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Tue, 29 Aug 2017 17:31:08 +0000 (18:31 +0100)
Fix a commit cc25c8b4c119 ("New pthread rwlock that is more scalable.")
regression and prevent uncontrolled stack space usage from happening
when a 5-, 6- or 7-argument syscall wrapper is placed in a loop.

The cause of the problem is the use of `alloca' in regular MIPS/Linux
wrappers to force the use of the frame pointer register in any function
using one or more of these wrappers.  Using the frame pointer register
is required so as not to break frame unwinding as the the stack pointer
is lowered within the inline asm used by these wrappers to make room for
the stack arguments, which 5-, 6- and 7-argument syscalls use with the
o32 ABI.

The regular MIPS/Linux wrappers are macros however, expanded inline, and
stack allocations made with `alloca' are not discarded until the return
of the function they are made in.  Consequently if called in a loop,
then virtual memory is wasted, and if the loop goes through enough
iterations, then ultimately available memory can get exhausted causing
the program to crash.

Address the issue by replacing the inline code with standalone assembly
functions, which rely on the compiler arranging syscall arguments
according to the o32 function calling convention, which MIPS/Linux
syscalls also use, except for the syscall number passed and the error
flag returned.  This way there is no need to fiddle with the stack
pointer anymore and all that has to be handled in the new standalone
functions is the special handling of the syscall number and the error
flag.

Redirect 5-, 6- or 7-argument MIPS16/Linux syscall wrappers to these new
functions as well, so as to avoid an unnecessary double call the
existing wrappers would cause with the new arrangement.

[BZ #21956]
* sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
[subdir = misc] (sysdep_routines): Remove `mips16-syscall5',
`mips16-syscall6' and `mips16-syscall7'.
(CFLAGS-mips16-syscall5.c, CFLAGS-mips16-syscall6.c)
(CFLAGS-mips16-syscall7.c): Remove.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions (libc):
Remove `__mips16_syscall5', `__mips16_syscall6' and
`__mips16_syscall7'.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
(__mips16_syscall0): Rename `__mips16_syscall_return' to
`__mips_syscall_return'.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
(__mips16_syscall1): Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
(__mips16_syscall2): Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
(__mips16_syscall3): Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
(__mips16_syscall4): Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c:
Remove.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c:
Remove.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c:
Remove.
* sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
(__mips16_syscall5): Expand to `__mips_syscall5' rather than
`__mips16_syscall5'.  Remove prototype.
(__mips16_syscall6): Expand to `__mips_syscall6' rather than
`__mips16_syscall6'.  Remove prototype.
(__mips16_syscall7): Expand to `__mips_syscall7' rather than
`__mips16_syscall7'.  Remove prototype.
(__nomips16, __mips16_syscall_return): Move to...
* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
(__nomips16, __mips_syscall_return): ... here.
[__mips16] (INTERNAL_SYSCALL_NCS): Rename
`__mips16_syscall_return' to `__mips_syscall_return'.
[__mips16] (INTERNAL_SYSCALL_MIPS16): Pass `number' to
`internal_syscall##nr'.
[!__mips16] (INTERNAL_SYSCALL): Pass `SYS_ify (name)' to
`internal_syscall##nr'.
(FORCE_FRAME_POINTER): Remove.
(__mips_syscall5): New prototype.
(internal_syscall5): Rewrite to call `__mips_syscall5'.
(__mips_syscall6): New prototype.
(internal_syscall6): Rewrite to call `__mips_syscall6'.
(__mips_syscall7): New prototype.
(internal_syscall7): Rewrite to call `__mips_syscall7'.
* sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S: New file.
* sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S: New file.
* sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S: New file.
* sysdeps/unix/sysv/linux/mips/mips32/Makefile [subdir = misc]
(sysdep_routines): Add libc-do-syscall.
* sysdeps/unix/sysv/linux/mips/mips32/Versions (libc): Add
`__mips_syscall5', `__mips_syscall6' and `__mips_syscall7'.

15 files changed:
ChangeLog
sysdeps/unix/sysv/linux/mips/mips32/Makefile
sysdeps/unix/sysv/linux/mips/mips32/Versions
sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S [moved from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c with 60% similarity]
sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S [moved from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c with 60% similarity]
sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S [moved from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c with 59% similarity]
sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
sysdeps/unix/sysv/linux/mips/mips32/sysdep.h

index b2016ca32a3f408cf58b9f54eeaac4c69f4da451..ce754281b39ab811cb52b87c4bec55152eacf31f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+2017-08-29  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
+           Aurelien Jarno  <aurelien@aurel32.net>
+           Maciej W. Rozycki  <macro@imgtec.com>
+
+       [BZ #21956]
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
+       [subdir = misc] (sysdep_routines): Remove `mips16-syscall5',
+       `mips16-syscall6' and `mips16-syscall7'.
+       (CFLAGS-mips16-syscall5.c, CFLAGS-mips16-syscall6.c)
+       (CFLAGS-mips16-syscall7.c): Remove.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions (libc):
+       Remove `__mips16_syscall5', `__mips16_syscall6' and
+       `__mips16_syscall7'.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
+       (__mips16_syscall0): Rename `__mips16_syscall_return' to
+       `__mips_syscall_return'.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
+       (__mips16_syscall1): Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
+       (__mips16_syscall2): Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
+       (__mips16_syscall3): Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
+       (__mips16_syscall4): Likewise.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c:
+       Remove.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c:
+       Remove.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c:
+       Remove.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
+       (__mips16_syscall5): Expand to `__mips_syscall5' rather than
+       `__mips16_syscall5'.  Remove prototype.
+       (__mips16_syscall6): Expand to `__mips_syscall6' rather than
+       `__mips16_syscall6'.  Remove prototype.
+       (__mips16_syscall7): Expand to `__mips_syscall7' rather than
+       `__mips16_syscall7'.  Remove prototype.
+       (__nomips16, __mips16_syscall_return): Move to...
+       * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
+       (__nomips16, __mips_syscall_return): ... here.
+       [__mips16] (INTERNAL_SYSCALL_NCS): Rename
+       `__mips16_syscall_return' to `__mips_syscall_return'.
+       [__mips16] (INTERNAL_SYSCALL_MIPS16): Pass `number' to
+       `internal_syscall##nr'.
+       [!__mips16] (INTERNAL_SYSCALL): Pass `SYS_ify (name)' to
+       `internal_syscall##nr'.
+       (FORCE_FRAME_POINTER): Remove.
+       (__mips_syscall5): New prototype.
+       (internal_syscall5): Rewrite to call `__mips_syscall5'.
+       (__mips_syscall6): New prototype.
+       (internal_syscall6): Rewrite to call `__mips_syscall6'.
+       (__mips_syscall7): New prototype.
+       (internal_syscall7): Rewrite to call `__mips_syscall7'.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S: New file.
+       * sysdeps/unix/sysv/linux/mips/mips32/Makefile [subdir = misc]
+       (sysdep_routines): Add libc-do-syscall.
+       * sysdeps/unix/sysv/linux/mips/mips32/Versions (libc): Add
+       `__mips_syscall5', `__mips_syscall6' and `__mips_syscall7'.
+
 2017-08-29  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
        [BZ #21672]
index 33b461500ca78f67cbe01f9651ec3c69b2fa3f52..aa1aa8fe8063eccfe0323bbc72abe8991a85d418 100644 (file)
@@ -3,6 +3,10 @@ ifeq ($(subdir),conform)
 conformtest-xfail-conds += mips-o32-linux
 endif
 
+ifeq ($(subdir),misc)
+sysdep_routines += mips-syscall5 mips-syscall6 mips-syscall7
+endif
+
 ifeq ($(subdir),stdlib)
 tests += bug-getcontext-mips-gp
 endif
index 9621fb5cae80dc4fc7c8ad244aea5891651938ad..9337f8fe3df832ce4e0431dcf3e9a485d020449a 100644 (file)
@@ -3,4 +3,7 @@ libc {
     getrlimit64;
     setrlimit64;
   }
+  GLIBC_PRIVATE {
+    __mips_syscall5; __mips_syscall6; __mips_syscall7;
+  }
 }
similarity index 60%
rename from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c
rename to sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S
index ad265d88e2875ddf5289d9305dfb710a43b1e910..9f331675dff78f52a4006cb63f4588ee949e9a46 100644 (file)
@@ -1,5 +1,5 @@
-/* MIPS16 syscall wrappers.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+/* MIPS syscall wrappers.
+   Copyright (C) 2017 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, see
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
+#include <sys/asm.h>
 
-#undef __mips16_syscall5
+       .text
+       .set    nomips16
 
-long long __nomips16
-__mips16_syscall5 (long a0, long a1, long a2, long a3,
-                  long a4,
-                  long number)
-{
-  union __mips16_syscall_return ret;
-  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 5,
-                                       a0, a1, a2, a3, a4);
-  return ret.val;
-}
+/* long long __mips_syscall5 (long arg1, long arg2, long arg3, long arg4,
+                             long arg5,
+                             long number)  */
+
+ENTRY(__mips_syscall5)
+       lw      v0, 20(sp)
+       syscall
+       move    v1, a3
+       jr      ra
+END(__mips_syscall5)
+libc_hidden_def (__mips_syscall5)
similarity index 60%
rename from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c
rename to sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S
index bfbd395ed329b37ea1ecd5184bd7f66917068836..0836660ede28df374a3cd229d29c103d80415128 100644 (file)
@@ -1,5 +1,5 @@
-/* MIPS16 syscall wrappers.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+/* MIPS syscall wrappers.
+   Copyright (C) 2017 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, see
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
+#include <sys/asm.h>
 
-#undef __mips16_syscall6
+       .text
+       .set    nomips16
 
-long long __nomips16
-__mips16_syscall6 (long a0, long a1, long a2, long a3,
-                  long a4, long a5,
-                  long number)
-{
-  union __mips16_syscall_return ret;
-  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 6,
-                                       a0, a1, a2, a3, a4, a5);
-  return ret.val;
-}
+/* long long __mips_syscall6 (long arg1, long arg2, long arg3, long arg4,
+                             long arg5, long arg6,
+                             long number)  */
+
+ENTRY(__mips_syscall6)
+       lw      v0, 24(sp)
+       syscall
+       move    v1, a3
+       jr      ra
+END(__mips_syscall6)
+libc_hidden_def (__mips_syscall6)
similarity index 59%
rename from sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c
rename to sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S
index e1267616dcf8bddf5e5665d4c13117c07ce6cc15..f7e742cc4d6f010a5d4b0258975764e9749dff2c 100644 (file)
@@ -1,5 +1,5 @@
-/* MIPS16 syscall wrappers.
-   Copyright (C) 2013-2017 Free Software Foundation, Inc.
+/* MIPS syscall wrappers.
+   Copyright (C) 2017 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, see
+   License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
+#include <sys/asm.h>
 
-#undef __mips16_syscall7
+       .text
+       .set    nomips16
 
-long long __nomips16
-__mips16_syscall7 (long a0, long a1, long a2, long a3,
-                  long a4, long a5, long a6,
-                  long number)
-{
-  union __mips16_syscall_return ret;
-  ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 7,
-                                       a0, a1, a2, a3, a4, a5, a6);
-  return ret.val;
-}
+/* long long __mips_syscall7 (long arg1, long arg2, long arg3, long arg4,
+                             long arg5, long arg6, long arg7,
+                             long number)  */
+
+ENTRY(__mips_syscall7)
+       lw      v0, 28(sp)
+       syscall
+       move    v1, a3
+       jr      ra
+END(__mips_syscall7)
+libc_hidden_def (__mips_syscall7)
index fa9fcb7e6f2e7009e58abb938942a4f3a12d770f..6869bf4f7c50bc18a7ea771a6bba68934014574a 100644 (file)
@@ -1,13 +1,9 @@
 ifeq ($(subdir),misc)
 sysdep_routines += mips16-syscall0 mips16-syscall1 mips16-syscall2
-sysdep_routines += mips16-syscall3 mips16-syscall4 mips16-syscall5
-sysdep_routines += mips16-syscall6 mips16-syscall7
+sysdep_routines += mips16-syscall3 mips16-syscall4
 CFLAGS-mips16-syscall0.c += -fexceptions
 CFLAGS-mips16-syscall1.c += -fexceptions
 CFLAGS-mips16-syscall2.c += -fexceptions
 CFLAGS-mips16-syscall3.c += -fexceptions
 CFLAGS-mips16-syscall4.c += -fexceptions
-CFLAGS-mips16-syscall5.c += -fexceptions
-CFLAGS-mips16-syscall6.c += -fexceptions
-CFLAGS-mips16-syscall7.c += -fexceptions
 endif
index 73bcfb566c9d370dc031ec91dfb6bcf553afecea..bb21747f4455334363c68aa0e66d7963fdaebe12 100644 (file)
@@ -1,6 +1,6 @@
 libc {
   GLIBC_PRIVATE {
     __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3;
-    __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7;
+    __mips16_syscall4;
   }
 }
index 880e9908e8759fc8b879caf7697e4e3c99848bf1..2ade219c6e79ae6f98ad881d084fd913683e4a5f 100644 (file)
 #ifndef MIPS16_SYSCALL_H
 #define MIPS16_SYSCALL_H 1
 
-#define __nomips16 __attribute__ ((nomips16))
-
-union __mips16_syscall_return
-  {
-    long long val;
-    struct
-      {
-       long v0;
-       long v1;
-      }
-    reg;
-  };
-
 long long __nomips16 __mips16_syscall0 (long number);
 #define __mips16_syscall0(dummy, number)                               \
        __mips16_syscall0 ((long) (number))
@@ -61,29 +48,22 @@ long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3,
                           (long) (a3),                                 \
                           (long) (number))
 
-long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3,
-                                       long a4,
-                                       long number);
+/* The remaining ones use regular MIPS wrappers.  */
+
 #define __mips16_syscall5(a0, a1, a2, a3, a4, number)                  \
-       __mips16_syscall5 ((long) (a0), (long) (a1), (long) (a2),       \
-                          (long) (a3), (long) (a4),                    \
-                          (long) (number))
+       __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2),         \
+                        (long) (a3), (long) (a4),                      \
+                        (long) (number))
 
-long long __nomips16 __mips16_syscall6 (long a0, long a1, long a2, long a3,
-                                       long a4, long a5,
-                                       long number);
 #define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number)              \
-       __mips16_syscall6 ((long) (a0), (long) (a1), (long) (a2),       \
-                          (long) (a3), (long) (a4), (long) (a5),       \
-                          (long) (number))
+       __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2),         \
+                        (long) (a3), (long) (a4), (long) (a5),         \
+                        (long) (number))
 
-long long __nomips16 __mips16_syscall7 (long a0, long a1, long a2, long a3,
-                                       long a4, long a5, long a6,
-                                       long number);
 #define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number)          \
-       __mips16_syscall7 ((long) (a0), (long) (a1), (long) (a2),       \
-                          (long) (a3), (long) (a4), (long) (a5),       \
-                          (long) (a6),                                 \
-                          (long) (number))
+       __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2),         \
+                        (long) (a3), (long) (a4), (long) (a5),         \
+                        (long) (a6),                                   \
+                        (long) (number))
 
 #endif
index 490245b34ec1bc448f24de097ff497376280a10a..51d946928227bb6cb9a5b104d8b62d9f3348fa33 100644 (file)
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
 
 #undef __mips16_syscall0
 
 long long __nomips16
 __mips16_syscall0 (long number)
 {
-  union __mips16_syscall_return ret;
+  union __mips_syscall_return ret;
   ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0);
   return ret.val;
 }
index 3061e8accb76ac4124ba840ddc23cecc4d45b901..13d57a78aa92b9ea46816ccfe431dbb03e2b484d 100644 (file)
@@ -17,7 +17,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
 
 #undef __mips16_syscall1
 
@@ -25,7 +24,7 @@ long long __nomips16
 __mips16_syscall1 (long a0,
                   long number)
 {
-  union __mips16_syscall_return ret;
+  union __mips_syscall_return ret;
   ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1,
                                        a0);
   return ret.val;
index 440a4ed285903773fc105e03f84498d460d62737..6e0e8d5bb5bfb04210d7865a231ad454087476da 100644 (file)
@@ -17,7 +17,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
 
 #undef __mips16_syscall2
 
@@ -25,7 +24,7 @@ long long __nomips16
 __mips16_syscall2 (long a0, long a1,
                   long number)
 {
-  union __mips16_syscall_return ret;
+  union __mips_syscall_return ret;
   ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2,
                                        a0, a1);
   return ret.val;
index c3f83fc1f69b4d210ebd55cd521a4d086d6ca74e..6bd6b8222bed3dcc2ba22d7bfaad47dd1fa86c4d 100644 (file)
@@ -17,7 +17,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
 
 #undef __mips16_syscall3
 
@@ -25,7 +24,7 @@ long long __nomips16
 __mips16_syscall3 (long a0, long a1, long a2,
                   long number)
 {
-  union __mips16_syscall_return ret;
+  union __mips_syscall_return ret;
   ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3,
                                        a0, a1, a2);
   return ret.val;
index 496297d296a7409db8ac74100c010771d0b99c6e..3847e4bc25d660d893f66b70a878b31a09881602 100644 (file)
@@ -17,7 +17,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <mips16-syscall.h>
 
 #undef __mips16_syscall4
 
@@ -25,7 +24,7 @@ long long __nomips16
 __mips16_syscall4 (long a0, long a1, long a2, long a3,
                   long number)
 {
-  union __mips16_syscall_return ret;
+  union __mips_syscall_return ret;
   ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4,
                                        a0, a1, a2, a3);
   return ret.val;
index e9e3ee7e82f9aee603d410cd8ab2edb785bc0b07..dadfa18de888e7bca41fefd58d58d142b7f23aa8 100644 (file)
 #undef INTERNAL_SYSCALL
 #undef INTERNAL_SYSCALL_NCS
 
+#define __nomips16 __attribute__ ((nomips16))
+
+union __mips_syscall_return
+  {
+    long long val;
+    struct
+      {
+       long v0;
+       long v1;
+      }
+    reg;
+  };
+
 #ifdef __mips16
 /* There's no MIPS16 syscall instruction, so we go through out-of-line
    standard MIPS wrappers.  These do use inline snippets below though,
 
 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                        \
 ({                                                                     \
-       union __mips16_syscall_return _sc_ret;                          \
+       union __mips_syscall_return _sc_ret;                            \
        _sc_ret.val = __mips16_syscall##nr (args, number);              \
        err = _sc_ret.reg.v1;                                           \
        _sc_ret.reg.v0;                                                 \
 # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...)             \
        internal_syscall##nr ("lw\t%0, %2\n\t",                         \
                              "R" (number),                             \
-                             0, err, args)
+                             number, err, args)
 
 #else /* !__mips16 */
 # 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)
+                             SYS_ify (name), err, args)
 
 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...)                        \
        internal_syscall##nr (MOVE32 "\t%0, %2\n\t",                    \
        _sys_result;                                                    \
 })
 
-/* We need to use a frame pointer for the functions in which we
-   adjust $sp around the syscall, or debug information and unwind
-   information will be $sp relative and thus wrong during the syscall.  As
-   of GCC 4.7, this is sufficient.  */
-#define FORCE_FRAME_POINTER                                            \
-  void *volatile __fp_force __attribute__ ((unused)) = alloca (4)
+/* Standalone MIPS wrappers used for 5, 6, and 7 argument syscalls,
+   which require stack arguments.  We rely on the compiler arranging
+   wrapper's arguments according to the MIPS o32 function calling
+   convention, which is reused by syscalls, except for the syscall
+   number passed and the error flag returned (taken care of in the
+   wrapper called).  This relieves us from relying on non-guaranteed
+   compiler specifics required for the stack arguments to be pushed,
+   which would be the case if these syscalls were inlined.  */
+
+long long __nomips16 __mips_syscall5 (long arg1, long arg2, long arg3,
+                                     long arg4, long arg5,
+                                     long number);
+libc_hidden_proto (__mips_syscall5, nomips16)
 
 #define internal_syscall5(v0_init, input, number, err,                 \
                          arg1, arg2, arg3, arg4, arg5)                 \
 ({                                                                     \
-       long _sys_result;                                               \
-                                                                       \
-       FORCE_FRAME_POINTER;                                            \
-       {                                                               \
-       register long __s0 asm ("$16") __attribute__ ((unused))         \
-         = (number);                                                   \
-       register long __v0 asm ("$2");                                  \
-       register long __a0 asm ("$4") = (long) (arg1);                  \
-       register long __a1 asm ("$5") = (long) (arg2);                  \
-       register long __a2 asm ("$6") = (long) (arg3);                  \
-       register long __a3 asm ("$7") = (long) (arg4);                  \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "subu\t$29, 32\n\t"                                             \
-       "sw\t%6, 16($29)\n\t"                                           \
-       v0_init                                                         \
-       "syscall\n\t"                                                   \
-       "addiu\t$29, 32\n\t"                                            \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
-         "r" ((long) (arg5))                                           \
-       : __SYSCALL_CLOBBERS);                                          \
-       err = __a3;                                                     \
-       _sys_result = __v0;                                             \
-       }                                                               \
-       _sys_result;                                                    \
+       union __mips_syscall_return _sc_ret;                            \
+       _sc_ret.val = __mips_syscall5 ((long) (arg1),                   \
+                                      (long) (arg2),                   \
+                                      (long) (arg3),                   \
+                                      (long) (arg4),                   \
+                                      (long) (arg5),                   \
+                                      (long) (number));                \
+       err = _sc_ret.reg.v1;                                           \
+       _sc_ret.reg.v0;                                                 \
 })
 
+long long __nomips16 __mips_syscall6 (long arg1, long arg2, long arg3,
+                                     long arg4, long arg5, long arg6,
+                                     long number);
+libc_hidden_proto (__mips_syscall6, nomips16)
+
 #define internal_syscall6(v0_init, input, number, err,                 \
                          arg1, arg2, arg3, arg4, arg5, arg6)           \
 ({                                                                     \
-       long _sys_result;                                               \
-                                                                       \
-       FORCE_FRAME_POINTER;                                            \
-       {                                                               \
-       register long __s0 asm ("$16") __attribute__ ((unused))         \
-         = (number);                                                   \
-       register long __v0 asm ("$2");                                  \
-       register long __a0 asm ("$4") = (long) (arg1);                  \
-       register long __a1 asm ("$5") = (long) (arg2);                  \
-       register long __a2 asm ("$6") = (long) (arg3);                  \
-       register long __a3 asm ("$7") = (long) (arg4);                  \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "subu\t$29, 32\n\t"                                             \
-       "sw\t%6, 16($29)\n\t"                                           \
-       "sw\t%7, 20($29)\n\t"                                           \
-       v0_init                                                         \
-       "syscall\n\t"                                                   \
-       "addiu\t$29, 32\n\t"                                            \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
-         "r" ((long) (arg5)), "r" ((long) (arg6))                      \
-       : __SYSCALL_CLOBBERS);                                          \
-       err = __a3;                                                     \
-       _sys_result = __v0;                                             \
-       }                                                               \
-       _sys_result;                                                    \
+       union __mips_syscall_return _sc_ret;                            \
+       _sc_ret.val = __mips_syscall6 ((long) (arg1),                   \
+                                      (long) (arg2),                   \
+                                      (long) (arg3),                   \
+                                      (long) (arg4),                   \
+                                      (long) (arg5),                   \
+                                      (long) (arg6),                   \
+                                      (long) (number));                \
+       err = _sc_ret.reg.v1;                                           \
+       _sc_ret.reg.v0;                                                 \
 })
 
+long long __nomips16 __mips_syscall7 (long arg1, long arg2, long arg3,
+                                     long arg4, long arg5, long arg6,
+                                     long arg7,
+                                     long number);
+libc_hidden_proto (__mips_syscall7, nomips16)
+
 #define internal_syscall7(v0_init, input, number, err,                 \
                          arg1, arg2, arg3, arg4, arg5, arg6, arg7)     \
 ({                                                                     \
-       long _sys_result;                                               \
-                                                                       \
-       FORCE_FRAME_POINTER;                                            \
-       {                                                               \
-       register long __s0 asm ("$16") __attribute__ ((unused))         \
-         = (number);                                                   \
-       register long __v0 asm ("$2");                                  \
-       register long __a0 asm ("$4") = (long) (arg1);                  \
-       register long __a1 asm ("$5") = (long) (arg2);                  \
-       register long __a2 asm ("$6") = (long) (arg3);                  \
-       register long __a3 asm ("$7") = (long) (arg4);                  \
-       __asm__ volatile (                                              \
-       ".set\tnoreorder\n\t"                                           \
-       "subu\t$29, 32\n\t"                                             \
-       "sw\t%6, 16($29)\n\t"                                           \
-       "sw\t%7, 20($29)\n\t"                                           \
-       "sw\t%8, 24($29)\n\t"                                           \
-       v0_init                                                         \
-       "syscall\n\t"                                                   \
-       "addiu\t$29, 32\n\t"                                            \
-       ".set\treorder"                                                 \
-       : "=r" (__v0), "+r" (__a3)                                      \
-       : input, "r" (__a0), "r" (__a1), "r" (__a2),                    \
-         "r" ((long) (arg5)), "r" ((long) (arg6)), "r" ((long) (arg7)) \
-       : __SYSCALL_CLOBBERS);                                          \
-       err = __a3;                                                     \
-       _sys_result = __v0;                                             \
-       }                                                               \
-       _sys_result;                                                    \
+       union __mips_syscall_return _sc_ret;                            \
+       _sc_ret.val = __mips_syscall7 ((long) (arg1),                   \
+                                      (long) (arg2),                   \
+                                      (long) (arg3),                   \
+                                      (long) (arg4),                   \
+                                      (long) (arg5),                   \
+                                      (long) (arg6),                   \
+                                      (long) (arg7),                   \
+                                      (long) (number));                \
+       err = _sc_ret.reg.v1;                                           \
+       _sc_ret.reg.v0;                                                 \
 })
 
 #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \