diff options
Diffstat (limited to 'ports/sysdeps/unix/sysv/linux/mips')
47 files changed, 854 insertions, 329 deletions
diff --git a/ports/sysdeps/unix/sysv/linux/mips/Makefile b/ports/sysdeps/unix/sysv/linux/mips/Makefile index 66ba621dae..1e54036bfe 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/Makefile +++ b/ports/sysdeps/unix/sysv/linux/mips/Makefile @@ -8,9 +8,6 @@ sysdep_routines += cachectl cacheflush sysmips _test_and_set sysdep_headers += sys/cachectl.h sys/sysmips.h sys/tas.h endif -# Get value of default-abi. -include $(common-objpfx)default-abi.make - abi-variants := o32_soft o32_hard n32_soft n32_hard n64_soft n64_hard ifeq (,$(filter $(default-abi),$(abi-variants))) diff --git a/ports/sysdeps/unix/sysv/linux/mips/bits/mman.h b/ports/sysdeps/unix/sysv/linux/mips/bits/mman.h index a13a900961..b327795f89 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/bits/mman.h +++ b/ports/sysdeps/unix/sysv/linux/mips/bits/mman.h @@ -23,41 +23,9 @@ /* The following definitions basically come from the kernel headers. But the kernel header is not namespace clean. */ - -/* Protections are chosen from these bits, OR'd together. The - implementation does not necessarily support PROT_EXEC or PROT_WRITE - without PROT_READ. The only guarantees are that no writing will be - allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ - -#define PROT_READ 0x1 /* Page can be read. */ -#define PROT_WRITE 0x2 /* Page can be written. */ -#define PROT_EXEC 0x4 /* Page can be executed. */ -#define PROT_NONE 0x0 /* Page can not be accessed. */ -#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of - growsdown vma (mprotect only). */ -#define PROT_GROWSUP 0x02000000 /* Extend change to start of - growsup vma (mprotect only). */ - -/* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes are private. */ -#ifdef __USE_MISC -# define MAP_TYPE 0x0f /* Mask for type of mapping. */ -#endif - -/* Other flags. */ -#define MAP_FIXED 0x10 /* Interpret addr exactly. */ -#ifdef __USE_MISC -# define MAP_FILE 0 -# define MAP_ANONYMOUS 0x0800 /* Don't use a file. */ -# define MAP_ANON MAP_ANONYMOUS -# define MAP_RENAME MAP_ANONYMOUS -#endif - /* These are Linux-specific. */ #ifdef __USE_MISC # define MAP_NORESERVE 0x0400 /* don't check for reservations */ -# define MAP_ANONYMOUS 0x0800 /* don't use a file */ # define MAP_GROWSDOWN 0x1000 /* stack-like segment */ # define MAP_DENYWRITE 0x2000 /* ETXTBSY */ # define MAP_EXECUTABLE 0x4000 /* mark it as an executable */ @@ -68,47 +36,11 @@ # define MAP_HUGETLB 0x80000 /* Create huge page mapping. */ #endif -/* Flags to `msync'. */ -#define MS_ASYNC 1 /* Sync memory asynchronously. */ -#define MS_SYNC 4 /* Synchronous memory sync. */ -#define MS_INVALIDATE 2 /* Invalidate the caches. */ - -/* Flags for `mlockall'. */ -#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ -#define MCL_FUTURE 2 /* Lock all additions to address - space. */ - -/* Flags for `mremap'. */ -#ifdef __USE_GNU -# define MREMAP_MAYMOVE 1 -# define MREMAP_FIXED 2 -#endif +#define __MAP_ANONYMOUS 0x0800 -/* Advice to `madvise'. */ -#ifdef __USE_BSD -# define MADV_NORMAL 0 /* No further special treatment. */ -# define MADV_RANDOM 1 /* Expect random page references. */ -# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -# define MADV_WILLNEED 3 /* Will need these pages. */ -# define MADV_DONTNEED 4 /* Don't need these pages. */ -# define MADV_REMOVE 9 /* Remove these pages and resources. */ -# define MADV_DONTFORK 10 /* Do not inherit across fork. */ -# define MADV_DOFORK 11 /* Do inherit across fork. */ -# define MADV_MERGEABLE 12 /* KSM may merge identical pages. */ -# define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages. */ -# define MADV_HUGEPAGE 14 /* Worth backing with hugepages. */ -# define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages. */ -# define MADV_DONTDUMP 16 /* Explicity exclude from the core dump, - overrides the coredump filter bits. */ -# define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag. */ -# define MADV_HWPOISON 100 /* Poison a page for testing. */ -#endif +/* Include generic Linux declarations. */ +#include <bits/mman-linux.h> -/* The POSIX people had to invent similar names for the same things. */ -#ifdef __USE_XOPEN2K -# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ -# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ -# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ -# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_MISC +# define MAP_RENAME MAP_ANONYMOUS #endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/bits/msq.h b/ports/sysdeps/unix/sysv/linux/mips/bits/msq.h index 8439069cd7..e814bc722f 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/bits/msq.h +++ b/ports/sysdeps/unix/sysv/linux/mips/bits/msq.h @@ -25,6 +25,7 @@ #define MSG_NOERROR 010000 /* no error if message is too big */ #ifdef __USE_GNU # define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +# define MSG_COPY 040000 /* copy (not remove) all queue messages */ #endif /* Types used in the structure definition. */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/brk.c b/ports/sysdeps/unix/sysv/linux/mips/brk.c index 9bd6d94bd1..07c8a9649f 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/brk.c +++ b/ports/sysdeps/unix/sysv/linux/mips/brk.c @@ -30,19 +30,10 @@ weak_alias (__curbrk, ___brk_addr) int __brk (void *addr) { + INTERNAL_SYSCALL_DECL (err); void *newbrk; - { - register long int res __asm__ ("$2"); - - asm ("move\t$4,%2\n\t" - "li\t%0,%1\n\t" - "syscall" /* Perform the system call. */ - : "=r" (res) - : "I" (SYS_ify (brk)), "r" (addr) - : "$4", "$7", __SYSCALL_CLOBBERS); - newbrk = (void *) res; - } + newbrk = (void *) INTERNAL_SYSCALL (brk, err, 1, addr); __curbrk = newbrk; if (newbrk < addr) diff --git a/ports/sysdeps/unix/sysv/linux/mips/clone.S b/ports/sysdeps/unix/sysv/linux/mips/clone.S index 72360f9621..f6f2f05659 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/clone.S +++ b/ports/sysdeps/unix/sysv/linux/mips/clone.S @@ -34,6 +34,7 @@ void *parent_tidptr, void *tls, void *child_tidptr) */ .text + .set nomips16 #if _MIPS_SIM == _ABIO32 # define EXTRA_LOCALS 1 #else @@ -47,7 +48,8 @@ NESTED(__clone,4*SZREG,sp) SETUP_GP #endif PTR_SUBU sp, FRAMESZ - SETUP_GP64 (GPOFF, __clone) + cfi_adjust_cfa_offset (FRAMESZ) + SETUP_GP64_STACK (GPOFF, __clone) #ifdef __PIC__ SAVE_GP (GPOFF) #endif @@ -88,26 +90,35 @@ NESTED(__clone,4*SZREG,sp) /* Do the system call */ li v0,__NR_clone + cfi_endproc syscall bnez a3,L(error) beqz v0,L(thread_start) /* Successful return from the parent */ - RESTORE_GP64 + cfi_startproc + cfi_adjust_cfa_offset (FRAMESZ) + SETUP_GP64_STACK_CFI (GPOFF) + cfi_remember_state + RESTORE_GP64_STACK PTR_ADDU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) ret /* Something bad happened -- no child created */ L(error): + cfi_restore_state #ifdef __PIC__ PTR_LA t9,__syscall_error - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) jr t9 #else - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) j __syscall_error #endif END(__clone) @@ -118,6 +129,7 @@ L(error): ENTRY(__thread_start) L(thread_start): + cfi_undefined ($31) /* cp is already loaded. */ SAVE_GP (GPOFF) /* The stackframe has been created on entry of clone(). */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/configure b/ports/sysdeps/unix/sysv/linux/mips/configure index cecfc9d84c..b4ee83e3ae 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/configure +++ b/ports/sysdeps/unix/sysv/linux/mips/configure @@ -105,7 +105,8 @@ if test -z "$libc_mips_float"; then as_fn_error $? "could not determine if compiler is using hard or soft floating point ABI" "$LINENO" 5 fi -echo "default-abi := ${libc_mips_abi}_${libc_mips_float}" > default-abi.make +config_vars="$config_vars +default-abi = ${libc_mips_abi}_${libc_mips_float}" case "$prefix" in /usr | /usr/) diff --git a/ports/sysdeps/unix/sysv/linux/mips/configure.in b/ports/sysdeps/unix/sysv/linux/mips/configure.in index 167779eaf9..b8dde6ef7a 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/configure.in +++ b/ports/sysdeps/unix/sysv/linux/mips/configure.in @@ -44,7 +44,7 @@ if test -z "$libc_mips_float"; then AC_MSG_ERROR([could not determine if compiler is using hard or soft floating point ABI]) fi -echo "default-abi := ${libc_mips_abi}_${libc_mips_float}" > default-abi.make +LIBC_CONFIG_VAR([default-abi], [${libc_mips_abi}_${libc_mips_float}]) case "$prefix" in /usr | /usr/) diff --git a/ports/sysdeps/unix/sysv/linux/mips/getcontext.S b/ports/sysdeps/unix/sysv/linux/mips/getcontext.S index 0e3d35b54f..268098c0b1 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/getcontext.S +++ b/ports/sysdeps/unix/sysv/linux/mips/getcontext.S @@ -27,6 +27,7 @@ /* int getcontext (ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 MASK = 0x00000000 #ifdef __PIC__ @@ -54,7 +55,8 @@ NESTED (__getcontext, FRAMESZ, ra) # endif PTR_ADDIU sp, -FRAMESZ - SETUP_GP64 (GPOFF, __getcontext) + cfi_adjust_cfa_offset (FRAMESZ) + SETUP_GP64_STACK (GPOFF, __getcontext) SAVE_GP (GPOFF) #else /* ! __PIC__ */ @@ -124,19 +126,23 @@ NESTED (__getcontext, FRAMESZ, ra) li v0, SYS_ify (rt_sigprocmask) syscall bnez a3, 99f + cfi_remember_state #ifdef __PIC__ - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDIU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) #endif move v0, zero jr ra 99: + cfi_restore_state #ifdef __PIC__ PTR_LA t9, JUMPTARGET (__syscall_error) - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDIU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) jr t9 #else /* ! __PIC__ */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/makecontext.S b/ports/sysdeps/unix/sysv/linux/mips/makecontext.S index 65f1a6aaa2..a8bbebbcc0 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/makecontext.S +++ b/ports/sysdeps/unix/sysv/linux/mips/makecontext.S @@ -27,6 +27,7 @@ /* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 @@ -63,9 +64,10 @@ NESTED (__makecontext, FRAMESZ, ra) #endif PTR_ADDIU sp, -FRAMESZ + cfi_adjust_cfa_offset (FRAMESZ) #ifdef __PIC__ - SETUP_GP64 (GPOFF, __makecontext) + SETUP_GP64_STACK (GPOFF, __makecontext) SAVE_GP (GPOFF) #endif @@ -145,8 +147,9 @@ NESTED (__makecontext, FRAMESZ, ra) REG_S a1, MCONTEXT_PC(a0) #ifdef __PIC__ - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDIU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) #endif jr ra diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile new file mode 100644 index 0000000000..fa9fcb7e6f --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile @@ -0,0 +1,13 @@ +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 +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 diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions new file mode 100644 index 0000000000..73bcfb566c --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions @@ -0,0 +1,6 @@ +libc { + GLIBC_PRIVATE { + __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; + __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + } +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h new file mode 100644 index 0000000000..8449836d32 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h @@ -0,0 +1,89 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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/>. */ + +#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)) + +long long __nomips16 __mips16_syscall1 (long a0, + long number); +#define __mips16_syscall1(a0, number) \ + __mips16_syscall1 ((long) (a0), \ + (long) (number)) + +long long __nomips16 __mips16_syscall2 (long a0, long a1, + long number); +#define __mips16_syscall2(a0, a1, number) \ + __mips16_syscall2 ((long) (a0), (long) (a1), \ + (long) (number)) + +long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2, + long number); +#define __mips16_syscall3(a0, a1, a2, number) \ + __mips16_syscall3 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (number)) + +long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3, + long number); +#define __mips16_syscall4(a0, a1, a2, a3, number) \ + __mips16_syscall4 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), \ + (long) (number)) + +long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3, + long a4, + long number); +#define __mips16_syscall5(a0, a1, a2, a3, a4, number) \ + __mips16_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)) + +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)) + +#endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c new file mode 100644 index 0000000000..0cdf94c22c --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c @@ -0,0 +1,30 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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_syscall0 + +long long __nomips16 +__mips16_syscall0 (long number) +{ + union __mips16_syscall_return ret; + ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0); + return ret.val; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c new file mode 100644 index 0000000000..5e60a59d56 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c @@ -0,0 +1,32 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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_syscall1 + +long long __nomips16 +__mips16_syscall1 (long a0, + long number) +{ + union __mips16_syscall_return ret; + ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1, + a0); + return ret.val; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c new file mode 100644 index 0000000000..7750c519ce --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c @@ -0,0 +1,32 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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_syscall2 + +long long __nomips16 +__mips16_syscall2 (long a0, long a1, + long number) +{ + union __mips16_syscall_return ret; + ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2, + a0, a1); + return ret.val; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c new file mode 100644 index 0000000000..7fc1c4e435 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c @@ -0,0 +1,32 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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_syscall3 + +long long __nomips16 +__mips16_syscall3 (long a0, long a1, long a2, + long number) +{ + union __mips16_syscall_return ret; + ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3, + a0, a1, a2); + return ret.val; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c new file mode 100644 index 0000000000..b8b4198c78 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c @@ -0,0 +1,32 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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_syscall4 + +long long __nomips16 +__mips16_syscall4 (long a0, long a1, long a2, long a3, + long number) +{ + union __mips16_syscall_return ret; + ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4, + a0, a1, a2, a3); + return ret.val; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c new file mode 100644 index 0000000000..e1322d107f --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c @@ -0,0 +1,33 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c new file mode 100644 index 0000000000..a9e5cd9dfe --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c @@ -0,0 +1,33 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c new file mode 100644 index 0000000000..d87b5ba5a8 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c @@ -0,0 +1,33 @@ +/* MIPS16 syscall wrappers. + Copyright (C) 2013 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; +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist index 7378869236..f01278e4a4 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/nptl/libc.abilist @@ -1390,6 +1390,19 @@ GLIBC_2.16 mbrtoc16 F mbrtoc32 F timespec_get F +GLIBC_2.17 + GLIBC_2.17 A + clock_getcpuclockid F + clock_getres F + clock_gettime F + clock_nanosleep F + clock_settime F + secure_getenv F +GLIBC_2.18 + GLIBC_2.18 A + __cxa_thread_atexit_impl F + __mips_fpu_getcw F + __mips_fpu_setcw F GLIBC_2.2 GLIBC_2.2 A _Exit F @@ -2242,11 +2255,3 @@ GLIBC_2.9 pipe2 F _gp_disp _gp_disp A -GLIBC_2.17 - GLIBC_2.17 A - clock_getcpuclockid F - clock_getres F - clock_gettime F - clock_nanosleep F - clock_settime F - secure_getenv F diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index e79fda9372..0faf68c4fc 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -67,25 +67,86 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) -#undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +/* Note that the original Linux syscall restart convention required the + instruction immediately preceding SYSCALL to initialize $v0 with the + syscall number. Then if a restart triggered, $v0 would have been + clobbered by the syscall interrupted, and needed to be reinititalized. + The kernel would decrement the PC by 4 before switching back to the + user mode so that $v0 had been reloaded before SYSCALL was executed + again. This implied the place $v0 was loaded from must have been + preserved across a syscall, e.g. an immediate, static register, stack + slot, etc. + + The convention was relaxed in Linux with a change applied to the kernel + GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that + first appeared in the 2.6.36 release. Since then the kernel has had + code that reloads $v0 upon syscall restart and resumes right at the + SYSCALL instruction, so no special arrangement is needed anymore. + + For backwards compatibility with existing kernel binaries we support + the old convention by choosing the instruction preceding SYSCALL + carefully. This also means we have to force a 32-bit encoding of the + microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif +#undef INTERNAL_SYSCALL #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#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, + through INTERNAL_SYSCALL_MIPS16. Spilling the syscall number to + memory gives the best code in that case, avoiding the need to save + and restore a static register. */ + +# include <mips16-syscall.h> + +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, args) + +# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ +({ \ + union __mips16_syscall_return ret; \ + ret.val = __mips16_syscall##nr (args, number); \ + err = ret.reg.v1; \ + 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) + +#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) + +# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) + +#endif /* !__mips16 */ + +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a3 asm("$7"); \ + register long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm ("$2"); \ + register long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -97,17 +158,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a0 asm("$4") = (long) (arg1); \ - register long __a3 asm("$7"); \ + register long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm ("$2"); \ + register long __a0 asm ("$4") = (long) (arg1); \ + register long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -119,20 +182,22 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a0 asm("$4") = (long) (arg1); \ - register long __a1 asm("$5") = (long) (arg2); \ - register long __a3 asm("$7"); \ + 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 __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1) \ : __SYSCALL_CLOBBERS); \ @@ -142,21 +207,24 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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"); \ + 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"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ @@ -166,21 +234,24 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ + 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" \ - cs_init \ + v0_init \ "syscall\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ @@ -197,25 +268,28 @@ #define FORCE_FRAME_POINTER \ void *volatile __fp_force __attribute__ ((unused)) = alloca (4) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ + 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" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)) \ @@ -226,26 +300,29 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ + 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" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)), "r" ((long) (arg6)) \ @@ -256,27 +333,30 @@ _sys_result; \ }) -#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +#define internal_syscall7(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ ({ \ long _sys_result; \ \ FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ + 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" \ - cs_init \ + v0_init \ "syscall\n\t" \ "addiu\t$29, 32\n\t" \ - ".set\treorder" \ + ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long) (arg5)), "r" ((long) (arg6)), "r" ((long) (arg7)) \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/truncate64.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/truncate64.c index 4367d1efee..6e52e32637 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips32/truncate64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/truncate64.c @@ -22,7 +22,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> /* Truncate the file FD refers to to LENGTH bytes. */ int @@ -30,7 +29,7 @@ truncate64 (const char *path, off64_t length) { unsigned int low = length & 0xffffffff; unsigned int high = length >> 32; - int result = INLINE_SYSCALL (truncate64, 4, CHECK_STRING (path), 0, + int result = INLINE_SYSCALL (truncate64, 4, path, 0, __LONG_LONG_PAIR (high, low)); return result; } diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c index 017b39d608..624994022f 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c @@ -23,7 +23,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <xstatconv.h> @@ -35,7 +34,7 @@ __fxstat64 (int vers, int fd, struct stat64 *buf) int result; struct kernel_stat kbuf; - result = INLINE_SYSCALL (fstat, 2, fd, __ptrvalue (&kbuf)); + result = INLINE_SYSCALL (fstat, 2, fd, &kbuf); if (result == 0) result = __xstat64_conv (vers, &kbuf, buf); diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c index 32571e717d..ca2f2f6153 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c @@ -25,7 +25,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <kernel-features.h> @@ -96,11 +95,9 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) } if (flag & AT_SYMLINK_NOFOLLOW) - result = INTERNAL_SYSCALL (lstat, err, 2, CHECK_STRING (file), - __ptrvalue (&kst)); + result = INTERNAL_SYSCALL (lstat, err, 2, file, &kst); else - result = INTERNAL_SYSCALL (stat, err, 2, CHECK_STRING (file), - __ptrvalue (&kst)); + result = INTERNAL_SYSCALL (stat, err, 2, file, &kst); if (__builtin_expect (!INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return __xstat64_conv (vers, &kst, st); diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c index 106271f759..b01204deb7 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c @@ -23,7 +23,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <xstatconv.h> @@ -34,7 +33,7 @@ __lxstat64 (int vers, const char *name, struct stat64 *buf) int result; struct kernel_stat kbuf; - result = INLINE_SYSCALL (lstat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = INLINE_SYSCALL (lstat, 2, name, &kbuf); if (result == 0) result = __xstat64_conv (vers, &kbuf, buf); diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c index b8905edd7d..3b94b1befe 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/msgctl.c @@ -20,14 +20,12 @@ #include <ipc_priv.h> #include <sysdep.h> -#include <bp-checks.h> - int __msgctl (int msqid, int cmd, struct msqid_ds *buf); int __msgctl (int msqid, int cmd, struct msqid_ds *buf) { - return INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, CHECK_1 (buf)); + return INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, buf); } #include <shlib-compat.h> diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist index df2e63728a..9dbbd97c8e 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/nptl/libc.abilist @@ -1398,6 +1398,9 @@ GLIBC_2.17 clock_nanosleep F clock_settime F secure_getenv F +GLIBC_2.18 + GLIBC_2.18 A + __cxa_thread_atexit_impl F GLIBC_2.2 GLIBC_2.2 A _Exit F diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h index 3ebbf892f7..452c2c70eb 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h @@ -71,25 +71,57 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) +/* Note that the original Linux syscall restart convention required the + instruction immediately preceding SYSCALL to initialize $v0 with the + syscall number. Then if a restart triggered, $v0 would have been + clobbered by the syscall interrupted, and needed to be reinititalized. + The kernel would decrement the PC by 4 before switching back to the + user mode so that $v0 had been reloaded before SYSCALL was executed + again. This implied the place $v0 was loaded from must have been + preserved across a syscall, e.g. an immediate, static register, stack + slot, etc. + + The convention was relaxed in Linux with a change applied to the kernel + GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that + first appeared in the 2.6.36 release. Since then the kernel has had + code that reloads $v0 upon syscall restart and resumes right at the + SYSCALL instruction, so no special arrangement is needed anymore. + + For backwards compatibility with existing kernel binaries we support + the old convention by choosing the instruction preceding SYSCALL + carefully. This also means we have to force a 32-bit encoding of the + microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif + #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ + "IK" (SYS_ify (name)), \ + 0, err, args) #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a3 asm("$7"); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -101,17 +133,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a3 asm("$7"); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -123,18 +157,20 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a1 asm("$5") = ARGIFY (arg2); \ - register long long __a3 asm("$7"); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a1 asm ("$5") = ARGIFY (arg2); \ + register long long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -146,19 +182,22 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3) \ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a1 asm("$5") = ARGIFY (arg2); \ - register long long __a2 asm("$6") = ARGIFY (arg3); \ - register long long __a3 asm("$7"); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a1 asm ("$5") = ARGIFY (arg2); \ + register long long __a2 asm ("$6") = ARGIFY (arg3); \ + register long long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -170,19 +209,22 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4) \ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a1 asm("$5") = ARGIFY (arg2); \ - register long long __a2 asm("$6") = ARGIFY (arg3); \ - register long long __a3 asm("$7") = ARGIFY (arg4); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a1 asm ("$5") = ARGIFY (arg2); \ + register long long __a2 asm ("$6") = ARGIFY (arg3); \ + register long long __a3 asm ("$7") = ARGIFY (arg4); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -194,20 +236,23 @@ _sys_result; \ }) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a1 asm("$5") = ARGIFY (arg2); \ - register long long __a2 asm("$6") = ARGIFY (arg3); \ - register long long __a3 asm("$7") = ARGIFY (arg4); \ - register long long __a4 asm("$8") = ARGIFY (arg5); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a1 asm ("$5") = ARGIFY (arg2); \ + register long long __a2 asm ("$6") = ARGIFY (arg3); \ + register long long __a3 asm ("$7") = ARGIFY (arg4); \ + register long long __a4 asm ("$8") = ARGIFY (arg5); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -219,21 +264,24 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ { \ - register long long __v0 asm("$2") ncs_init; \ - register long long __a0 asm("$4") = ARGIFY (arg1); \ - register long long __a1 asm("$5") = ARGIFY (arg2); \ - register long long __a2 asm("$6") = ARGIFY (arg3); \ - register long long __a3 asm("$7") = ARGIFY (arg4); \ - register long long __a4 asm("$8") = ARGIFY (arg5); \ - register long long __a5 asm("$9") = ARGIFY (arg6); \ + register long long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long long __v0 asm ("$2"); \ + register long long __a0 asm ("$4") = ARGIFY (arg1); \ + register long long __a1 asm ("$5") = ARGIFY (arg2); \ + register long long __a2 asm ("$6") = ARGIFY (arg3); \ + register long long __a3 asm ("$7") = ARGIFY (arg4); \ + register long long __a4 asm ("$8") = ARGIFY (arg5); \ + register long long __a5 asm ("$9") = ARGIFY (arg6); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/ioctl.S b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/ioctl.S index b3bed4663c..c5f1c350ed 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/ioctl.S +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/ioctl.S @@ -31,9 +31,9 @@ ENTRY (__ioctl) ret L(error): - SETUP_GP64 (a0, __ioctl) + SETUP_GP64_REG (a0, __ioctl) PTR_LA t9, __syscall_error - RESTORE_GP64 + RESTORE_GP64_REG jr t9 PSEUDO_END (__ioctl) diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist index 22b3068d8f..c7e46aa869 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/nptl/libc.abilist @@ -1396,6 +1396,9 @@ GLIBC_2.17 clock_nanosleep F clock_settime F secure_getenv F +GLIBC_2.18 + GLIBC_2.18 A + __cxa_thread_atexit_impl F GLIBC_2.2 GLIBC_2.2 A _Exit F diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h index 9d949955be..d16ed6941c 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h @@ -67,25 +67,57 @@ #undef INTERNAL_SYSCALL_ERRNO #define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val) +/* Note that the original Linux syscall restart convention required the + instruction immediately preceding SYSCALL to initialize $v0 with the + syscall number. Then if a restart triggered, $v0 would have been + clobbered by the syscall interrupted, and needed to be reinititalized. + The kernel would decrement the PC by 4 before switching back to the + user mode so that $v0 had been reloaded before SYSCALL was executed + again. This implied the place $v0 was loaded from must have been + preserved across a syscall, e.g. an immediate, static register, stack + slot, etc. + + The convention was relaxed in Linux with a change applied to the kernel + GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that + first appeared in the 2.6.36 release. Since then the kernel has had + code that reloads $v0 upon syscall restart and resumes right at the + SYSCALL instruction, so no special arrangement is needed anymore. + + For backwards compatibility with existing kernel binaries we support + the old convention by choosing the instruction preceding SYSCALL + carefully. This also means we have to force a 32-bit encoding of the + microMIPS MOVE instruction if one is used. */ + +#ifdef __mips_micromips +# define MOVE32 "move32" +#else +# define MOVE32 "move" +#endif + #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ - internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ - "i" (SYS_ify (name)), err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ + "IK" (SYS_ify (name)), \ + 0, err, args) #undef INTERNAL_SYSCALL_NCS -#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ - internal_syscall##nr (= number, , "r" (__v0), err, args) +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ + "r" (__s0), \ + number, err, args) -#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +#define internal_syscall0(v0_init, input, number, err, dummy...) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a3 asm("$7"); \ + register long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm ("$2"); \ + register long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -97,17 +129,19 @@ _sys_result; \ }) -#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +#define internal_syscall1(v0_init, input, number, err, arg1) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a0 asm("$4") = (long) (arg1); \ - register long __a3 asm("$7"); \ + register long __s0 asm ("$16") __attribute__ ((unused)) \ + = (number); \ + register long __v0 asm ("$2"); \ + register long __a0 asm ("$4") = (long) (arg1); \ + register long __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set reorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -119,18 +153,20 @@ _sys_result; \ }) -#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - register long __a0 asm("$4") = (long) (arg1); \ - register long __a1 asm("$5") = (long) (arg2); \ - register long __a3 asm("$7"); \ + 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 __a3 asm ("$7"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -142,19 +178,22 @@ _sys_result; \ }) -#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3) \ +#define internal_syscall3(v0_init, input, number, err, \ + arg1, arg2, arg3) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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"); \ + 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"); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ @@ -166,19 +205,22 @@ _sys_result; \ }) -#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4) \ +#define internal_syscall4(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ + 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" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -190,20 +232,23 @@ _sys_result; \ }) -#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +#define internal_syscall5(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ - register long __a4 asm("$8") = (long) (arg5); \ + 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); \ + register long __a4 asm ("$8") = (long) (arg5); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ @@ -215,21 +260,24 @@ _sys_result; \ }) -#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +#define internal_syscall6(v0_init, input, number, err, \ + arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2") ncs_init; \ - 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); \ - register long __a4 asm("$8") = (long) (arg5); \ - register long __a5 asm("$9") = (long) (arg6); \ + 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); \ + register long __a4 asm ("$8") = (long) (arg5); \ + register long __a5 asm ("$9") = (long) (arg6); \ __asm__ volatile ( \ ".set\tnoreorder\n\t" \ - cs_init \ + v0_init \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "+r" (__a3) \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h index 354eba2f3d..6565225662 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/nptl/sysdep-cancel.h @@ -57,6 +57,7 @@ cfi_same_value (gp); \ RESTORESTK; \ ret; \ + cfi_endproc; \ .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ ENTRY (name) \ SAVESTK; \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c index 9b183f335c..197f7eb809 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/shmctl.c @@ -20,14 +20,12 @@ #include <ipc_priv.h> #include <sysdep.h> -#include <bp-checks.h> - int __shmctl (int shmid, int cmd, struct shmid_ds *buf); int __shmctl (int shmid, int cmd, struct shmid_ds *buf) { - return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); + return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, buf); } #include <shlib-compat.h> diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/syscall.S b/ports/sysdeps/unix/sysv/linux/mips/mips64/syscall.S index 839276d7ad..850025c635 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/syscall.S +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/syscall.S @@ -30,7 +30,9 @@ NESTED (syscall, SZREG, ra) .mask 0x00010000, -SZREG .fmask 0x00000000, 0 PTR_ADDIU sp, -SZREG + cfi_adjust_cfa_offset (SZREG) REG_S s0, (sp) + cfi_rel_offset (s0, 0) move s0, a0 move a0, a1 /* shift arg1 - arg7. */ @@ -45,15 +47,17 @@ NESTED (syscall, SZREG, ra) syscall /* Do the system call. */ REG_L s0, (sp) + cfi_restore (s0) PTR_ADDIU sp, SZREG + cfi_adjust_cfa_offset (-SZREG) bne a3, zero, L(error) ret L(error): - SETUP_GP64 (a0, syscall) + SETUP_GP64_REG (a0, syscall) PTR_LA t9, __syscall_error - RESTORE_GP64 + RESTORE_GP64_REG jr t9 END (syscall) diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/xstat64.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/xstat64.c index 2408e5e374..89cde2b33a 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/mips64/xstat64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/xstat64.c @@ -23,7 +23,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <xstatconv.h> @@ -35,7 +34,7 @@ __xstat64 (int vers, const char *name, struct stat64 *buf) int result; struct kernel_stat kbuf; - result = INLINE_SYSCALL (stat, 2, CHECK_STRING (name), __ptrvalue (&kbuf)); + result = INLINE_SYSCALL (stat, 2, name, &kbuf); if (result == 0) result = __xstat64_conv (vers, &kbuf, buf); diff --git a/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h b/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h index fe7c747cde..4f27b8b827 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h +++ b/ports/sysdeps/unix/sysv/linux/mips/nptl/lowlevellock.h @@ -36,6 +36,8 @@ #define FUTEX_TRYLOCK_PI 8 #define FUTEX_WAIT_BITSET 9 #define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 #define FUTEX_PRIVATE_FLAG 128 #define FUTEX_CLOCK_REALTIME 256 @@ -141,6 +143,34 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) +/* Priority Inheritance support. */ +#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \ + lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private) + +#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \ + mutex, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 5, (futexp), \ + __lll_private_flag (__op, private), \ + (val), (timespec), mutex); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + static inline int __attribute__((always_inline)) __lll_trylock(int *futex) { diff --git a/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h b/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h index e1dd672528..3b0eccc77f 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h +++ b/ports/sysdeps/unix/sysv/linux/mips/nptl/sysdep-cancel.h @@ -39,6 +39,7 @@ # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .align 2; \ + .set nomips16; \ L(pseudo_start): \ cfi_startproc; \ 99: PSEUDO_ERRJMP \ @@ -52,6 +53,7 @@ .set reorder; \ bne a3, zero, 99b; \ ret; \ + cfi_endproc; \ .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ ENTRY (name) \ .set noreorder; \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/pread.c b/ports/sysdeps/unix/sysv/linux/mips/pread.c index b269e1c25a..db18265e3d 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/pread.c +++ b/ports/sysdeps/unix/sysv/linux/mips/pread.c @@ -26,7 +26,6 @@ #include <sysdep-cancel.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <kernel-features.h> @@ -54,10 +53,9 @@ __libc_pread (fd, buf, count, offset) if (SINGLE_THREAD_P) { #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, - offset); + result = INLINE_SYSCALL (pread, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pread, 6, fd, buf, count, 0, __LONG_LONG_PAIR (offset >> 31, offset)); #endif return result; @@ -66,9 +64,9 @@ __libc_pread (fd, buf, count, offset) int oldtype = LIBC_CANCEL_ASYNC (); #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, offset); + result = INLINE_SYSCALL (pread, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pread, 6, fd, buf, count, 0, __LONG_LONG_PAIR (offset >> 31, offset)); #endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/pread64.c b/ports/sysdeps/unix/sysv/linux/mips/pread64.c index 8c2c403a9d..3b8c8aa720 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/pread64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/pread64.c @@ -25,7 +25,6 @@ #include <sysdep-cancel.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <kernel-features.h> @@ -50,10 +49,9 @@ __libc_pread64 (fd, buf, count, offset) if (SINGLE_THREAD_P) { #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, - offset); + result = INLINE_SYSCALL (pread, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pread, 6, fd, buf, count, 0, __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) (offset & 0xffffffff))); #endif @@ -63,9 +61,9 @@ __libc_pread64 (fd, buf, count, offset) int oldtype = LIBC_CANCEL_ASYNC (); #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pread, 4, fd, CHECK_N (buf, count), count, offset); + result = INLINE_SYSCALL (pread, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pread, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pread, 6, fd, buf, count, 0, __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) (offset & 0xffffffff))); #endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/pwrite.c b/ports/sysdeps/unix/sysv/linux/mips/pwrite.c index aa3501414b..94213bc8ba 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/pwrite.c +++ b/ports/sysdeps/unix/sysv/linux/mips/pwrite.c @@ -26,7 +26,6 @@ #include <sysdep-cancel.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <kernel-features.h> @@ -54,10 +53,9 @@ __libc_pwrite (fd, buf, count, offset) if (SINGLE_THREAD_P) { #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, - offset); + result = INLINE_SYSCALL (pwrite, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pwrite, 6, fd, buf, count, 0, __LONG_LONG_PAIR (offset >> 31, offset)); #endif return result; @@ -66,9 +64,9 @@ __libc_pwrite (fd, buf, count, offset) int oldtype = LIBC_CANCEL_ASYNC (); #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, offset); + result = INLINE_SYSCALL (pwrite, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pwrite, 6, fd, buf, count, 0, __LONG_LONG_PAIR (offset >> 31, offset)); #endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/pwrite64.c b/ports/sysdeps/unix/sysv/linux/mips/pwrite64.c index 1d14e0761a..aa8a4dec35 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/pwrite64.c +++ b/ports/sysdeps/unix/sysv/linux/mips/pwrite64.c @@ -25,7 +25,6 @@ #include <sysdep-cancel.h> #include <sys/syscall.h> -#include <bp-checks.h> #include <kernel-features.h> @@ -49,10 +48,9 @@ __libc_pwrite64 (fd, buf, count, offset) if (SINGLE_THREAD_P) { #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, - offset); + result = INLINE_SYSCALL (pwrite, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pwrite, 6, fd, buf, count, 0, __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) (offset & 0xffffffff))); #endif @@ -63,9 +61,9 @@ __libc_pwrite64 (fd, buf, count, offset) int oldtype = LIBC_CANCEL_ASYNC (); #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64 - result = INLINE_SYSCALL (pwrite, 4, fd, CHECK_N (buf, count), count, offset); + result = INLINE_SYSCALL (pwrite, 4, fd, buf, count, offset); #else - result = INLINE_SYSCALL (pwrite, 6, fd, CHECK_N (buf, count), count, 0, + result = INLINE_SYSCALL (pwrite, 6, fd, buf, count, 0, __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) (offset & 0xffffffff))); #endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/setcontext.S b/ports/sysdeps/unix/sysv/linux/mips/setcontext.S index 42f709d846..2d5aee013b 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/setcontext.S +++ b/ports/sysdeps/unix/sysv/linux/mips/setcontext.S @@ -27,6 +27,7 @@ /* int setcontext (const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 @@ -56,9 +57,10 @@ NESTED (__setcontext, FRAMESZ, ra) #endif PTR_ADDIU sp, -FRAMESZ + cfi_adjust_cfa_offset (FRAMESZ) #ifdef __PIC__ - SETUP_GP64 (GPOFF, __setcontext) + SETUP_GP64_STACK (GPOFF, __setcontext) SAVE_GP (GPOFF) #endif @@ -152,6 +154,7 @@ NESTED (__setcontext, FRAMESZ, ra) and call the signal return syscall as if a signal handler exited normally. */ PTR_ADDIU sp, -((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) + cfi_adjust_cfa_offset ((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) /* Only ucontext is referred to from rt_sigreturn, copy it. */ @@ -175,11 +178,13 @@ NESTED (__setcontext, FRAMESZ, ra) path. Successful rt_sigreturn never returns to its calling place. */ PTR_ADDIU sp, ((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) + cfi_adjust_cfa_offset (-((RT_SIGFRAME_SIZE + ALSZ) & ALMASK)) 99: #ifdef __PIC__ PTR_LA t9, JUMPTARGET (__syscall_error) - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDIU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) jr t9 #else /* ! __PIC__ */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/sigaction.c b/ports/sysdeps/unix/sysv/linux/mips/sigaction.c index c490dd144e..9d8ee76d02 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/sigaction.c +++ b/ports/sysdeps/unix/sysv/linux/mips/sigaction.c @@ -71,8 +71,8 @@ __libc_sigaction (sig, act, oact) /* XXX The size argument hopefully will have to be changed to the real size of the user-level sigset_t. */ result = INLINE_SYSCALL (rt_sigaction, 4, sig, - act ? __ptrvalue (&kact) : NULL, - oact ? __ptrvalue (&koact) : NULL, + act ? &kact : NULL, + oact ? &koact : NULL, sizeof (kernel_sigset_t)); if (oact && result >= 0) diff --git a/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S b/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S index d965f3919b..ec271b0584 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S +++ b/ports/sysdeps/unix/sysv/linux/mips/swapcontext.S @@ -27,6 +27,7 @@ /* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ .text + .set nomips16 LOCALSZ = 0 ARGSZ = 0 MASK = 0x00000000 @@ -63,7 +64,8 @@ NESTED (__swapcontext, FRAMESZ, ra) # endif PTR_ADDIU sp, -FRAMESZ - SETUP_GP64 (GPOFF, __swapcontext) + cfi_adjust_cfa_offset (FRAMESZ) + SETUP_GP64_STACK (GPOFF, __swapcontext) SAVE_GP (GPOFF) #else /* ! __PIC__ */ @@ -198,8 +200,9 @@ NESTED (__swapcontext, FRAMESZ, ra) 99: #ifdef __PIC__ PTR_LA t9, JUMPTARGET (__syscall_error) - RESTORE_GP64 + RESTORE_GP64_STACK PTR_ADDIU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) jr t9 #else /* ! __PIC__ */ diff --git a/ports/sysdeps/unix/sysv/linux/mips/ustat.c b/ports/sysdeps/unix/sysv/linux/mips/ustat.c index f05bba6294..6db482e96b 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/ustat.c +++ b/ports/sysdeps/unix/sysv/linux/mips/ustat.c @@ -22,7 +22,6 @@ #include <sysdep.h> #include <sys/syscall.h> -#include <bp-checks.h> int ustat (dev_t dev, struct ustat *ubuf) @@ -32,5 +31,5 @@ ustat (dev_t dev, struct ustat *ubuf) /* We must convert the value to dev_t type used by the kernel. */ k_dev = ((major (dev) & 0xff) << 8) | (minor (dev) & 0xff); - return INLINE_SYSCALL (ustat, 2, k_dev, CHECK_1 (ubuf)); + return INLINE_SYSCALL (ustat, 2, k_dev, ubuf); } diff --git a/ports/sysdeps/unix/sysv/linux/mips/vfork.S b/ports/sysdeps/unix/sysv/linux/mips/vfork.S index b9503c3943..ae76a91d38 100644 --- a/ports/sysdeps/unix/sysv/linux/mips/vfork.S +++ b/ports/sysdeps/unix/sysv/linux/mips/vfork.S @@ -34,6 +34,7 @@ /* int vfork() */ .text + .set nomips16 LOCALSZ= 1 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK GPOFF= FRAMESZ-(1*SZREG) @@ -42,7 +43,8 @@ NESTED(__vfork,FRAMESZ,sp) SETUP_GP #endif PTR_SUBU sp, FRAMESZ - SETUP_GP64 (a5, __vfork) + cfi_adjust_cfa_offset (FRAMESZ) + SETUP_GP64_REG (a5, __vfork) #ifdef __PIC__ SAVE_GP (GPOFF) #endif @@ -63,6 +65,7 @@ NESTED(__vfork,FRAMESZ,sp) #endif PTR_ADDU sp, FRAMESZ + cfi_adjust_cfa_offset (-FRAMESZ) SAVE_PID @@ -75,20 +78,22 @@ NESTED(__vfork,FRAMESZ,sp) RESTORE_PID + cfi_remember_state bnez a3,L(error) /* Successful return from the parent or child. */ - RESTORE_GP64 + RESTORE_GP64_REG ret /* Something bad happened -- no child created. */ L(error): + cfi_restore_state #ifdef __PIC__ PTR_LA t9, __syscall_error - RESTORE_GP64 + RESTORE_GP64_REG jr t9 #else - RESTORE_GP64 + RESTORE_GP64_REG j __syscall_error #endif END(__vfork) |