about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-04-06 17:01:56 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-04-12 11:04:28 -0300
commit158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d (patch)
tree4314d7eeee6694b56c5c12153686f6a58d5ab890 /sysdeps
parent4fee33f8c11447d345b2b1118a98958b54d5fda3 (diff)
downloadglibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.tar.gz
glibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.tar.xz
glibc-158d5fa0e1906e7810bdc6ecb7bf598dcc3cd17d.zip
Consolidate Linux mmap implementation (BZ#21270)
This patch consolidates all Linux mmap implementations on default
sysdeps/unix/sysv/linux/mmap{64}.c one.  To accomodate all required
architecture specific requeriments a new internal header is created
(mmap_internal.h) where each architecture add its specific code
requirements.  Currently only x86_64 (to define MMAP_PREPARE to add
MAP_32BITS), s390 (which have a different kernel ABI for mmap), m68k
(which have variable minimum page sizes), and MIPS n32 (which zero
extend the offset to handle negative one correctly) redefine the new
header.

The patch also fixes BZ#21270 where default mmap64 on architectures
which uses mmap2 silent truncates large offsets value (larger than
1 << (page shift + 8 * sizeof (off_t)) or 1<<44 on architectures with
4096 bytes page size).  The new consolidate implementation returns
EINVAL as allowed by POSIX.

It also adds a tests for on current tst-mmap-offset one.  I have run
a full make check on x86_64, x86_64-32, i686, aarch64, armhf, powerpc,
powerpc64le, sparc64, and sparcv9 without any regressions.  I also ran
some basic tests (tst-mmap-offset) on sh4, m68k, and on qemu simulated
MIPS32 and MIPS64.

	[BZ #21270]
	* posix/tst-mmap-offset.c (do_prepare): New function.
	(do_test): Rename to do_test_bz18877 and use FAIL_RET.
	(do_test_bz21270): New function.
	* sysdeps/unix/sysv/linux/aarch64/mmap.c: Remove file.
	* sysdeps/unix/sysv/linux/arm/mmap.c: Remove file.
	* sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/hppa/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/m68k/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/m68k/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/mmap64.c: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/mmap.c: Likewise.
	* sysdeps/unix/sysv/linux/mmap_internal.h: New file.
	* sysdeps/unix/sysv/linux/m68k/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list: Remove mmap
	from auto-generation list.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: Likewise.
	* sysdeps/unix/sysv/linux/mmap.c: New file.
	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64): Add check for invalid
	offsets and support for mmap2 syscall.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/mmap.c34
-rw-r--r--sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c40
-rw-r--r--sysdeps/unix/sysv/linux/hppa/mmap.c49
-rw-r--r--sysdeps/unix/sysv/linux/m68k/mmap.S42
-rw-r--r--sysdeps/unix/sysv/linux/m68k/mmap64.c5
-rw-r--r--sysdeps/unix/sysv/linux/m68k/mmap_internal.h (renamed from sysdeps/unix/sysv/linux/arm/mmap.c)15
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/mmap.S50
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/mmap.c1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h (renamed from sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c)25
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list2
-rw-r--r--sysdeps/unix/sysv/linux/mmap.c51
-rw-r--r--sysdeps/unix/sysv/linux/mmap64.c57
-rw-r--r--sysdeps/unix/sysv/linux/mmap_internal.h49
-rw-r--r--sysdeps/unix/sysv/linux/s390/mmap_internal.h (renamed from sysdeps/unix/sysv/linux/i386/mmap.c)30
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/mmap.S74
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S81
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/mmap.S78
-rw-r--r--sysdeps/unix/sysv/linux/wordsize-64/mmap.c40
-rw-r--r--sysdeps/unix/sysv/linux/wordsize-64/mmap64.c1
-rw-r--r--sysdeps/unix/sysv/linux/wordsize-64/syscalls.list1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h (renamed from sysdeps/unix/sysv/linux/x86_64/64/mmap.c)9
23 files changed, 172 insertions, 565 deletions
diff --git a/sysdeps/unix/sysv/linux/aarch64/mmap.c b/sysdeps/unix/sysv/linux/aarch64/mmap.c
deleted file mode 100644
index 1dd18f97a2..0000000000
--- a/sysdeps/unix/sysv/linux/aarch64/mmap.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2009-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 <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sys/syscall.h>
-#include <sysdep.h>
-#include <unistd.h>
-
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-  return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd, offset);
-}
-
-weak_alias (__mmap, mmap)
-weak_alias (__mmap, mmap64)
-weak_alias (__mmap, __mmap64)
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c
deleted file mode 100644
index ebeb79b543..0000000000
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 2011-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
-
-   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 <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sysdep.h>
-
-#ifndef MMAP_PAGE_UNIT
-# define MMAP_PAGE_UNIT 4096UL
-#endif
-
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-  if (offset & (MMAP_PAGE_UNIT - 1))
-    {
-      __set_errno (EINVAL);
-      return MAP_FAILED;
-    }
-  return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
-                                   offset / MMAP_PAGE_UNIT);
-}
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/hppa/mmap.c b/sysdeps/unix/sysv/linux/hppa/mmap.c
deleted file mode 100644
index 72957cd22c..0000000000
--- a/sysdeps/unix/sysv/linux/hppa/mmap.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (C) 1994-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 <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-
-/* Map addresses starting near ADDR and extending for LEN bytes.  From
-   OFFSET into the file FD describes according to PROT and FLAGS.  If ADDR
-   is nonzero, it is the desired mapping address.  If the MAP_FIXED bit is
-   set in FLAGS, the mapping will be at ADDR exactly (which must be
-   page-aligned); otherwise the system chooses a convenient nearby address.
-   The return value is the actual mapping address chosen or MAP_FAILED
-   for errors (in which case `errno' is set).  A successful `mmap' call
-   deallocates any previous mapping for the affected region.  */
-
-#include <sysdep.h>
-
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-
-	__ptr_t ret;
-
-	ret = (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd, offset);
-
-	/* check if it's really a negative number */
-	if(((unsigned long)ret & 0xfffff000) == 0xfffff000)
-		return MAP_FAILED;
-
-	return ret;
-
-}
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/m68k/mmap.S b/sysdeps/unix/sysv/linux/m68k/mmap.S
deleted file mode 100644
index eb8e0716b8..0000000000
--- a/sysdeps/unix/sysv/linux/m68k/mmap.S
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (C) 1996-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>
-
-	.text
-ENTRY (__mmap)
-
-	move.l #SYS_ify (mmap), %d0	/* System call number in %d0.  */
-
-	lea 4(%sp), %a0			/* Address of args is 1st arg.  */
-	move.l %a0, %d1
-
-	/* Do the system call trap.  */
-	trap #0
-
-	/* Kludge: negative numbers are among the legal return values.
-	   If %d0 is between -4096 and 0 then there was an error.  */
-	cmp.l #-4096, %d0
-	jhi SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  Copy it to %a0 because
-	   mmap is declared to return a pointer.  */
-	move.l %d0, %a0
-	rts
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/m68k/mmap64.c b/sysdeps/unix/sysv/linux/m68k/mmap64.c
deleted file mode 100644
index 8bf8987017..0000000000
--- a/sysdeps/unix/sysv/linux/m68k/mmap64.c
+++ /dev/null
@@ -1,5 +0,0 @@
-/* ColdFire and Sun 3 kernels have PAGE_SHIFT set to 13 and expect
-   mmap2 offset to be provided in 8K pages.  Determine the shift
-   dynamically with getpagesize.  */
-#define MMAP2_PAGE_SHIFT -1
-#include <sysdeps/unix/sysv/linux/mmap64.c>
diff --git a/sysdeps/unix/sysv/linux/arm/mmap.c b/sysdeps/unix/sysv/linux/m68k/mmap_internal.h
index 4fe8678ea5..bd8bd3843b 100644
--- a/sysdeps/unix/sysv/linux/arm/mmap.c
+++ b/sysdeps/unix/sysv/linux/m68k/mmap_internal.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+/* Common mmap definition for Linux implementation.  Linux/m68k version.
+   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
@@ -15,4 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c>
+#ifndef MMAP_M68K_INTERNAL_LINUX_H
+#define MMAP_M68K_INTERNAL_LINUX_H
+
+/* ColdFire and Sun 3 kernels have PAGE_SHIFT set to 13 and expect
+   mmap2 offset to be provided in 8K pages.  Determine the shift
+   dynamically with getpagesize.  */
+#define MMAP2_PAGE_SHIFT -1
+
+#include_next <mmap_internal.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/microblaze/mmap.S b/sysdeps/unix/sysv/linux/microblaze/mmap.S
deleted file mode 100644
index 0099993a89..0000000000
--- a/sysdeps/unix/sysv/linux/microblaze/mmap.S
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright (C) 2009-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>
-
-#define EINVAL 22
-	.text
-ENTRY (__mmap)
-	addik	r3,r0,-EINVAL
-	andi	r4,r10,0xfff
-	bnei	r4,L(skip)
-	addik	r12,r0,SYS_ify(mmap2)
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10
-	sra	r10,r10 ;	/* mmap2 takes the offset in pages.  */
-	brki	r14,8
-	nop
-L(skip):
-	addik	r4,r0,-4095
-	cmpu	r4,r4,r3
-	bgei	r4,SYSCALL_ERROR_LABEL
-	rtsd	r15,8
-	nop
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mmap.c b/sysdeps/unix/sysv/linux/mips/mips32/mmap.c
deleted file mode 100644
index f30b1da58e..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips32/mmap.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/unix/sysv/linux/generic/wordsize-32/mmap.c>
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c b/sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h
index ca0a5b1442..4b65559ecb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/mmap.c
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/mmap_internal.h
@@ -1,4 +1,4 @@
-/* mmap for MIPS n32.
+/* Common mmap definition for Linux implementation.  MIPS n32 version.
    Copyright (C) 2016-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,20 +16,13 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <stdint.h>
-#include <sysdep.h>
+#ifndef MMAP_MIPS_N32_INTERNAL_H
+#define MMAP_MIPS_N32_INTERNAL_H
 
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-  /* To handle negative offsets consistently with other architectures,
-     the offset must be zero-extended to 64-bit.  */
-  uint64_t offset_adj = (uint64_t) (uint32_t) offset;
-  return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags, fd,
-				   offset_adj);
-}
+/* To handle negative offsets consistently with other architectures,
+   the offset must be zero-extended to 64-bit.  */
+#define MMAP_ADJUST_OFFSET(offset) (uint64_t) (uint32_t) offset
 
-weak_alias (__mmap, mmap)
+#include_next <mmap_internal.h>
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list b/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list
index 7af317f69c..5f3d04728d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list
@@ -4,8 +4,6 @@
 # return value.
 lseek64		-	lseek		i:iii	__lseek64	__libc_lseek64 lseek64 llseek
 
-mmap64		-	mmap		b:aniiii __mmap64	mmap64
-
 readahead	-	readahead	i:iii	__readahead	readahead
 
 prlimit64	EXTRA	prlimit64	i:iipp	prlimit64
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c
deleted file mode 100644
index 0dbd384a6a..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/mmap64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* mmap64 is the same as mmap. */
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list b/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
index 5b5cfc2655..28664208d0 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/syscalls.list
@@ -1,7 +1,5 @@
 # File name	Caller	Syscall name	# args	Strong name	Weak names
 
-mmap		-	mmap		b:aniiii __mmap		mmap __mmap64 mmap64
-
 readahead	-	readahead	i:iii	__readahead	readahead
 
 prlimit		EXTRA	prlimit64	i:iipp	prlimit		prlimit64
diff --git a/sysdeps/unix/sysv/linux/mmap.c b/sysdeps/unix/sysv/linux/mmap.c
new file mode 100644
index 0000000000..b1f229f19c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mmap.c
@@ -0,0 +1,51 @@
+/* mmap - map files or devices into memory.  Linux version.
+   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 <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sysdep.h>
+#include <stdint.h>
+#include <mmap_internal.h>
+
+#ifndef __OFF_T_MATCHES_OFF64_T
+
+/* An architecture may override this.  */
+# ifndef MMAP_ADJUST_OFFSET
+#  define MMAP_ADJUST_OFFSET(offset) offset
+# endif
+
+void *
+__mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+  MMAP_CHECK_PAGE_UNIT ();
+
+  if (offset & MMAP_OFF_LOW_MASK)
+    return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
+
+#ifdef __NR_mmap2
+  return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
+			     offset / (uint32_t) MMAP2_PAGE_UNIT);
+#else
+  return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd,
+			     MMAP_ADJUST_OFFSET (offset));
+#endif
+}
+weak_alias (__mmap, mmap)
+
+#endif /* __OFF_T_MATCHES_OFF64_T  */
diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c
index e823600a0d..d3ea279afe 100644
--- a/sysdeps/unix/sysv/linux/mmap64.c
+++ b/sysdeps/unix/sysv/linux/mmap64.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999-2017 Free Software Foundation, Inc.
+/* mmap - map files or devices into memory.  Linux version.
+   Copyright (C) 1999-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Jakub Jelinek <jakub@redhat.com>, 1999.
 
@@ -19,39 +20,41 @@
 #include <errno.h>
 #include <unistd.h>
 #include <sys/mman.h>
-#include <string.h>
-
 #include <sysdep.h>
-#include <sys/syscall.h>
+#include <mmap_internal.h>
 
-/* This is always 12, even on architectures where PAGE_SHIFT != 12.  */
-#ifndef MMAP2_PAGE_SHIFT
-# define MMAP2_PAGE_SHIFT 12
-#endif
-#if MMAP2_PAGE_SHIFT == -1
-static int page_shift;
-#else
-#define page_shift MMAP2_PAGE_SHIFT
-#endif
+/* To avoid silent truncation of offset when using mmap2, do not accept
+   offset larger than 1 << (page_shift + off_t bits).  For archictures with
+   32 bits off_t and page size of 4096 it would be 1^44.  */
+#define MMAP_OFF_HIGH_MASK \
+  ((-(MMAP2_PAGE_UNIT << 1) << (8 * sizeof (off_t) - 1)))
 
+#define MMAP_OFF_MASK (MMAP_OFF_HIGH_MASK | MMAP_OFF_LOW_MASK)
+
+/* An architecture may override this.  */
+#ifndef MMAP_PREPARE
+# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
+#endif
 
 void *
 __mmap64 (void *addr, size_t len, int prot, int flags, int fd, off64_t offset)
 {
-#if MMAP2_PAGE_SHIFT == -1
-  if (page_shift == 0)
-    {
-      int page_size = __getpagesize ();
-      page_shift = __ffs (page_size) - 1;
-    }
-#endif
-  if (offset & ((1 << page_shift) - 1))
+  MMAP_CHECK_PAGE_UNIT ();
+
+  if (offset & MMAP_OFF_MASK)
     return (void *) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
-  void *result;
-  result = (void *)
-    INLINE_SYSCALL (mmap2, 6, addr,
-		    len, prot, flags, fd,
-		    (off_t) (offset >> page_shift));
-  return result;
+
+  MMAP_PREPARE (addr, len, prot, flags, fd, offset);
+#ifdef __NR_mmap2
+  return (void *) MMAP_CALL (mmap2, addr, len, prot, flags, fd,
+			     (off_t) (offset / MMAP2_PAGE_UNIT));
+#else
+  return (void *) MMAP_CALL (mmap, addr, len, prot, flags, fd, offset);
+#endif
 }
 weak_alias (__mmap64, mmap64)
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+weak_alias (__mmap64, mmap)
+weak_alias (__mmap64, __mmap)
+#endif
diff --git a/sysdeps/unix/sysv/linux/mmap_internal.h b/sysdeps/unix/sysv/linux/mmap_internal.h
new file mode 100644
index 0000000000..499e389605
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mmap_internal.h
@@ -0,0 +1,49 @@
+/* Common mmap definition for Linux implementation.
+   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/>.  */
+
+#ifndef MMAP_INTERNAL_LINUX_H
+#define MMAP_INTERNAL_LINUX_H 1
+
+/* This is the minimum mmap2 unit size accept by the kernel.  An architecture
+   with multiple minimum page sizes (such as m68k) might define it as -1 and
+   thus it will queried at runtime.  */
+#ifndef MMAP2_PAGE_UNIT
+# define MMAP2_PAGE_UNIT 4096ULL
+#endif
+
+#if MMAP2_PAGE_UNIT == -1
+static int page_unit;
+
+# define MMAP_CHECK_PAGE_UNIT()			\
+  if (page_unit == 0)				\
+    page_unit = __getpagesize ();
+#else
+# define page_unit MMAP2_PAGE_UNIT
+# define MMAP_CHECK_PAGE_UNIT()
+#endif
+
+/* Do not accept offset not multiple of page size.  */
+#define MMAP_OFF_LOW_MASK  (MMAP2_PAGE_UNIT - 1)
+
+/* An architecture may override this.  */
+#ifndef MMAP_CALL
+# define MMAP_CALL(__nr, __addr, __len, __prot, __flags, __fd, __offset) \
+  INLINE_SYSCALL_CALL (__nr, __addr, __len, __prot, __flags, __fd, __offset)
+#endif
+
+#endif /* MMAP_INTERNAL_LINUX_H  */
diff --git a/sysdeps/unix/sysv/linux/i386/mmap.c b/sysdeps/unix/sysv/linux/s390/mmap_internal.h
index abf3a26877..2b11ce4e68 100644
--- a/sysdeps/unix/sysv/linux/i386/mmap.c
+++ b/sysdeps/unix/sysv/linux/s390/mmap_internal.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+/* mmap - map files or devices into memory.  Linux/s390 version.
+   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
@@ -15,22 +16,17 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sysdep.h>
+#ifndef MMAP_S390_INTERNAL_H
+# define MMAP_S390_INTERNAL_H
 
-#ifndef MMAP_PAGE_UNIT
-# define MMAP_PAGE_UNIT 4096UL
-#endif
+#define MMAP_CALL(__nr, __addr, __len, __prot, __flags, __fd, __offset)	\
+  ({									\
+    long int __args[6] = { (long int) (__addr), (long int) (__len),	\
+			   (long int) (__prot), (long int) (__flags),	\
+			   (long int) (__fd), (long int) (__offset) };	\
+    INLINE_SYSCALL_CALL (__nr, __args);					\
+  })
 
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-  if (offset & (MMAP_PAGE_UNIT - 1))
-    return (__ptr_t) INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
-  return (__ptr_t) INLINE_SYSCALL (mmap2, 6, addr, len, prot, flags, fd,
-                                   offset / MMAP_PAGE_UNIT);
-}
+#include_next <mmap_internal.h>
 
-weak_alias (__mmap, mmap)
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/mmap.S b/sysdeps/unix/sysv/linux/s390/s390-32/mmap.S
deleted file mode 100644
index 99b56ed392..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/mmap.S
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
-   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
-   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>
-
-#define EINVAL	22
-
-	.text
-ENTRY(__mmap)
-	/* Save registers and setup stack frame.  */
-	stm     %r6,%r15,24(%r15)
-	cfi_offset (%r15, -36)
-	cfi_offset (%r14, -40)
-	cfi_offset (%r13, -44)
-	cfi_offset (%r12, -48)
-	cfi_offset (%r11, -52)
-	cfi_offset (%r10, -56)
-	cfi_offset (%r9, -60)
-	cfi_offset (%r8, -64)
-	cfi_offset (%r7, -68)
-	cfi_offset (%r6, -72)
-	lr      %r1,%r15
-	ahi     %r15,-120               /* buy stack space */
-	cfi_adjust_cfa_offset (120)
-	st      %r1,0(%r15)             /* store back chain */
-
-	/* Store parameters on stack, because mmap2
-	 * takes only one parameter: a pointer to the parameter area
-	 */
-	st      %r6,0x70(%r15)          /* Store 'fd'.      */
-	st      %r5,0x6C(%r15)          /* Store 'flags'.   */
-	st      %r4,0x68(%r15)          /* Store 'prot'.    */
-	st      %r3,0x64(%r15)          /* Store 'length'.  */
-	st      %r2,0x60(%r15)          /* Store 'start'.   */
-	l       %r1,216(%r15)           /* Load offset.     */
-
-	tml     %r1,0x0fff              /* Offset page aligned ?  */
-	lhi     %r2,-EINVAL
-	jnz     1f                      /* No -> EINVAL.  */
-	srl     %r1,12                  /* mmap2 takes the offset in pages.  */
-	st      %r1,0x74(%r15)          /* Store page offset.  */
-	la      %r2,0x60(%r15)          /* Load address of parameter list.  */
-	svc     SYS_ify(mmap2)          /* Do the system call trap.  */
-
-1:	l       %r15,0(%r15)            /* Load back chain.  */
-	cfi_adjust_cfa_offset (-120)
-	lm      %r6,%r15,24(%r15)       /* Load registers.  */
-
-	/* check gpr 2 for error */
-	lhi     %r0,-4096
-	clr     %r2,%r0
-	jnl     SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-	br      %r14
-
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S b/sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S
deleted file mode 100644
index f1825782a4..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-32/mmap64.S
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
-   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
-   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>
-
-#define EINVAL	22
-#define ENOSYS	38
-
-	.text
-ENTRY(__mmap64)
-	/* Save registers and setup stack frame.  */
-	stm	%r6,%r15,24(%r15)
-	cfi_offset (%r15, -36)
-	cfi_offset (%r14, -40)
-	cfi_offset (%r13, -44)
-	cfi_offset (%r12, -48)
-	cfi_offset (%r11, -52)
-	cfi_offset (%r10, -56)
-	cfi_offset (%r9, -60)
-	cfi_offset (%r8, -64)
-	cfi_offset (%r7, -68)
-	cfi_offset (%r6, -72)
-	lr	%r1,%r15
-	ahi	%r15,-120		/* Buy stack space.   */
-	cfi_adjust_cfa_offset (120)
-	st	%r1,0(%r15)		/* Store back chain.  */
-
-	/* Store parameters on stack, because mmap2
-	 * takes only one parameter: a pointer to the parameter area.  */
-	st	%r6,0x70(%r15)		/* Store 'fd'.	    */
-	st	%r5,0x6C(%r15)		/* Store 'flags'.   */
-	st	%r4,0x68(%r15)		/* Store 'prot'.    */
-	st	%r3,0x64(%r15)		/* Store 'length'.  */
-	st	%r2,0x60(%r15)		/* Store 'start'.   */
-
-	lm	%r0,%r1,216(%r15)	/* Load 64 bit offset.	*/
-	tml	%r1,0x0fff		/* Offset page aligned ?  */
-	jnz	2f			/* No -> EINVAL.  */
-	srdl	%r0,12			/* mmap2 takes the offset in pages.  */
-	ltr	%r0,%r0			/* Offset > 2^44 ?  */
-	jnz	2f
-	st	%r1,0x74(%r15)		/* Store page offset.  */
-
-	la	%r2,0x60(%r15)		/* Load address of parameter list.  */
-	svc	SYS_ify(mmap2)		/* Do the system call trap.  */
-
-	l	%r15,0(%r15)		/* Load back chain.  */
-	cfi_adjust_cfa_offset (-120)
-	lm	%r6,%r15,24(%r15)	/* Load registers.  */
-
-	/* Check gpr 2 for error.  */
-	lhi	%r0,-4096
-	clr	%r2,%r0
-	jnl	SYSCALL_ERROR_LABEL
-
-	/* Successful; return the syscall's value.  */
-	br	%r14
-
-2:	lhi	%r2,-EINVAL
-	l	%r15,0(%r15)		/* Load back chain.  */
-	lm	%r6,%r15,24(%r15)	/* Load registers.  */
-	j	SYSCALL_ERROR_LABEL
-
-PSEUDO_END (__mmap64)
-
-weak_alias (__mmap64, mmap64)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S b/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
deleted file mode 100644
index 06d31bbb92..0000000000
--- a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Wrapper around mmap system call.  64 bit S/390 version.
-   Copyright (C) 2001-2017 Free Software Foundation, Inc.
-   Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
-   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>
-
-#define EINVAL	22
-
-        .text
-
-ENTRY(__mmap)
-	/* Save registers and setup stack frame.  */
-        stmg    %r6,%r15,48(%r15)
-	cfi_offset (%r15,-40)
-	cfi_offset (%r14,-48)
-	cfi_offset (%r13,-56)
-	cfi_offset (%r12,-64)
-	cfi_offset (%r11,-72)
-	cfi_offset (%r10,-80)
-	cfi_offset (%r9,-88)
-	cfi_offset (%r8,-96)
-	cfi_offset (%r7,-104)
-	cfi_offset (%r6,-112)
-        lgr     %r1,%r15
-        lg      %r0,8(%r15)             /* Load eos.  */
-        aghi    %r15,-208               /* Buy stack space.  */
-	cfi_adjust_cfa_offset (208)
-        stg     %r1,0(%r15)             /* Store back chain.  */
-        stg     %r0,8(%r15)             /* Store eos.  */
-
-        /* Store parameters on stack, because old_mmap
-           takes only one parameter: a pointer to the parameter area.  */
-        mvc     200(8,%r15),368(%r15)   /* Move 'offset'.  */
-        lgfr    %r6,%r6
-        stg     %r6,192(%r15)           /* Store 'fd'.  */
-        lgfr    %r5,%r5
-        stg     %r5,184(%r15)           /* Store 'flags'.  */
-        lgfr    %r4,%r4
-        stg     %r4,176(%r15)           /* Store 'prot'.  */
-        stg     %r3,168(%r15)           /* Store 'length'.  */
-        stg     %r2,160(%r15)           /* Store 'start'.  */
-
-        la      %r2,160(%r15)           /* Load address of parameter list.  */
-        /* Do the system call trap.  */
-        svc     SYS_ify(mmap)
-
-        lg      %r15,0(%r15)            /* Load back chain.  */
-	cfi_adjust_cfa_offset (-208)
-        lmg     %r6,%r15,48(%r15)       /* Load registers.  */
-
-        /* Check gpr 2 for error.  */
-        lghi    %r0,-4096
-        clgr    %r2,%r0
-        jgnl    SYSCALL_ERROR_LABEL
-
-        /* Successful; return the syscall's value.  */
-        br      %r14
-
-PSEUDO_END (__mmap)
-
-weak_alias (__mmap, mmap)
-weak_alias (__mmap, mmap64)
-weak_alias (__mmap, __mmap64)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/mmap.c b/sysdeps/unix/sysv/linux/wordsize-64/mmap.c
deleted file mode 100644
index a784b62b4d..0000000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/mmap.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Linux mmap system call.  64-bit version.
-   Copyright (C) 2015-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 <sys/types.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <sysdep.h>
-
-/* An architecture may override this.  */
-#ifndef MMAP_PREPARE
-# define MMAP_PREPARE(addr, len, prot, flags, fd, offset)
-#endif
-
-__ptr_t
-__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-  MMAP_PREPARE (addr, len, prot, flags, fd, offset);
-  return (__ptr_t) INLINE_SYSCALL (mmap, 6, addr, len, prot, flags,
-				   fd, offset);
-}
-
-weak_alias (__mmap, mmap)
-weak_alias (__mmap, mmap64)
-weak_alias (__mmap, __mmap64)
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/mmap64.c b/sysdeps/unix/sysv/linux/wordsize-64/mmap64.c
deleted file mode 100644
index 0dbd384a6a..0000000000
--- a/sysdeps/unix/sysv/linux/wordsize-64/mmap64.c
+++ /dev/null
@@ -1 +0,0 @@
-/* mmap64 is the same as mmap. */
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list b/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list
index e71cd7b156..0c606477da 100644
--- a/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list
+++ b/sysdeps/unix/sysv/linux/wordsize-64/syscalls.list
@@ -2,7 +2,6 @@
 
 fstatfs		-	fstatfs		i:ip	__fstatfs	fstatfs fstatfs64 __fstatfs64
 statfs		-	statfs		i:sp	__statfs	statfs statfs64
-mmap		-	mmap		b:aniiii __mmap		mmap __mmap64 mmap64
 readahead	-	readahead	i:iii	__readahead	readahead
 sendfile	-	sendfile	i:iipi	sendfile	sendfile64
 sync_file_range	-	sync_file_range	Ci:iiii	sync_file_range
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap.c b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
index 9091b09ac8..06254efb94 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/mmap.c
+++ b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
@@ -17,6 +17,9 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifndef MMAP_X86_64_INTERNAL_H
+#define MMAP_X86_64_INTERNAL_H
+
 #include <ldsodefs.h>
 
 /* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable pages
@@ -26,7 +29,7 @@
       && ((prot) & PROT_EXEC) != 0					\
       && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC))			\
     {									\
-      __ptr_t ret = (__ptr_t) INLINE_SYSCALL (mmap, 6, (addr), (len),	\
+      void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len),	\
 					      (prot),			\
 					      (flags) | MAP_32BIT,	\
 					      (fd), (offset));		\
@@ -34,4 +37,6 @@
 	return ret;							\
     }
 
-#include <sysdeps/unix/sysv/linux/wordsize-64/mmap.c>
+#include_next <mmap_internal.h>
+
+#endif