2019-06-03 08:44:50 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-03-05 15:49:31 +04:00
/*
* AArch64 - specific system calls implementation
*
* Copyright ( C ) 2012 ARM Ltd .
* Author : Catalin Marinas < catalin . marinas @ arm . com >
*/
# 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>
2018-07-11 16:56:42 +03:00
2016-04-18 12:28:37 +03:00
# include <asm/cpufeature.h>
2018-07-11 16:56:42 +03:00
# include <asm/syscall.h>
2012-03-05 15:49:31 +04:00
2018-07-11 16:56:54 +03:00
SYSCALL_DEFINE6 ( mmap , unsigned long , addr , unsigned long , len ,
unsigned long , prot , unsigned long , flags ,
2019-04-29 17:27:19 +03:00
unsigned long , fd , unsigned long , off )
2012-03-05 15:49:31 +04:00
{
if ( offset_in_page ( off ) ! = 0 )
return - EINVAL ;
2018-03-11 13:34:46 +03:00
return ksys_mmap_pgoff ( addr , len , prot , flags , fd , off > > PAGE_SHIFT ) ;
2012-03-05 15:49:31 +04:00
}
2016-04-18 12:28:37 +03:00
SYSCALL_DEFINE1 ( arm64_personality , unsigned int , personality )
{
if ( personality ( personality ) = = PER_LINUX32 & &
! system_supports_32bit_el0 ( ) )
return - EINVAL ;
2018-07-11 16:56:52 +03:00
return ksys_personality ( personality ) ;
2016-04-18 12:28:37 +03:00
}
2019-05-25 01:11:18 +03:00
asmlinkage long sys_ni_syscall ( void ) ;
asmlinkage long __arm64_sys_ni_syscall ( const struct pt_regs * __unused )
{
return sys_ni_syscall ( ) ;
}
2012-03-05 15:49:31 +04:00
/*
* Wrappers to pass the pt_regs argument .
*/
2019-05-28 14:39:34 +03:00
# define __arm64_sys_personality __arm64_sys_arm64_personality
2012-03-05 15:49:31 +04:00
arm64: implement syscall wrappers
To minimize the risk of userspace-controlled values being used under
speculation, this patch adds pt_regs based syscall wrappers for arm64,
which pass the minimum set of required userspace values to syscall
implementations. For each syscall, a wrapper which takes a pt_regs
argument is automatically generated, and this extracts the arguments
before calling the "real" syscall implementation.
Each syscall has three functions generated:
* __do_<compat_>sys_<name> is the "real" syscall implementation, with
the expected prototype.
* __se_<compat_>sys_<name> is the sign-extension/narrowing wrapper,
inherited from common code. This takes a series of long parameters,
casting each to the requisite types required by the "real" syscall
implementation in __do_<compat_>sys_<name>.
This wrapper *may* not be necessary on arm64 given the AAPCS rules on
unused register bits, but it seemed safer to keep the wrapper for now.
* __arm64_<compat_>_sys_<name> takes a struct pt_regs pointer, and
extracts *only* the relevant register values, passing these on to the
__se_<compat_>sys_<name> wrapper.
The syscall invocation code is updated to handle the calling convention
required by __arm64_<compat_>_sys_<name>, and passes a single struct
pt_regs pointer.
The compiler can fold the syscall implementation and its wrappers, such
that the overhead of this approach is minimized.
Note that we play games with sys_ni_syscall(). It can't be defined with
SYSCALL_DEFINE0() because we must avoid the possibility of error
injection. Additionally, there are a couple of locations where we need
to call it from C code, and we don't (currently) have a
ksys_ni_syscall(). While it has no wrapper, passing in a redundant
pt_regs pointer is benign per the AAPCS.
When ARCH_HAS_SYSCALL_WRAPPER is selected, no prototype is defines for
sys_ni_syscall(). Since we need to treat it differently for in-kernel
calls and the syscall tables, the prototype is defined as-required.
The wrappers are largely the same as their x86 counterparts, but
simplified as we don't have a variety of compat calling conventions that
require separate stubs. Unlike x86, we have some zero-argument compat
syscalls, and must define COMPAT_SYSCALL_DEFINE0() to ensure that these
are also given an __arm64_compat_sys_ prefix.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
2018-07-11 16:56:56 +03:00
# undef __SYSCALL
# define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
# include <asm/unistd.h>
2012-03-05 15:49:31 +04:00
# undef __SYSCALL
2019-05-25 01:11:18 +03:00
# define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
2012-03-05 15:49:31 +04:00
2018-07-11 16:56:49 +03:00
const syscall_fn_t sys_call_table [ __NR_syscalls ] = {
2019-05-25 01:11:18 +03:00
[ 0 . . . __NR_syscalls - 1 ] = __arm64_sys_ni_syscall ,
2012-03-05 15:49:31 +04:00
# include <asm/unistd.h>
} ;