mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
f08cae2f28
The file offset argument to the arm64 sys_mmap() implementation is scaled from bytes to pages by shifting right by PAGE_SHIFT. Unfortunately, the offset is passed in as a signed 'off_t' type and therefore large offsets (i.e. with the top bit set) are incorrectly sign-extended by the shift. This has been observed to cause false mmap() failures when mapping GPU doorbells on an arm64 server part. Change the type of the file offset argument to sys_mmap() from 'off_t' to 'unsigned long' so that the shifting scales the value as expected. Cc: <stable@vger.kernel.org> Signed-off-by: Boyang Zhou <zhouby_cn@126.com> [will: rewrote commit message] Signed-off-by: Will Deacon <will.deacon@arm.com>
69 lines
2.0 KiB
C
69 lines
2.0 KiB
C
/*
|
|
* AArch64-specific system calls implementation
|
|
*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
* Author: Catalin Marinas <catalin.marinas@arm.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <linux/compiler.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/export.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/syscalls.h>
|
|
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/syscall.h>
|
|
|
|
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
|
|
unsigned long, prot, unsigned long, flags,
|
|
unsigned long, fd, unsigned long, off)
|
|
{
|
|
if (offset_in_page(off) != 0)
|
|
return -EINVAL;
|
|
|
|
return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
|
|
}
|
|
|
|
SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
|
|
{
|
|
if (personality(personality) == PER_LINUX32 &&
|
|
!system_supports_32bit_el0())
|
|
return -EINVAL;
|
|
return ksys_personality(personality);
|
|
}
|
|
|
|
/*
|
|
* Wrappers to pass the pt_regs argument.
|
|
*/
|
|
#define sys_personality sys_arm64_personality
|
|
|
|
asmlinkage long sys_ni_syscall(const struct pt_regs *);
|
|
#define __arm64_sys_ni_syscall sys_ni_syscall
|
|
|
|
#undef __SYSCALL
|
|
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
|
|
#include <asm/unistd.h>
|
|
|
|
#undef __SYSCALL
|
|
#define __SYSCALL(nr, sym) [nr] = (syscall_fn_t)__arm64_##sym,
|
|
|
|
const syscall_fn_t sys_call_table[__NR_syscalls] = {
|
|
[0 ... __NR_syscalls - 1] = (syscall_fn_t)sys_ni_syscall,
|
|
#include <asm/unistd.h>
|
|
};
|