Re: [PATCH v12 06/28] riscv/mm : ensure PROT_WRITE leads to VM_READ | VM_WRITE

Arnd Bergmann
2025-04-24T12:43:42Z

On Thu, Apr 24, 2025, at 14:23, Radim Krčmář wrote:
> 2025-04-23T17:45:53-07:00, Deepak Gupta <debug@rivosinc.com>:
>> On Thu, Apr 10, 2025 at 12:03:44PM +0200, Radim Krčmář wrote:
>>>2025-03-14T14:39:25-07:00, Deepak Gupta <debug@rivosinc.com>:
>>>Why isn't the previous hunk be enough? (Or why don't we do just this?)
>>>
>>>riscv_sys_mmap() eventually calls arch_calc_vm_prot_bits(), so I'd
>>>rather fix each code path just once.
>>
>> You're right. Above hunk (arch/riscv/include/asm/mman.h) alone should be enough.
>> I did this change in `sys_riscv.c` out of caution. If it feels like un-necessary,
>> I'll remove it. No hard feelings either way.
>
> I think it makes the code harder to reason about. Here it is not clear
> why this caller of ksys_mmap_pgoff() has to do this, while others don't.

Right, I've been meaning to clean this up for years: there should
really not be anything architecture specific in the sys_mmap() or
sys_mmap2() syscalls, but we never managed to have a global definition
for those and instead leave them up to the architectures and over
the years they have diverged.

See below for my earlier prototype of this.

Arnd

From 42efb4468e119f34361f039d0779b8cd00d73de8 Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Wed, 22 Dec 2021 15:06:58 +0100
Subject: [PATCH] treewide: replace mmap_pgoff() with mmap2()

32-bit architectures generally implement sys_mmap2() as their primary
mmap() implementation, but common code only provides sys_mmap_pgoff(),
which has slightly different behavior when dealing with page sizes
other than 4096 bytes.

On m68k, arc and hexagon, the use of mmap_pgoff() appears to be
irreversible, as they do support multiple page sizes and user space
now relies on passing the argument in actual pages rather than
fixed-size units. m68k also has a misleading comment about SUN3
that needs to be rewritten to reflect that this is not broken but
required by libc now.

powerpc and riscv are additional exceptions here, as they have
checks for the 'prot' argument that need to be kept in place.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arc/include/asm/syscalls.h | 4 ++++
arch/arm/include/asm/ftrace.h | 4 +---
arch/arm/kernel/entry-common.S | 9 ---------
arch/arm/mm/mmap.c | 9 +++++++++
arch/arm64/kernel/sys32.c | 16 ----------------
arch/arm64/tools/syscall_32.tbl | 2 +-
arch/csky/kernel/syscall.c | 15 ---------------
arch/hexagon/kernel/syscalltab.c | 11 +++++++++--
arch/m68k/include/asm/syscalls.h | 3 +++
arch/m68k/kernel/sys_m68k.c | 11 +++++------
arch/m68k/kernel/syscalltable.S | 2 --
arch/microblaze/kernel/sys_microblaze.c | 11 -----------
arch/mips/kernel/syscall.c | 11 -----------
arch/mips/kernel/syscalls/syscall_o32.tbl | 2 +-
arch/nios2/kernel/syscall_table.c | 2 --
arch/parisc/kernel/sys_parisc.c | 10 ----------
arch/powerpc/include/asm/syscalls.h | 7 ++-----
arch/powerpc/kernel/syscalls.c | 17 +++++------------
arch/powerpc/kernel/syscalls/syscall.tbl | 4 ++--
arch/riscv/include/asm/syscall.h | 8 ++++++++
arch/riscv/kernel/sys_riscv.c | 5 +++--
arch/riscv/kernel/syscall_table.c | 3 +++
arch/sh/include/asm/syscalls.h | 3 ---
arch/sh/kernel/sys_sh.c | 16 ----------------
arch/sparc/kernel/sys_sparc_32.c | 12 ------------
arch/x86/entry/syscalls/syscall_32.tbl | 2 +-
arch/xtensa/kernel/syscalls/syscall.tbl | 2 +-
include/linux/syscalls.h | 2 +-
mm/mmap.c | 11 ++++++++---
mm/nommu.c | 11 ++++++++---

diff --git a/arch/arc/include/asm/syscalls.h b/arch/arc/include/asm/syscalls.h
index c3f4714a4f5c..91e2d3fac623 100644
--- a/arch/arc/include/asm/syscalls.h
+++ b/arch/arc/include/asm/syscalls.h
@@ -17,6 +17,10 @@ int sys_arc_settls(void *);
int sys_arc_gettls(void);
int sys_arc_usr_cmpxchg(int *, int, int);

+asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+
#include <asm-generic/syscalls.h>

#endif
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 5be3ddc96a50..3b2d84ec11f3 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -62,9 +62,7 @@ static inline void *return_address(unsigned int level)
static inline bool arch_syscall_match_sym_name(const char *sym,
const char *name)
{
- if (!strcmp(sym, "sys_mmap2"))
- sym = "sys_mmap_pgoff";
- else if (!strcmp(sym, "sys_statfs64_wrapper"))
+ if (!strcmp(sym, "sys_statfs64_wrapper"))
sym = "sys_statfs64";
else if (!strcmp(sym, "sys_fstatfs64_wrapper"))
sym = "sys_fstatfs64";
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index f379c852dcb7..d7657d210c61 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -406,15 +406,6 @@ sys_fstatfs64_wrapper:
b sys_fstatfs64
ENDPROC(sys_fstatfs64_wrapper)

-/*
- * Note: off_4k (r5) is always units of 4K. If we can't do the requested
- * offset, we return EINVAL.
- */
-sys_mmap2:
- str r5, [sp, #4]
- b sys_mmap_pgoff
-ENDPROC(sys_mmap2)
-
#ifdef CONFIG_OABI_COMPAT

/*
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 3dbb383c26d5..8d7fb2df1349 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/personality.h>
#include <linux/random.h>
+#include <linux/syscalls.h>
#include <asm/cachetype.h>

#define COLOUR_ALIGN(addr,pgoff) \
@@ -165,3 +166,11 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
}
+
+/* arc glibc passes PAGE_SIZE units rather than the usual 4K */
+SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+ long, prot, unsigned long, flags,
+ long, fd, unsigned long, pgoff)
+{
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+}
diff --git a/arch/arm64/kernel/sys32.c b/arch/arm64/kernel/sys32.c
index 0e3aa4d762a3..8709521ef7bf 100644
--- a/arch/arm64/kernel/sys32.c
+++ b/arch/arm64/kernel/sys32.c
@@ -43,22 +43,6 @@ COMPAT_SYSCALL_DEFINE3(aarch32_fstatfs64, unsigned int, fd, compat_size_t, sz,
return kcompat_sys_fstatfs64(fd, sz, buf);
}

-/*
- * Note: off_4k is always in units of 4K. If we can't do the
- * requested offset because it is not page-aligned, we return -EINVAL.
- */
-COMPAT_SYSCALL_DEFINE6(aarch32_mmap2, unsigned long, addr, unsigned long, len,
- unsigned long, prot, unsigned long, flags,
- unsigned long, fd, unsigned long, off_4k)
-{
- if (off_4k & (~PAGE_MASK >> 12))
- return -EINVAL;
-
- off_4k >>= (PAGE_SHIFT - 12);
-
- return ksys_mmap_pgoff(addr, len, prot, flags, fd, off_4k);
-}
-
#ifdef CONFIG_CPU_BIG_ENDIAN
#define arg_u32p(name) u32, name##_hi, u32, name##_lo
#else
diff --git a/arch/arm64/tools/syscall_32.tbl b/arch/arm64/tools/syscall_32.tbl
index 0765b3a8d6d6..893a33b94c74 100644
--- a/arch/arm64/tools/syscall_32.tbl
+++ b/arch/arm64/tools/syscall_32.tbl
@@ -204,7 +204,7 @@
190 common vfork sys_vfork
# SuS compliant getrlimit
191 common ugetrlimit sys_getrlimit compat_sys_getrlimit
-192 common mmap2 sys_mmap2 compat_sys_aarch32_mmap2
+192 common mmap2 sys_mmap2
193 common truncate64 sys_truncate64 compat_sys_aarch32_truncate64
194 common ftruncate64 sys_ftruncate64 compat_sys_aarch32_ftruncate64
195 common stat64 sys_stat64
diff --git a/arch/csky/kernel/syscall.c b/arch/csky/kernel/syscall.c
index 4540a271ee39..ecde99520fd1 100644
--- a/arch/csky/kernel/syscall.c
+++ b/arch/csky/kernel/syscall.c
@@ -14,21 +14,6 @@ SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
return 0;
}

-SYSCALL_DEFINE6(mmap2,
- unsigned long, addr,
- unsigned long, len,
- unsigned long, prot,
- unsigned long, flags,
- unsigned long, fd,
- unsigned long, offset)
-{
- if (unlikely(offset & (~PAGE_MASK >> 12)))
- return -EINVAL;
-
- return ksys_mmap_pgoff(addr, len, prot, flags, fd,
- offset >> (PAGE_SHIFT - 12));
-}
-
/*
* for abiv1 the 64bits args should be even th, So we need mov the advice
* forward.
diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c
index b53e2eead4ac..595ab60c9d7b 100644
--- a/arch/hexagon/kernel/syscalltab.c
+++ b/arch/hexagon/kernel/syscalltab.c
@@ -14,8 +14,6 @@
#define __SYSCALL(nr, call) [nr] = (call),
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)

-#define sys_mmap2 sys_mmap_pgoff
-
SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,
SC_ARG64(offset), SC_ARG64(len))
{
@@ -25,6 +23,15 @@ SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,

#define sys_sync_file_range sys_sync_file_range2

+/* hexagon libc passes PAGE_SIZE units rather than the usual 4K */
+#define sys_mmap2 sys_mmap_pgoff
+SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+ long, prot, unsigned long, flags,
+ long, fd, unsigned long, pgoff)
+{
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+}
+
void *sys_call_table[__NR_syscalls] = {
#include <asm/syscall_table_32.h>
};
diff --git a/arch/m68k/include/asm/syscalls.h b/arch/m68k/include/asm/syscalls.h
index fb3639acd07b..70c5f01d8036 100644
--- a/arch/m68k/include/asm/syscalls.h
+++ b/arch/m68k/include/asm/syscalls.h
@@ -5,6 +5,9 @@
#include <linux/compiler_types.h>
#include <linux/linkage.h>

+asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
asmlinkage int sys_cacheflush(unsigned long addr, int scope, int cache,
unsigned long len);
asmlinkage int sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3,
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 1af5e6082467..87a251d05554 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -37,15 +37,14 @@

#include "../mm/fault.h"

-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+/*
+ * m68k user space expects to pass units of PAGE_SIZE rather than 4KB,
+ * so provide a custom wrapper around ksys_mmap_pgoff()
+ */
+asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
- /*
- * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
- * so we need to shift the argument down by 1; m68k mmap64(3)
- * (in libc) expects the last argument of mmap2 in 4Kb units.
- */
return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
}

diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index e25ef4a9df30..d7b8f4840eb4 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -14,9 +14,7 @@

#include <linux/linkage.h>

-#ifndef CONFIG_MMU
#define sys_mmap2 sys_mmap_pgoff
-#endif

#define __SYSCALL(nr, entry) .long entry
.section .rodata
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index 0850b099f300..7fde269b5ef3 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -42,14 +42,3 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,

return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
}
-
-SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
- unsigned long, prot, unsigned long, flags, unsigned long, fd,
- unsigned long, pgoff)
-{
- if (pgoff & (~PAGE_MASK >> 12))
- return -EINVAL;
-
- return ksys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT - 12));
-}
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 1bfc34a2e5b3..f050b7cd6dc0 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -69,17 +69,6 @@ SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
offset >> PAGE_SHIFT);
}

-SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
- unsigned long, prot, unsigned long, flags, unsigned long, fd,
- unsigned long, pgoff)
-{
- if (pgoff & (~PAGE_MASK >> 12))
- return -EINVAL;
-
- return ksys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT - 12));
-}
-
save_static_function(sys_fork);
save_static_function(sys_clone);
save_static_function(sys_clone3);
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 114a5a1a6230..961379b9ef7b 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -221,7 +221,7 @@
207 o32 sendfile sys_sendfile compat_sys_sendfile
208 o32 getpmsg sys_ni_syscall
209 o32 putpmsg sys_ni_syscall
-210 o32 mmap2 sys_mips_mmap2
+210 o32 mmap2 sys_mmap2
211 o32 truncate64 sys_truncate64 sys_32_truncate64
212 o32 ftruncate64 sys_ftruncate64 sys_32_ftruncate64
213 o32 stat64 sys_stat64 sys_newstat
diff --git a/arch/nios2/kernel/syscall_table.c b/arch/nios2/kernel/syscall_table.c
index 434694067d8f..88ecde1b96f3 100644
--- a/arch/nios2/kernel/syscall_table.c
+++ b/arch/nios2/kernel/syscall_table.c
@@ -12,8 +12,6 @@
#define __SYSCALL(nr, call) [nr] = (call),
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)

-#define sys_mmap2 sys_mmap_pgoff
-
void *sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls-1] = sys_ni_syscall,
#include <asm/syscall_table_32.h>
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index f852fe274abe..c56d4d3dff32 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -182,16 +182,6 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
addr, len, pgoff, flags, DOWN);
}

-asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags, unsigned long fd,
- unsigned long pgoff)
-{
- /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
- we have. */
- return ksys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT - 12));
-}
-
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd,
unsigned long offset)
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
index 6d51b007b59e..711785d630c2 100644
--- a/arch/powerpc/include/asm/syscalls.h
+++ b/arch/powerpc/include/asm/syscalls.h
@@ -52,10 +52,10 @@ long compat_sys_ppc64_personality(unsigned long personality);

long sys_swapcontext(struct ucontext __user *old_ctx,
struct ucontext __user *new_ctx, long ctx_size);
-long sys_mmap(unsigned long addr, size_t len,
+long sys_ppc_mmap(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, off_t offset);
-long sys_mmap2(unsigned long addr, size_t len,
+long sys_ppc32_mmap2(unsigned long addr, size_t len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
long sys_switch_endian(void);
@@ -113,9 +113,6 @@ long sys_ppc_fallocate(int fd, int mode, u32 offset1, u32 offset2,
u32 len1, u32 len2);
#endif
#ifdef CONFIG_COMPAT
-long compat_sys_mmap2(unsigned long addr, size_t len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff);
long compat_sys_ppc_pread64(unsigned int fd,
char __user *ubuf, compat_size_t count,
u32 reg6, u32 pos1, u32 pos2);
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index 68ebb23a5af4..003ad44eaa5f 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -49,24 +49,17 @@ static long do_mmap2(unsigned long addr, size_t len,
return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> shift);
}

-SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len,
+/*
+ * like the normal mmap2(), but checks the prot argument
+ */
+SYSCALL_DEFINE6(ppc32_mmap2, unsigned long, addr, size_t, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, unsigned long, pgoff)
{
return do_mmap2(addr, len, prot, flags, fd, pgoff, PAGE_SHIFT-12);
}

-#ifdef CONFIG_COMPAT
-COMPAT_SYSCALL_DEFINE6(mmap2,
- unsigned long, addr, size_t, len,
- unsigned long, prot, unsigned long, flags,
- unsigned long, fd, unsigned long, off_4k)
-{
- return do_mmap2(addr, len, prot, flags, fd, off_4k, PAGE_SHIFT-12);
-}
-#endif
-
-SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len,
+SYSCALL_DEFINE6(ppc_mmap, unsigned long, addr, size_t, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, off_t, offset)
{
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index 9a084bdb8926..b7d83806d48f 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -124,7 +124,7 @@
89 32 readdir sys_old_readdir compat_sys_old_readdir
89 64 readdir sys_ni_syscall
89 spu readdir sys_ni_syscall
-90 common mmap sys_mmap
+90 common mmap sys_ppc_mmap
91 common munmap sys_munmap
92 common truncate sys_truncate compat_sys_truncate
93 common ftruncate sys_ftruncate compat_sys_ftruncate
@@ -249,7 +249,7 @@
191 32 readahead sys_ppc_readahead compat_sys_ppc_readahead
191 64 readahead sys_readahead
191 spu readahead sys_readahead
-192 32 mmap2 sys_mmap2 compat_sys_mmap2
+192 32 mmap2 sys_mmap2
193 32 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64
194 32 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64
195 32 stat64 sys_stat64
diff --git a/arch/riscv/include/asm/syscall.h b/arch/riscv/include/asm/syscall.h
index 34313387f977..20cbf0c63e20 100644
--- a/arch/riscv/include/asm/syscall.h
+++ b/arch/riscv/include/asm/syscall.h
@@ -121,4 +121,12 @@ asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);

asmlinkage long sys_riscv_hwprobe(struct riscv_hwprobe *, size_t, size_t,
unsigned long *, unsigned int);
+
+asmlinkage long sys_riscv_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+asmlinkage long sys_riscv_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t pgoff);
+
#endif /* _ASM_RISCV_SYSCALL_H */
diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c
index d77afe05578f..8e8c32241db6 100644
--- a/arch/riscv/kernel/sys_riscv.c
+++ b/arch/riscv/kernel/sys_riscv.c
@@ -20,8 +20,9 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len,
offset >> (PAGE_SHIFT - page_shift_offset));
}

+/* same as the generic version, but checks the prot argument */
#ifdef CONFIG_64BIT
-SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
+SYSCALL_DEFINE6(riscv_mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, unsigned long, offset)
{
@@ -30,7 +31,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
#endif

#if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
-SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+SYSCALL_DEFINE6(riscv_mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
unsigned long, fd, unsigned long, offset)
{
diff --git a/arch/riscv/kernel/syscall_table.c b/arch/riscv/kernel/syscall_table.c
index 43363a80d722..def8e888d262 100644
--- a/arch/riscv/kernel/syscall_table.c
+++ b/arch/riscv/kernel/syscall_table.c
@@ -15,6 +15,9 @@
#define __SYSCALL(nr, call) asmlinkage long __riscv_##call(const struct pt_regs *);
#include <asm/syscall_table.h>

+#define __riscv_sys_mmap __riscv_sys_riscv_mmap
+#define __riscv_sys_mmap2 __riscv_sys_riscv_mmap2
+
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = __riscv_##call,

diff --git a/arch/sh/include/asm/syscalls.h b/arch/sh/include/asm/syscalls.h
index 39240e06e8aa..d54c69633acc 100644
--- a/arch/sh/include/asm/syscalls.h
+++ b/arch/sh/include/asm/syscalls.h
@@ -5,9 +5,6 @@
asmlinkage int old_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
int fd, unsigned long off);
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff);
asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op);

#include <asm/syscalls_32.h>
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index a5a7b33ed81a..45abd5e1246e 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -38,22 +38,6 @@ asmlinkage int old_mmap(unsigned long addr, unsigned long len,
return ksys_mmap_pgoff(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
}

-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
-{
- /*
- * The shift for mmap2 is constant, regardless of PAGE_SIZE
- * setting.
- */
- if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
- return -EINVAL;
-
- pgoff >>= PAGE_SHIFT - 12;
-
- return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
-}
-
/* sys_cacheflush -- flush (part of) the processor cache. */
asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
{
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index fb31bc0c5b48..2331ba5bad8b 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -104,18 +104,6 @@ int sparc_mmap_check(unsigned long addr, unsigned long len)
return 0;
}

-/* Linux version of mmap */
-
-SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
- unsigned long, prot, unsigned long, flags, unsigned long, fd,
- unsigned long, pgoff)
-{
- /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
- we have. */
- return ksys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT - 12));
-}
-
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags, unsigned long, fd,
unsigned long, off)
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index ac007ea00979..e11dba577071 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -204,7 +204,7 @@
189 i386 putpmsg
190 i386 vfork sys_vfork
191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit
-192 i386 mmap2 sys_mmap_pgoff
+192 i386 mmap2 sys_mmap2
193 i386 truncate64 sys_ia32_truncate64
194 i386 ftruncate64 sys_ia32_ftruncate64
195 i386 stat64 sys_stat64 compat_sys_ia32_stat64
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index f657a77314f8..e13e73fab37c 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -89,7 +89,7 @@
78 common flistxattr sys_flistxattr
79 common fremovexattr sys_fremovexattr
# File Map / Shared Memory Operations
-80 common mmap2 sys_mmap_pgoff
+80 common mmap2 sys_mmap2
81 common munmap sys_munmap
82 common mprotect sys_mprotect
83 common brk sys_brk
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e5603cc91963..0df21f8f6e24 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -1198,7 +1198,7 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
unsigned long third, void __user *ptr, long fifth);

/* obsolete */
-asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
diff --git a/mm/mmap.c b/mm/mmap.c
index bd210aaf7ebd..73ba0e5cae07 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -611,11 +611,16 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
return retval;
}

-SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
- unsigned long, fd, unsigned long, pgoff)
+ unsigned long, fd, unsigned long, off_4k)
{
- return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ if (off_4k & (~PAGE_MASK >> 12))
+ return -EINVAL;
+
+ off_4k >>= (PAGE_SHIFT - 12);
+
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, off_4k);
}

#ifdef __ARCH_WANT_SYS_OLD_MMAP
diff --git a/mm/nommu.c b/mm/nommu.c
index 76c3096206fa..86cca5b21e87 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1247,11 +1247,16 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
return retval;
}

-SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
- unsigned long, fd, unsigned long, pgoff)
+ unsigned long, fd, unsigned long, off_4k)
{
- return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+ if (off_4k & (~PAGE_MASK >> 12))
+ return -EINVAL;
+
+ off_4k >>= (PAGE_SHIFT - 12);
+
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd, off_4k);
}

#ifdef __ARCH_WANT_SYS_OLD_MMAP
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index 9a084bdb8926..ddfeff063a6d 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -124,7 +124,7 @@
89 32 readdir sys_old_readdir compat_sys_old_readdir
89 64 readdir sys_ni_syscall
89 spu readdir sys_ni_syscall
-90 common mmap sys_mmap
+90 common mmap sys_ppc_mmap
91 common munmap sys_munmap
92 common truncate sys_truncate compat_sys_truncate
93 common ftruncate sys_ftruncate compat_sys_ftruncate
@@ -249,7 +249,7 @@
191 32 readahead sys_ppc_readahead compat_sys_ppc_readahead
191 64 readahead sys_readahead
191 spu readahead sys_readahead
-192 32 mmap2 sys_mmap2 compat_sys_mmap2
+192 32 mmap2 sys_ppc32_mmap2
193 32 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64
194 32 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64
195 32 stat64 sys_stat64