Message ID | alpine.DEB.2.00.1708232347420.17596@tp.orcam.me.uk |
---|---|
State | New |
Headers | show |
On 24/08/2017 10:26, Maciej W. Rozycki wrote: > From: Adhemerval Zanella <adhemerval.zanella@linaro.org> > > 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. > > 2017-08-24 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'. Patch LGTM, thanks for following this up. > > --- > On Mon, 21 Aug 2017, Adhemerval Zanella wrote: > >>> 2. I exported `__mips_syscall?' wrappers from `libc.so' rather than making >>> them hidden. This is also consistent with `__mips16_syscall?' wrappers >>> and reduces code duplication of doubtful benefit -- it could be that >>> some calls, if internal, could be subject to the JALR->BAL >>> optimisation, however only those that are in range and only in regular >>> MIPS code, for a minimal execution time saving on some processors only. >>> Exporting these entries makes the maintenance effort much easier >>> though, as we don't have to track and record their use in the >>> individual subdirectories in Makefile. >> >> In this case we can still have internal hidden calls for libc with the cost >> of code duplication by using hiden alias with: >> >> libc_hidden_proto (__mips_syscall{5,6,7}, nomips16) >> >> And with the pairing >> >> libc_hidden_def (__mips_syscall{5,6,7}); >> >> On implementation. > > Thanks for the hint. Actually that does not cause code duplication. > > I actually considered making hidden aliases available for use within > libc.so as a possible future improvement, but didn't realise it would be > as simple to arrange with the symbols defined in standalone assembly > code rather than C. This results in 61 BAL instructions replacing JALR > ones in my regular MIPS libc.so build. Nice improvement. > >>> Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S >>> =================================================================== >>> --- /dev/null 1970-01-01 00:00:00.000000000 +0000 >>> +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S 2017-08-20 03:02:13.583854495 +0100 >>> @@ -0,0 +1,33 @@ >> >> One line comment to describe this file. > > I pinched the terse comment used across the existing MIPS16 wrappers > (with s/MIPS16/MIPS/ applied); I hope this is good enough as otherwise the > code should be self-explanatory. I think it is good enough. > >>> @@ -262,110 +275,65 @@ >>> _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) >>> +/* Out-of-line standard MIPS wrappers used for 5, 6, and 7 argument >>> + syscalls, which require stack arguments. */ >> >> I think it is worth to add a comment why we are using out-of-line wrappers >> for syscalls with 5, 6, and 7 arguments. > > Good point, let me know if what I came up with is comprehensive enough. > > This update has passed regular MIPS and MIPS16 o32 regression testing, > with no regressions. OK to apply? Ok from my side. > > NB while looking at it I've noticed we do not pass any `-O' optimisation > flag to the GCC driver while building .S files. That in turn means no GAS > branch optimisation is enabled and consequently branch delay slots are not > scheduled in `reorder' code by the assembler (the MIPS/GCC `asm' spec has > this `%{noasmopt:-O0; O0|fno-delayed-branch:-O1; O*:-O2; :-O1}'), causing > delay slots wasted with a NOP where a preceding instruction could be moved > instead and save some code space. It can be easily observed by comparing > code in the compiler-generated MIPS16 wrappers vs the new standalone > assembly regular MIPS (and microMIPS) wrappers. > > Was this a deliberate choice made sometime to have greater control over > code produced or just an accidental oversight? I am not sure if it was deliberate, but my guess it is not really an issue for most architectures since afaik any '-O' optimization flag along with .S files usually does not turn any extra flags (SUBTARGET_ASM_SPEC seems to be define only in a handful architectures on gcc). For MIPS I think we can set ASFLAGS to O1 since it should enable the required optimization, unless there is an specific gas option to enable it (which I couldn't find). Another option would be to filter out CFLAGS and extract the optimization level used for ASFLAGS, but I think for this specific issue it should extra non required complexity. Another thing I noticed is another possible optimization for size would to use ".set push", ".set noreorder", and ".set pop" instead of current code as below. Using GCC 6.2.1 and binutils 2.27 I noted building for mips16 (using a strip libc.so for both): - base: section size .text 966480 .eh_frame_hdr 8764 .eh_frame 36628 .pdr 97568 - patched: section size .text 966160 .eh_frame_hdr 8732 .eh_frame 36492 .pdr 97440 Not that much, but still a gain. Using O1 (as below) shows some more slight gains: section size .text 966096 .eh_frame_hdr 8732 .eh_frame 36492 .pdr 97440 --- diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile index 7c1d779..1130015 100644 --- a/sysdeps/mips/Makefile +++ b/sysdeps/mips/Makefile @@ -83,3 +83,9 @@ $(objpfx)tst-mode-switch-2: $(shared-thread-library) endif endif endif + +# Enable delay branch optimization +ASFLAGS-.o += -O1 +ASFLAGS-.os += -O1 +ASFLAGS-.op += -O1 +ASFLAGS-.oS += -O2 --- diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index dadfa18..96867de 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -159,10 +159,11 @@ union __mips_syscall_return register long __v0 asm ("$2"); \ register long __a3 asm ("$7"); \ __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ + ".set push\n\t" \ + ".set noreorder\n\t" \ v0_init \ "syscall\n\t" \ - ".set reorder" \ + ".set pop" \ : "=r" (__v0), "=r" (__a3) \ : input \ : __SYSCALL_CLOBBERS); \ @@ -183,10 +184,11 @@ union __mips_syscall_return register long __a0 asm ("$4") = (long) (arg1); \ register long __a3 asm ("$7"); \ __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ + ".set push\n\t" \ + ".set noreorder\n\t" \ v0_init \ "syscall\n\t" \ - ".set reorder" \ + ".set pop" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0) \ : __SYSCALL_CLOBBERS); \ @@ -208,10 +210,11 @@ union __mips_syscall_return register long __a1 asm ("$5") = (long) (arg2); \ register long __a3 asm ("$7"); \ __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ + ".set push\n\t" \ + ".set noreorder\n\t" \ v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set pop" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1) \ : __SYSCALL_CLOBBERS); \ @@ -235,10 +238,11 @@ union __mips_syscall_return register long __a2 asm ("$6") = (long) (arg3); \ register long __a3 asm ("$7"); \ __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ + ".set push\n\t" \ + ".set noreorder\n\t" \ v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set pop" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ @@ -262,10 +266,11 @@ union __mips_syscall_return register long __a2 asm ("$6") = (long) (arg3); \ register long __a3 asm ("$7") = (long) (arg4); \ __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ + ".set push\n\t" \ + ".set noreorder\n\t" \ v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set pop" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ > > Maciej > > --- > sysdeps/unix/sysv/linux/mips/mips32/Makefile | 4 > sysdeps/unix/sysv/linux/mips/mips32/Versions | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S | 35 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S | 35 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S | 35 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile | 6 > sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions | 2 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h | 44 -- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 163 ++++------- > 17 files changed, 201 insertions(+), 240 deletions(-) > > glibc-aurelien-mips-o32-syscall.diff > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 21:30:35.093821957 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-22 20:33:16.504589387 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 21:30:35.142707136 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-22 20:33:16.571894966 +0100 > @@ -3,4 +3,7 @@ libc { > getrlimit64; > setrlimit64; > } > + GLIBC_PRIVATE { > + __mips_syscall5; __mips_syscall6; __mips_syscall7; > + } > } > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S 2017-08-22 20:47:54.745857965 +0100 > @@ -0,0 +1,35 @@ > +/* 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 > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + 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 > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* 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) > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S 2017-08-22 20:47:47.596264940 +0100 > @@ -0,0 +1,35 @@ > +/* 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 > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + 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 > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* 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) > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S 2017-08-22 20:47:25.781928113 +0100 > @@ -0,0 +1,35 @@ > +/* 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 > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + 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 > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* 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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 21:30:35.448096086 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-22 20:33:16.687468562 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 21:30:35.487709423 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-22 20:33:16.719930829 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 21:30:35.540283348 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-22 20:33:16.732035716 +0100 > @@ -19,19 +19,6 @@ > #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) (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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 21:30:35.557630985 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-22 20:33:16.741195496 +0100 > @@ -17,14 +17,13 @@ > <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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 21:30:35.658293922 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-22 20:33:16.758455153 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 21:30:35.769000365 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-22 20:33:16.768703866 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 21:30:35.796726756 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-22 20:33:16.779819073 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 21:30:35.819263979 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-22 20:33:16.794914009 +0100 > @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2017-08-20 21:30:35.822296212 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-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 > - modify it under the terms of the GNU Lesser General Public > - License as published by the Free Software Foundation; either > - version 2.1 of the License, or (at your option) any later version. > - > - The GNU C Library is distributed in the hope that it will be useful, > - but WITHOUT ANY WARRANTY; without even the implied warranty of > - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - 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 > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall5 > - > -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; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2017-08-20 21:30:35.838512882 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-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 > - modify it under the terms of the GNU Lesser General Public > - License as published by the Free Software Foundation; either > - version 2.1 of the License, or (at your option) any later version. > - > - The GNU C Library is distributed in the hope that it will be useful, > - but WITHOUT ANY WARRANTY; without even the implied warranty of > - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - 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 > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall6 > - > -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; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2017-08-20 21:30:35.846816836 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-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 > - modify it under the terms of the GNU Lesser General Public > - License as published by the Free Software Foundation; either > - version 2.1 of the License, or (at your option) any later version. > - > - The GNU C Library is distributed in the hope that it will be useful, > - but WITHOUT ANY WARRANTY; without even the implied warranty of > - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - 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 > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall7 > - > -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; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 21:30:35.944796826 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-22 23:13:25.010701782 +0100 > @@ -98,6 +98,19 @@ > #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, > @@ -112,7 +125,7 @@ > > # 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; \ > @@ -121,13 +134,13 @@ > # 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", \ > @@ -262,110 +275,74 @@ > _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", \ >
On 2017-08-24 14:26, Maciej W. Rozycki wrote: > From: Adhemerval Zanella <adhemerval.zanella@linaro.org> > > 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. > > 2017-08-24 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'. > > --- Thanks for this new version, it looks good to me. Aurelien -- Aurelien Jarno GPG: 4096R/1DDD8C9B aurelien@aurel32.net http://www.aurel32.net
On Thu, 24 Aug 2017, Adhemerval Zanella wrote: > > This update has passed regular MIPS and MIPS16 o32 regression testing, > > with no regressions. OK to apply? > > Ok from my side. I have applied it to master now; thanks to everyone involved. As a fix for a functional regression (as demonstrated by `tst-rwlock15') do we want to have it in 2.25 and 2.26 as well? I'll continue the discussion about assembly optimisation separately. Maciej
On 2017-08-29 19:00, Maciej W. Rozycki wrote: > On Thu, 24 Aug 2017, Adhemerval Zanella wrote: > > > > This update has passed regular MIPS and MIPS16 o32 regression testing, > > > with no regressions. OK to apply? > > > > Ok from my side. > > I have applied it to master now; thanks to everyone involved. As a fix > for a functional regression (as demonstrated by `tst-rwlock15') do we want > to have it in 2.25 and 2.26 as well? That might be a good idea. At least Debian is now using this patch, and we regularly pull from the upstream stable branch. I can take care of that in the next days. Aurelien -- Aurelien Jarno GPG: 4096R/1DDD8C9B aurelien@aurel32.net http://www.aurel32.net
Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 21:30:35.093821957 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-22 20:33:16.504589387 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 21:30:35.142707136 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-22 20:33:16.571894966 +0100 @@ -3,4 +3,7 @@ libc { getrlimit64; setrlimit64; } + GLIBC_PRIVATE { + __mips_syscall5; __mips_syscall6; __mips_syscall7; + } } Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S 2017-08-22 20:47:54.745857965 +0100 @@ -0,0 +1,35 @@ +/* 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* 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) Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S 2017-08-22 20:47:47.596264940 +0100 @@ -0,0 +1,35 @@ +/* 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* 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) Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S 2017-08-22 20:47:25.781928113 +0100 @@ -0,0 +1,35 @@ +/* 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + 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 + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* 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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 21:30:35.448096086 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-22 20:33:16.687468562 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 21:30:35.487709423 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-22 20:33:16.719930829 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 21:30:35.540283348 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-22 20:33:16.732035716 +0100 @@ -19,19 +19,6 @@ #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) (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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 21:30:35.557630985 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-22 20:33:16.741195496 +0100 @@ -17,14 +17,13 @@ <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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 21:30:35.658293922 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-22 20:33:16.758455153 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 21:30:35.769000365 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-22 20:33:16.768703866 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 21:30:35.796726756 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-22 20:33:16.779819073 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 21:30:35.819263979 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-22 20:33:16.794914009 +0100 @@ -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: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2017-08-20 21:30:35.822296212 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-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 - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - 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 - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall5 - -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; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2017-08-20 21:30:35.838512882 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-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 - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - 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 - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall6 - -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; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2017-08-20 21:30:35.846816836 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-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 - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - 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 - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall7 - -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; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 21:30:35.944796826 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-22 23:13:25.010701782 +0100 @@ -98,6 +98,19 @@ #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, @@ -112,7 +125,7 @@ # 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; \ @@ -121,13 +134,13 @@ # 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", \ @@ -262,110 +275,74 @@ _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", \