1 /* 2 * Based on arch/arm/kernel/sys_arm.c 3 * 4 * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c 5 * Copyright (C) 1995, 1996 Russell King. 6 * Copyright (C) 2012 ARM Ltd. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <linux/compat.h> 22 #include <linux/personality.h> 23 #include <linux/sched.h> 24 #include <linux/slab.h> 25 #include <linux/syscalls.h> 26 #include <linux/uaccess.h> 27 28 #include <asm/cacheflush.h> 29 #include <asm/unistd.h> 30 31 static long 32 __do_compat_cache_op(unsigned long start, unsigned long end) 33 { 34 long ret; 35 36 do { 37 unsigned long chunk = min(PAGE_SIZE, end - start); 38 39 if (fatal_signal_pending(current)) 40 return 0; 41 42 ret = __flush_cache_user_range(start, start + chunk); 43 if (ret) 44 return ret; 45 46 cond_resched(); 47 start += chunk; 48 } while (start < end); 49 50 return 0; 51 } 52 53 static inline long 54 do_compat_cache_op(unsigned long start, unsigned long end, int flags) 55 { 56 if (end < start || flags) 57 return -EINVAL; 58 59 if (!access_ok(VERIFY_READ, start, end - start)) 60 return -EFAULT; 61 62 return __do_compat_cache_op(start, end); 63 } 64 /* 65 * Handle all unrecognised system calls. 66 */ 67 long compat_arm_syscall(struct pt_regs *regs) 68 { 69 unsigned int no = regs->regs[7]; 70 71 switch (no) { 72 /* 73 * Flush a region from virtual address 'r0' to virtual address 'r1' 74 * _exclusive_. There is no alignment requirement on either address; 75 * user space does not need to know the hardware cache layout. 76 * 77 * r2 contains flags. It should ALWAYS be passed as ZERO until it 78 * is defined to be something else. For now we ignore it, but may 79 * the fires of hell burn in your belly if you break this rule. ;) 80 * 81 * (at a later date, we may want to allow this call to not flush 82 * various aspects of the cache. Passing '0' will guarantee that 83 * everything necessary gets flushed to maintain consistency in 84 * the specified region). 85 */ 86 case __ARM_NR_compat_cacheflush: 87 return do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]); 88 89 case __ARM_NR_compat_set_tls: 90 current->thread.tp_value = regs->regs[0]; 91 92 /* 93 * Protect against register corruption from context switch. 94 * See comment in tls_thread_flush. 95 */ 96 barrier(); 97 asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0])); 98 return 0; 99 100 default: 101 return -ENOSYS; 102 } 103 } 104