Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: System calls handling

This patch adds support for system calls coming from 64-bit
applications. It uses the asm-generic/unistd.h definitions with the
canonical set of system calls. The private system calls are only used
for 32-bit (compat) applications as 64-bit ones can set the TLS and
flush the caches entirely from user space.

The sys_call_table is just an array defined in a C file and it contains
pointers to the syscall functions. The array is 4KB aligned to allow the
use of the ADRP instruction (longer range ADR) in entry.S.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

+290
+62
arch/arm64/include/asm/stat.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #ifndef __ASM_STAT_H 17 + #define __ASM_STAT_H 18 + 19 + #include <asm-generic/stat.h> 20 + 21 + #if defined(__KERNEL__) && defined(CONFIG_COMPAT) 22 + 23 + #include <asm/compat.h> 24 + 25 + /* 26 + * struct stat64 is needed for compat tasks only. Its definition is different 27 + * from the generic struct stat64. 28 + */ 29 + struct stat64 { 30 + compat_u64 st_dev; 31 + unsigned char __pad0[4]; 32 + 33 + #define STAT64_HAS_BROKEN_ST_INO 1 34 + compat_ulong_t __st_ino; 35 + compat_uint_t st_mode; 36 + compat_uint_t st_nlink; 37 + 38 + compat_ulong_t st_uid; 39 + compat_ulong_t st_gid; 40 + 41 + compat_u64 st_rdev; 42 + unsigned char __pad3[4]; 43 + 44 + compat_s64 st_size; 45 + compat_ulong_t st_blksize; 46 + compat_u64 st_blocks; /* Number of 512-byte blocks allocated. */ 47 + 48 + compat_ulong_t st_atime; 49 + compat_ulong_t st_atime_nsec; 50 + 51 + compat_ulong_t st_mtime; 52 + compat_ulong_t st_mtime_nsec; 53 + 54 + compat_ulong_t st_ctime; 55 + compat_ulong_t st_ctime_nsec; 56 + 57 + compat_u64 st_ino; 58 + }; 59 + 60 + #endif 61 + 62 + #endif
+23
arch/arm64/include/asm/statfs.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #ifndef __ASM_STATFS_H 17 + #define __ASM_STATFS_H 18 + 19 + #define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) 20 + 21 + #include <asm-generic/statfs.h> 22 + 23 + #endif
+40
arch/arm64/include/asm/syscalls.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #ifndef __ASM_SYSCALLS_H 17 + #define __ASM_SYSCALLS_H 18 + 19 + #include <linux/linkage.h> 20 + #include <linux/compiler.h> 21 + #include <linux/signal.h> 22 + 23 + /* 24 + * System call wrappers implemented in kernel/entry.S. 25 + */ 26 + asmlinkage long sys_execve_wrapper(const char __user *filename, 27 + const char __user *const __user *argv, 28 + const char __user *const __user *envp); 29 + asmlinkage long sys_clone_wrapper(unsigned long clone_flags, 30 + unsigned long newsp, 31 + void __user *parent_tid, 32 + unsigned long tls_val, 33 + void __user *child_tid); 34 + asmlinkage long sys_rt_sigreturn_wrapper(void); 35 + asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, 36 + stack_t __user *uoss); 37 + 38 + #include <asm-generic/syscalls.h> 39 + 40 + #endif /* __ASM_SYSCALLS_H */
+27
arch/arm64/include/asm/unistd.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #if !defined(__ASM_UNISTD_H) || defined(__SYSCALL) 17 + #define __ASM_UNISTD_H 18 + 19 + #ifndef __SYSCALL_COMPAT 20 + #include <asm-generic/unistd.h> 21 + #endif 22 + 23 + #if defined(__KERNEL__) && defined(CONFIG_COMPAT) 24 + #include <asm/unistd32.h> 25 + #endif 26 + 27 + #endif /* __ASM_UNISTD_H */
+138
arch/arm64/kernel/sys.c
··· 1 + /* 2 + * AArch64-specific system calls implementation 3 + * 4 + * Copyright (C) 2012 ARM Ltd. 5 + * Author: Catalin Marinas <catalin.marinas@arm.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include <linux/compiler.h> 21 + #include <linux/errno.h> 22 + #include <linux/fs.h> 23 + #include <linux/mm.h> 24 + #include <linux/export.h> 25 + #include <linux/sched.h> 26 + #include <linux/slab.h> 27 + #include <linux/syscalls.h> 28 + 29 + /* 30 + * Clone a task - this clones the calling program thread. 31 + */ 32 + asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, 33 + int __user *parent_tidptr, unsigned long tls_val, 34 + int __user *child_tidptr, struct pt_regs *regs) 35 + { 36 + if (!newsp) 37 + newsp = regs->sp; 38 + /* 16-byte aligned stack mandatory on AArch64 */ 39 + if (newsp & 15) 40 + return -EINVAL; 41 + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 42 + } 43 + 44 + /* 45 + * sys_execve() executes a new program. 46 + */ 47 + asmlinkage long sys_execve(const char __user *filenamei, 48 + const char __user *const __user *argv, 49 + const char __user *const __user *envp, 50 + struct pt_regs *regs) 51 + { 52 + long error; 53 + char * filename; 54 + 55 + filename = getname(filenamei); 56 + error = PTR_ERR(filename); 57 + if (IS_ERR(filename)) 58 + goto out; 59 + error = do_execve(filename, argv, envp, regs); 60 + putname(filename); 61 + out: 62 + return error; 63 + } 64 + 65 + int kernel_execve(const char *filename, 66 + const char *const argv[], 67 + const char *const envp[]) 68 + { 69 + struct pt_regs regs; 70 + int ret; 71 + 72 + memset(&regs, 0, sizeof(struct pt_regs)); 73 + ret = do_execve(filename, 74 + (const char __user *const __user *)argv, 75 + (const char __user *const __user *)envp, &regs); 76 + if (ret < 0) 77 + goto out; 78 + 79 + /* 80 + * Save argc to the register structure for userspace. 81 + */ 82 + regs.regs[0] = ret; 83 + 84 + /* 85 + * We were successful. We won't be returning to our caller, but 86 + * instead to user space by manipulating the kernel stack. 87 + */ 88 + asm( "add x0, %0, %1\n\t" 89 + "mov x1, %2\n\t" 90 + "mov x2, %3\n\t" 91 + "bl memmove\n\t" /* copy regs to top of stack */ 92 + "mov x27, #0\n\t" /* not a syscall */ 93 + "mov x28, %0\n\t" /* thread structure */ 94 + "mov sp, x0\n\t" /* reposition stack pointer */ 95 + "b ret_to_user" 96 + : 97 + : "r" (current_thread_info()), 98 + "Ir" (THREAD_START_SP - sizeof(regs)), 99 + "r" (&regs), 100 + "Ir" (sizeof(regs)) 101 + : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); 102 + 103 + out: 104 + return ret; 105 + } 106 + EXPORT_SYMBOL(kernel_execve); 107 + 108 + asmlinkage long sys_mmap(unsigned long addr, unsigned long len, 109 + unsigned long prot, unsigned long flags, 110 + unsigned long fd, off_t off) 111 + { 112 + if (offset_in_page(off) != 0) 113 + return -EINVAL; 114 + 115 + return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); 116 + } 117 + 118 + /* 119 + * Wrappers to pass the pt_regs argument. 120 + */ 121 + #define sys_execve sys_execve_wrapper 122 + #define sys_clone sys_clone_wrapper 123 + #define sys_rt_sigreturn sys_rt_sigreturn_wrapper 124 + #define sys_sigaltstack sys_sigaltstack_wrapper 125 + 126 + #include <asm/syscalls.h> 127 + 128 + #undef __SYSCALL 129 + #define __SYSCALL(nr, sym) [nr] = sym, 130 + 131 + /* 132 + * The sys_call_table array must be 4K aligned to be accessible from 133 + * kernel/entry.S. 134 + */ 135 + void *sys_call_table[__NR_syscalls] __aligned(4096) = { 136 + [0 ... __NR_syscalls - 1] = sys_ni_syscall, 137 + #include <asm/unistd.h> 138 + };