1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2a88b5ba8SSam Ravnborg /* linux/arch/sparc64/kernel/sys_sparc.c 3a88b5ba8SSam Ravnborg * 4a88b5ba8SSam Ravnborg * This file contains various random system calls that 5a88b5ba8SSam Ravnborg * have a non-standard calling sequence on the Linux/sparc 6a88b5ba8SSam Ravnborg * platform. 7a88b5ba8SSam Ravnborg */ 8a88b5ba8SSam Ravnborg 9a88b5ba8SSam Ravnborg #include <linux/errno.h> 10a88b5ba8SSam Ravnborg #include <linux/types.h> 113f07c014SIngo Molnar #include <linux/sched/signal.h> 1201042607SIngo Molnar #include <linux/sched/mm.h> 13b17b0153SIngo Molnar #include <linux/sched/debug.h> 14a88b5ba8SSam Ravnborg #include <linux/fs.h> 15a88b5ba8SSam Ravnborg #include <linux/file.h> 16a88b5ba8SSam Ravnborg #include <linux/mm.h> 17a88b5ba8SSam Ravnborg #include <linux/sem.h> 18a88b5ba8SSam Ravnborg #include <linux/msg.h> 19a88b5ba8SSam Ravnborg #include <linux/shm.h> 20a88b5ba8SSam Ravnborg #include <linux/stat.h> 21a88b5ba8SSam Ravnborg #include <linux/mman.h> 22a88b5ba8SSam Ravnborg #include <linux/utsname.h> 23a88b5ba8SSam Ravnborg #include <linux/smp.h> 24a88b5ba8SSam Ravnborg #include <linux/slab.h> 25a88b5ba8SSam Ravnborg #include <linux/syscalls.h> 26a88b5ba8SSam Ravnborg #include <linux/ipc.h> 27a88b5ba8SSam Ravnborg #include <linux/personality.h> 28a88b5ba8SSam Ravnborg #include <linux/random.h> 29066bcacaSPaul Gortmaker #include <linux/export.h> 30812cb83aSKirill Tkhai #include <linux/context_tracking.h> 311a596398SArnd Bergmann #include <linux/timex.h> 327c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 331a596398SArnd Bergmann 34a88b5ba8SSam Ravnborg #include <asm/utrap.h> 35a88b5ba8SSam Ravnborg #include <asm/unistd.h> 36a88b5ba8SSam Ravnborg 37a88b5ba8SSam Ravnborg #include "entry.h" 388df52620SSam Ravnborg #include "kernel.h" 39a88b5ba8SSam Ravnborg #include "systbls.h" 40a88b5ba8SSam Ravnborg 41a88b5ba8SSam Ravnborg /* #define DEBUG_UNIMP_SYSCALL */ 42a88b5ba8SSam Ravnborg 43ee076e81SAl Viro SYSCALL_DEFINE0(getpagesize) 44a88b5ba8SSam Ravnborg { 45a88b5ba8SSam Ravnborg return PAGE_SIZE; 46a88b5ba8SSam Ravnborg } 47a88b5ba8SSam Ravnborg 48a88b5ba8SSam Ravnborg /* Does addr --> addr+len fall within 4GB of the VA-space hole or 49a88b5ba8SSam Ravnborg * overflow past the end of the 64-bit address space? 50a88b5ba8SSam Ravnborg */ 51a88b5ba8SSam Ravnborg static inline int invalid_64bit_range(unsigned long addr, unsigned long len) 52a88b5ba8SSam Ravnborg { 53a88b5ba8SSam Ravnborg unsigned long va_exclude_start, va_exclude_end; 54a88b5ba8SSam Ravnborg 55a88b5ba8SSam Ravnborg va_exclude_start = VA_EXCLUDE_START; 56a88b5ba8SSam Ravnborg va_exclude_end = VA_EXCLUDE_END; 57a88b5ba8SSam Ravnborg 58a88b5ba8SSam Ravnborg if (unlikely(len >= va_exclude_start)) 59a88b5ba8SSam Ravnborg return 1; 60a88b5ba8SSam Ravnborg 61a88b5ba8SSam Ravnborg if (unlikely((addr + len) < addr)) 62a88b5ba8SSam Ravnborg return 1; 63a88b5ba8SSam Ravnborg 64a88b5ba8SSam Ravnborg if (unlikely((addr >= va_exclude_start && addr < va_exclude_end) || 65a88b5ba8SSam Ravnborg ((addr + len) >= va_exclude_start && 66a88b5ba8SSam Ravnborg (addr + len) < va_exclude_end))) 67a88b5ba8SSam Ravnborg return 1; 68a88b5ba8SSam Ravnborg 69a88b5ba8SSam Ravnborg return 0; 70a88b5ba8SSam Ravnborg } 71a88b5ba8SSam Ravnborg 72a88b5ba8SSam Ravnborg /* These functions differ from the default implementations in 73a88b5ba8SSam Ravnborg * mm/mmap.c in two ways: 74a88b5ba8SSam Ravnborg * 75a88b5ba8SSam Ravnborg * 1) For file backed MAP_SHARED mmap()'s we D-cache color align, 76a88b5ba8SSam Ravnborg * for fixed such mappings we just validate what the user gave us. 77a88b5ba8SSam Ravnborg * 2) For 64-bit tasks we avoid mapping anything within 4GB of 78a88b5ba8SSam Ravnborg * the spitfire/niagara VA-hole. 79a88b5ba8SSam Ravnborg */ 80a88b5ba8SSam Ravnborg 81748ba883SAndrew Morton static inline unsigned long COLOR_ALIGN(unsigned long addr, 82a88b5ba8SSam Ravnborg unsigned long pgoff) 83a88b5ba8SSam Ravnborg { 84a88b5ba8SSam Ravnborg unsigned long base = (addr+SHMLBA-1)&~(SHMLBA-1); 85a88b5ba8SSam Ravnborg unsigned long off = (pgoff<<PAGE_SHIFT) & (SHMLBA-1); 86a88b5ba8SSam Ravnborg 87a88b5ba8SSam Ravnborg return base + off; 88a88b5ba8SSam Ravnborg } 89a88b5ba8SSam Ravnborg 90a88b5ba8SSam Ravnborg unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) 91a88b5ba8SSam Ravnborg { 92a88b5ba8SSam Ravnborg struct mm_struct *mm = current->mm; 93a88b5ba8SSam Ravnborg struct vm_area_struct * vma; 94a88b5ba8SSam Ravnborg unsigned long task_size = TASK_SIZE; 95a88b5ba8SSam Ravnborg int do_color_align; 96*b80fa3cbSRick Edgecombe struct vm_unmapped_area_info info = {}; 97a88b5ba8SSam Ravnborg 98a88b5ba8SSam Ravnborg if (flags & MAP_FIXED) { 99a88b5ba8SSam Ravnborg /* We do not accept a shared mapping if it would violate 100a88b5ba8SSam Ravnborg * cache aliasing constraints. 101a88b5ba8SSam Ravnborg */ 102a88b5ba8SSam Ravnborg if ((flags & MAP_SHARED) && 103a88b5ba8SSam Ravnborg ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) 104a88b5ba8SSam Ravnborg return -EINVAL; 105a88b5ba8SSam Ravnborg return addr; 106a88b5ba8SSam Ravnborg } 107a88b5ba8SSam Ravnborg 108a88b5ba8SSam Ravnborg if (test_thread_flag(TIF_32BIT)) 109a88b5ba8SSam Ravnborg task_size = STACK_TOP32; 110a88b5ba8SSam Ravnborg if (unlikely(len > task_size || len >= VA_EXCLUDE_START)) 111a88b5ba8SSam Ravnborg return -ENOMEM; 112a88b5ba8SSam Ravnborg 113a88b5ba8SSam Ravnborg do_color_align = 0; 114a88b5ba8SSam Ravnborg if (filp || (flags & MAP_SHARED)) 115a88b5ba8SSam Ravnborg do_color_align = 1; 116a88b5ba8SSam Ravnborg 117a88b5ba8SSam Ravnborg if (addr) { 118a88b5ba8SSam Ravnborg if (do_color_align) 119748ba883SAndrew Morton addr = COLOR_ALIGN(addr, pgoff); 120a88b5ba8SSam Ravnborg else 121a88b5ba8SSam Ravnborg addr = PAGE_ALIGN(addr); 122a88b5ba8SSam Ravnborg 123a88b5ba8SSam Ravnborg vma = find_vma(mm, addr); 124a88b5ba8SSam Ravnborg if (task_size - len >= addr && 1251be7107fSHugh Dickins (!vma || addr + len <= vm_start_gap(vma))) 126a88b5ba8SSam Ravnborg return addr; 127a88b5ba8SSam Ravnborg } 128a88b5ba8SSam Ravnborg 129bb64f550SMichel Lespinasse info.length = len; 130bb64f550SMichel Lespinasse info.low_limit = TASK_UNMAPPED_BASE; 131bb64f550SMichel Lespinasse info.high_limit = min(task_size, VA_EXCLUDE_START); 132bb64f550SMichel Lespinasse info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; 133bb64f550SMichel Lespinasse info.align_offset = pgoff << PAGE_SHIFT; 134bb64f550SMichel Lespinasse addr = vm_unmapped_area(&info); 135bb64f550SMichel Lespinasse 136bb64f550SMichel Lespinasse if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) { 137bb64f550SMichel Lespinasse VM_BUG_ON(addr != -ENOMEM); 138bb64f550SMichel Lespinasse info.low_limit = VA_EXCLUDE_END; 139bb64f550SMichel Lespinasse info.high_limit = task_size; 140bb64f550SMichel Lespinasse addr = vm_unmapped_area(&info); 141a88b5ba8SSam Ravnborg } 142a88b5ba8SSam Ravnborg 143a88b5ba8SSam Ravnborg return addr; 144a88b5ba8SSam Ravnborg } 145a88b5ba8SSam Ravnborg 146a88b5ba8SSam Ravnborg unsigned long 147a88b5ba8SSam Ravnborg arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 148a88b5ba8SSam Ravnborg const unsigned long len, const unsigned long pgoff, 149a88b5ba8SSam Ravnborg const unsigned long flags) 150a88b5ba8SSam Ravnborg { 151a88b5ba8SSam Ravnborg struct vm_area_struct *vma; 152a88b5ba8SSam Ravnborg struct mm_struct *mm = current->mm; 153a88b5ba8SSam Ravnborg unsigned long task_size = STACK_TOP32; 154a88b5ba8SSam Ravnborg unsigned long addr = addr0; 155a88b5ba8SSam Ravnborg int do_color_align; 156*b80fa3cbSRick Edgecombe struct vm_unmapped_area_info info = {}; 157a88b5ba8SSam Ravnborg 158a88b5ba8SSam Ravnborg /* This should only ever run for 32-bit processes. */ 159a88b5ba8SSam Ravnborg BUG_ON(!test_thread_flag(TIF_32BIT)); 160a88b5ba8SSam Ravnborg 161a88b5ba8SSam Ravnborg if (flags & MAP_FIXED) { 162a88b5ba8SSam Ravnborg /* We do not accept a shared mapping if it would violate 163a88b5ba8SSam Ravnborg * cache aliasing constraints. 164a88b5ba8SSam Ravnborg */ 165a88b5ba8SSam Ravnborg if ((flags & MAP_SHARED) && 166a88b5ba8SSam Ravnborg ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) 167a88b5ba8SSam Ravnborg return -EINVAL; 168a88b5ba8SSam Ravnborg return addr; 169a88b5ba8SSam Ravnborg } 170a88b5ba8SSam Ravnborg 171a88b5ba8SSam Ravnborg if (unlikely(len > task_size)) 172a88b5ba8SSam Ravnborg return -ENOMEM; 173a88b5ba8SSam Ravnborg 174a88b5ba8SSam Ravnborg do_color_align = 0; 175a88b5ba8SSam Ravnborg if (filp || (flags & MAP_SHARED)) 176a88b5ba8SSam Ravnborg do_color_align = 1; 177a88b5ba8SSam Ravnborg 178a88b5ba8SSam Ravnborg /* requesting a specific address */ 179a88b5ba8SSam Ravnborg if (addr) { 180a88b5ba8SSam Ravnborg if (do_color_align) 181748ba883SAndrew Morton addr = COLOR_ALIGN(addr, pgoff); 182a88b5ba8SSam Ravnborg else 183a88b5ba8SSam Ravnborg addr = PAGE_ALIGN(addr); 184a88b5ba8SSam Ravnborg 185a88b5ba8SSam Ravnborg vma = find_vma(mm, addr); 186a88b5ba8SSam Ravnborg if (task_size - len >= addr && 1871be7107fSHugh Dickins (!vma || addr + len <= vm_start_gap(vma))) 188a88b5ba8SSam Ravnborg return addr; 189a88b5ba8SSam Ravnborg } 190a88b5ba8SSam Ravnborg 191bb64f550SMichel Lespinasse info.flags = VM_UNMAPPED_AREA_TOPDOWN; 192bb64f550SMichel Lespinasse info.length = len; 193bb64f550SMichel Lespinasse info.low_limit = PAGE_SIZE; 194bb64f550SMichel Lespinasse info.high_limit = mm->mmap_base; 195bb64f550SMichel Lespinasse info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; 196bb64f550SMichel Lespinasse info.align_offset = pgoff << PAGE_SHIFT; 197bb64f550SMichel Lespinasse addr = vm_unmapped_area(&info); 198a88b5ba8SSam Ravnborg 199a88b5ba8SSam Ravnborg /* 200a88b5ba8SSam Ravnborg * A failed mmap() very likely causes application failure, 201a88b5ba8SSam Ravnborg * so fall back to the bottom-up function here. This scenario 202a88b5ba8SSam Ravnborg * can happen with large stack limits and large mmap() 203a88b5ba8SSam Ravnborg * allocations. 204a88b5ba8SSam Ravnborg */ 205bb64f550SMichel Lespinasse if (addr & ~PAGE_MASK) { 206bb64f550SMichel Lespinasse VM_BUG_ON(addr != -ENOMEM); 207bb64f550SMichel Lespinasse info.flags = 0; 208bb64f550SMichel Lespinasse info.low_limit = TASK_UNMAPPED_BASE; 209bb64f550SMichel Lespinasse info.high_limit = STACK_TOP32; 210bb64f550SMichel Lespinasse addr = vm_unmapped_area(&info); 211bb64f550SMichel Lespinasse } 212a88b5ba8SSam Ravnborg 213a88b5ba8SSam Ravnborg return addr; 214a88b5ba8SSam Ravnborg } 215a88b5ba8SSam Ravnborg 216a88b5ba8SSam Ravnborg /* Try to align mapping such that we align it as much as possible. */ 217a88b5ba8SSam Ravnborg unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags) 218a88b5ba8SSam Ravnborg { 219a88b5ba8SSam Ravnborg unsigned long align_goal, addr = -ENOMEM; 220a88b5ba8SSam Ravnborg 221a88b5ba8SSam Ravnborg if (flags & MAP_FIXED) { 222a88b5ba8SSam Ravnborg /* Ok, don't mess with it. */ 223529ce23aSRick Edgecombe return mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags); 224a88b5ba8SSam Ravnborg } 225a88b5ba8SSam Ravnborg flags &= ~MAP_SHARED; 226a88b5ba8SSam Ravnborg 227a88b5ba8SSam Ravnborg align_goal = PAGE_SIZE; 228a88b5ba8SSam Ravnborg if (len >= (4UL * 1024 * 1024)) 229a88b5ba8SSam Ravnborg align_goal = (4UL * 1024 * 1024); 230a88b5ba8SSam Ravnborg else if (len >= (512UL * 1024)) 231a88b5ba8SSam Ravnborg align_goal = (512UL * 1024); 232a88b5ba8SSam Ravnborg else if (len >= (64UL * 1024)) 233a88b5ba8SSam Ravnborg align_goal = (64UL * 1024); 234a88b5ba8SSam Ravnborg 235a88b5ba8SSam Ravnborg do { 236529ce23aSRick Edgecombe addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, 237529ce23aSRick Edgecombe len + (align_goal - PAGE_SIZE), pgoff, flags); 238a88b5ba8SSam Ravnborg if (!(addr & ~PAGE_MASK)) { 239a88b5ba8SSam Ravnborg addr = (addr + (align_goal - 1UL)) & ~(align_goal - 1UL); 240a88b5ba8SSam Ravnborg break; 241a88b5ba8SSam Ravnborg } 242a88b5ba8SSam Ravnborg 243a88b5ba8SSam Ravnborg if (align_goal == (4UL * 1024 * 1024)) 244a88b5ba8SSam Ravnborg align_goal = (512UL * 1024); 245a88b5ba8SSam Ravnborg else if (align_goal == (512UL * 1024)) 246a88b5ba8SSam Ravnborg align_goal = (64UL * 1024); 247a88b5ba8SSam Ravnborg else 248a88b5ba8SSam Ravnborg align_goal = PAGE_SIZE; 249a88b5ba8SSam Ravnborg } while ((addr & ~PAGE_MASK) && align_goal > PAGE_SIZE); 250a88b5ba8SSam Ravnborg 251a88b5ba8SSam Ravnborg /* Mapping is smaller than 64K or larger areas could not 252a88b5ba8SSam Ravnborg * be obtained. 253a88b5ba8SSam Ravnborg */ 254a88b5ba8SSam Ravnborg if (addr & ~PAGE_MASK) 255529ce23aSRick Edgecombe addr = mm_get_unmapped_area(current->mm, NULL, orig_addr, len, pgoff, flags); 256a88b5ba8SSam Ravnborg 257a88b5ba8SSam Ravnborg return addr; 258a88b5ba8SSam Ravnborg } 259917c3660SSam Ravnborg EXPORT_SYMBOL(get_fb_unmapped_area); 260a88b5ba8SSam Ravnborg 2615a0efea0SDavid S. Miller /* Essentially the same as PowerPC. */ 2625a0efea0SDavid S. Miller static unsigned long mmap_rnd(void) 263a88b5ba8SSam Ravnborg { 2645a0efea0SDavid S. Miller unsigned long rnd = 0UL; 265a88b5ba8SSam Ravnborg 266a88b5ba8SSam Ravnborg if (current->flags & PF_RANDOMIZE) { 2675ef11c35SDaniel Cashman unsigned long val = get_random_long(); 268a88b5ba8SSam Ravnborg if (test_thread_flag(TIF_32BIT)) 269fa8cbaafSDan McGee rnd = (val % (1UL << (23UL-PAGE_SHIFT))); 270a88b5ba8SSam Ravnborg else 271fa8cbaafSDan McGee rnd = (val % (1UL << (30UL-PAGE_SHIFT))); 272a88b5ba8SSam Ravnborg } 273fa8cbaafSDan McGee return rnd << PAGE_SHIFT; 2745a0efea0SDavid S. Miller } 2755a0efea0SDavid S. Miller 2768f2af155SKees Cook void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) 2775a0efea0SDavid S. Miller { 2785a0efea0SDavid S. Miller unsigned long random_factor = mmap_rnd(); 2795a0efea0SDavid S. Miller unsigned long gap; 280a88b5ba8SSam Ravnborg 281a88b5ba8SSam Ravnborg /* 282a88b5ba8SSam Ravnborg * Fall back to the standard layout if the personality 283a88b5ba8SSam Ravnborg * bit is set, or if the expected stack growth is unlimited: 284a88b5ba8SSam Ravnborg */ 2858f2af155SKees Cook gap = rlim_stack->rlim_cur; 286a88b5ba8SSam Ravnborg if (!test_thread_flag(TIF_32BIT) || 287a88b5ba8SSam Ravnborg (current->personality & ADDR_COMPAT_LAYOUT) || 28876704fb5SJiri Slaby gap == RLIM_INFINITY || 289a88b5ba8SSam Ravnborg sysctl_legacy_va_layout) { 290a88b5ba8SSam Ravnborg mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; 291529ce23aSRick Edgecombe clear_bit(MMF_TOPDOWN, &mm->flags); 292a88b5ba8SSam Ravnborg } else { 293a88b5ba8SSam Ravnborg /* We know it's 32-bit */ 294a88b5ba8SSam Ravnborg unsigned long task_size = STACK_TOP32; 295a88b5ba8SSam Ravnborg 296a88b5ba8SSam Ravnborg if (gap < 128 * 1024 * 1024) 297a88b5ba8SSam Ravnborg gap = 128 * 1024 * 1024; 298a88b5ba8SSam Ravnborg if (gap > (task_size / 6 * 5)) 299a88b5ba8SSam Ravnborg gap = (task_size / 6 * 5); 300a88b5ba8SSam Ravnborg 301a88b5ba8SSam Ravnborg mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor); 302529ce23aSRick Edgecombe set_bit(MMF_TOPDOWN, &mm->flags); 303a88b5ba8SSam Ravnborg } 304a88b5ba8SSam Ravnborg } 305a88b5ba8SSam Ravnborg 306a88b5ba8SSam Ravnborg /* 307a88b5ba8SSam Ravnborg * sys_pipe() is the normal C calling standard for creating 308a88b5ba8SSam Ravnborg * a pipe. It's not the way unix traditionally does this, though. 309a88b5ba8SSam Ravnborg */ 3103e3511b3SAl Viro SYSCALL_DEFINE0(sparc_pipe) 311a88b5ba8SSam Ravnborg { 312a88b5ba8SSam Ravnborg int fd[2]; 313a88b5ba8SSam Ravnborg int error; 314a88b5ba8SSam Ravnborg 315a88b5ba8SSam Ravnborg error = do_pipe_flags(fd, 0); 316a88b5ba8SSam Ravnborg if (error) 317a88b5ba8SSam Ravnborg goto out; 3183e3511b3SAl Viro current_pt_regs()->u_regs[UREG_I1] = fd[1]; 319a88b5ba8SSam Ravnborg error = fd[0]; 320a88b5ba8SSam Ravnborg out: 321a88b5ba8SSam Ravnborg return error; 322a88b5ba8SSam Ravnborg } 323a88b5ba8SSam Ravnborg 324a88b5ba8SSam Ravnborg /* 325a88b5ba8SSam Ravnborg * sys_ipc() is the de-multiplexer for the SysV IPC calls.. 326a88b5ba8SSam Ravnborg * 327a88b5ba8SSam Ravnborg * This is really horribly ugly. 328a88b5ba8SSam Ravnborg */ 329a88b5ba8SSam Ravnborg 330baed7fc9SChristoph Hellwig SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second, 331e4265019SDavid S. Miller unsigned long, third, void __user *, ptr, long, fifth) 332a88b5ba8SSam Ravnborg { 333a88b5ba8SSam Ravnborg long err; 334a88b5ba8SSam Ravnborg 335fb377eb8SArnd Bergmann if (!IS_ENABLED(CONFIG_SYSVIPC)) 336fb377eb8SArnd Bergmann return -ENOSYS; 337fb377eb8SArnd Bergmann 338a88b5ba8SSam Ravnborg /* No need for backward compatibility. We can start fresh... */ 33953eb2516SRob Gardner if (call <= SEMTIMEDOP) { 340a88b5ba8SSam Ravnborg switch (call) { 341a88b5ba8SSam Ravnborg case SEMOP: 342fb377eb8SArnd Bergmann err = ksys_semtimedop(first, ptr, 3439ef595d8SJoe Perches (unsigned int)second, NULL); 344a88b5ba8SSam Ravnborg goto out; 345a88b5ba8SSam Ravnborg case SEMTIMEDOP: 346fb377eb8SArnd Bergmann err = ksys_semtimedop(first, ptr, (unsigned int)second, 34773a66023SArnd Bergmann (const struct __kernel_timespec __user *) 348a88b5ba8SSam Ravnborg (unsigned long) fifth); 349a88b5ba8SSam Ravnborg goto out; 350a88b5ba8SSam Ravnborg case SEMGET: 351fb377eb8SArnd Bergmann err = ksys_semget(first, (int)second, (int)third); 352a88b5ba8SSam Ravnborg goto out; 353a88b5ba8SSam Ravnborg case SEMCTL: { 354fb377eb8SArnd Bergmann err = ksys_old_semctl(first, second, 355a88b5ba8SSam Ravnborg (int)third | IPC_64, 356e1fd1f49SAl Viro (unsigned long) ptr); 357a88b5ba8SSam Ravnborg goto out; 358a88b5ba8SSam Ravnborg } 359a88b5ba8SSam Ravnborg default: 360a88b5ba8SSam Ravnborg err = -ENOSYS; 361a88b5ba8SSam Ravnborg goto out; 3626cb79b3fSJoe Perches } 363a88b5ba8SSam Ravnborg } 364a88b5ba8SSam Ravnborg if (call <= MSGCTL) { 365a88b5ba8SSam Ravnborg switch (call) { 366a88b5ba8SSam Ravnborg case MSGSND: 367fb377eb8SArnd Bergmann err = ksys_msgsnd(first, ptr, (size_t)second, 368a88b5ba8SSam Ravnborg (int)third); 369a88b5ba8SSam Ravnborg goto out; 370a88b5ba8SSam Ravnborg case MSGRCV: 371fb377eb8SArnd Bergmann err = ksys_msgrcv(first, ptr, (size_t)second, fifth, 372a88b5ba8SSam Ravnborg (int)third); 373a88b5ba8SSam Ravnborg goto out; 374a88b5ba8SSam Ravnborg case MSGGET: 375fb377eb8SArnd Bergmann err = ksys_msgget((key_t)first, (int)second); 376a88b5ba8SSam Ravnborg goto out; 377a88b5ba8SSam Ravnborg case MSGCTL: 378fb377eb8SArnd Bergmann err = ksys_old_msgctl(first, (int)second | IPC_64, ptr); 379a88b5ba8SSam Ravnborg goto out; 380a88b5ba8SSam Ravnborg default: 381a88b5ba8SSam Ravnborg err = -ENOSYS; 382a88b5ba8SSam Ravnborg goto out; 3836cb79b3fSJoe Perches } 384a88b5ba8SSam Ravnborg } 385a88b5ba8SSam Ravnborg if (call <= SHMCTL) { 386a88b5ba8SSam Ravnborg switch (call) { 387a88b5ba8SSam Ravnborg case SHMAT: { 388a88b5ba8SSam Ravnborg ulong raddr; 389079a96aeSWill Deacon err = do_shmat(first, ptr, (int)second, &raddr, SHMLBA); 390a88b5ba8SSam Ravnborg if (!err) { 391a88b5ba8SSam Ravnborg if (put_user(raddr, 392a88b5ba8SSam Ravnborg (ulong __user *) third)) 393a88b5ba8SSam Ravnborg err = -EFAULT; 394a88b5ba8SSam Ravnborg } 395a88b5ba8SSam Ravnborg goto out; 396a88b5ba8SSam Ravnborg } 397a88b5ba8SSam Ravnborg case SHMDT: 398fb377eb8SArnd Bergmann err = ksys_shmdt(ptr); 399a88b5ba8SSam Ravnborg goto out; 400a88b5ba8SSam Ravnborg case SHMGET: 401fb377eb8SArnd Bergmann err = ksys_shmget(first, (size_t)second, (int)third); 402a88b5ba8SSam Ravnborg goto out; 403a88b5ba8SSam Ravnborg case SHMCTL: 404fb377eb8SArnd Bergmann err = ksys_old_shmctl(first, (int)second | IPC_64, ptr); 405a88b5ba8SSam Ravnborg goto out; 406a88b5ba8SSam Ravnborg default: 407a88b5ba8SSam Ravnborg err = -ENOSYS; 408a88b5ba8SSam Ravnborg goto out; 4096cb79b3fSJoe Perches } 410a88b5ba8SSam Ravnborg } else { 411a88b5ba8SSam Ravnborg err = -ENOSYS; 412a88b5ba8SSam Ravnborg } 413a88b5ba8SSam Ravnborg out: 414a88b5ba8SSam Ravnborg return err; 415a88b5ba8SSam Ravnborg } 416a88b5ba8SSam Ravnborg 417e4265019SDavid S. Miller SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) 418a88b5ba8SSam Ravnborg { 419525fd5a9SDmitry V. Levin long ret; 420a88b5ba8SSam Ravnborg 421a27032eeSJiri Kosina if (personality(current->personality) == PER_LINUX32 && 422a27032eeSJiri Kosina personality(personality) == PER_LINUX) 423a27032eeSJiri Kosina personality |= PER_LINUX32; 424a88b5ba8SSam Ravnborg ret = sys_personality(personality); 425a27032eeSJiri Kosina if (personality(ret) == PER_LINUX32) 426a27032eeSJiri Kosina ret &= ~PER_LINUX32; 427a88b5ba8SSam Ravnborg 428a88b5ba8SSam Ravnborg return ret; 429a88b5ba8SSam Ravnborg } 430a88b5ba8SSam Ravnborg 431a88b5ba8SSam Ravnborg int sparc_mmap_check(unsigned long addr, unsigned long len) 432a88b5ba8SSam Ravnborg { 433a88b5ba8SSam Ravnborg if (test_thread_flag(TIF_32BIT)) { 434a88b5ba8SSam Ravnborg if (len >= STACK_TOP32) 435a88b5ba8SSam Ravnborg return -EINVAL; 436a88b5ba8SSam Ravnborg 437a88b5ba8SSam Ravnborg if (addr > STACK_TOP32 - len) 438a88b5ba8SSam Ravnborg return -EINVAL; 439a88b5ba8SSam Ravnborg } else { 440a88b5ba8SSam Ravnborg if (len >= VA_EXCLUDE_START) 441a88b5ba8SSam Ravnborg return -EINVAL; 442a88b5ba8SSam Ravnborg 443a88b5ba8SSam Ravnborg if (invalid_64bit_range(addr, len)) 444a88b5ba8SSam Ravnborg return -EINVAL; 445a88b5ba8SSam Ravnborg } 446a88b5ba8SSam Ravnborg 447a88b5ba8SSam Ravnborg return 0; 448a88b5ba8SSam Ravnborg } 449a88b5ba8SSam Ravnborg 450a88b5ba8SSam Ravnborg /* Linux version of mmap */ 451e4265019SDavid S. Miller SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, 452e4265019SDavid S. Miller unsigned long, prot, unsigned long, flags, unsigned long, fd, 453e4265019SDavid S. Miller unsigned long, off) 454a88b5ba8SSam Ravnborg { 455f8b72560SAl Viro unsigned long retval = -EINVAL; 456a88b5ba8SSam Ravnborg 457f8b72560SAl Viro if ((off + PAGE_ALIGN(len)) < off) 458a88b5ba8SSam Ravnborg goto out; 459f8b72560SAl Viro if (off & ~PAGE_MASK) 460f8b72560SAl Viro goto out; 461a90f590aSDominik Brodowski retval = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); 462a88b5ba8SSam Ravnborg out: 463a88b5ba8SSam Ravnborg return retval; 464a88b5ba8SSam Ravnborg } 465a88b5ba8SSam Ravnborg 466e4265019SDavid S. Miller SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len) 467a88b5ba8SSam Ravnborg { 468a88b5ba8SSam Ravnborg if (invalid_64bit_range(addr, len)) 469a88b5ba8SSam Ravnborg return -EINVAL; 470a88b5ba8SSam Ravnborg 471bfce281cSAl Viro return vm_munmap(addr, len); 472a88b5ba8SSam Ravnborg } 473a88b5ba8SSam Ravnborg 474e4265019SDavid S. Miller SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, 475e4265019SDavid S. Miller unsigned long, new_len, unsigned long, flags, 476e4265019SDavid S. Miller unsigned long, new_addr) 477a88b5ba8SSam Ravnborg { 478a88b5ba8SSam Ravnborg if (test_thread_flag(TIF_32BIT)) 479657bec85SAl Viro return -EINVAL; 480657bec85SAl Viro return sys_mremap(addr, old_len, new_len, flags, new_addr); 481a88b5ba8SSam Ravnborg } 482a88b5ba8SSam Ravnborg 48347db6975SAl Viro SYSCALL_DEFINE0(nis_syscall) 484a88b5ba8SSam Ravnborg { 485a88b5ba8SSam Ravnborg static int count; 48647db6975SAl Viro struct pt_regs *regs = current_pt_regs(); 487a88b5ba8SSam Ravnborg 488a88b5ba8SSam Ravnborg /* Don't make the system unusable, if someone goes stuck */ 489a88b5ba8SSam Ravnborg if (count++ > 5) 490a88b5ba8SSam Ravnborg return -ENOSYS; 491a88b5ba8SSam Ravnborg 492a88b5ba8SSam Ravnborg printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]); 493a88b5ba8SSam Ravnborg #ifdef DEBUG_UNIMP_SYSCALL 494a88b5ba8SSam Ravnborg show_regs (regs); 495a88b5ba8SSam Ravnborg #endif 496a88b5ba8SSam Ravnborg 497a88b5ba8SSam Ravnborg return -ENOSYS; 498a88b5ba8SSam Ravnborg } 499a88b5ba8SSam Ravnborg 500a88b5ba8SSam Ravnborg /* #define DEBUG_SPARC_BREAKPOINT */ 501a88b5ba8SSam Ravnborg 502a88b5ba8SSam Ravnborg asmlinkage void sparc_breakpoint(struct pt_regs *regs) 503a88b5ba8SSam Ravnborg { 504812cb83aSKirill Tkhai enum ctx_state prev_state = exception_enter(); 505a88b5ba8SSam Ravnborg 506a88b5ba8SSam Ravnborg if (test_thread_flag(TIF_32BIT)) { 507a88b5ba8SSam Ravnborg regs->tpc &= 0xffffffff; 508a88b5ba8SSam Ravnborg regs->tnpc &= 0xffffffff; 509a88b5ba8SSam Ravnborg } 510a88b5ba8SSam Ravnborg #ifdef DEBUG_SPARC_BREAKPOINT 511a88b5ba8SSam Ravnborg printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc); 512a88b5ba8SSam Ravnborg #endif 5132c9f7eafSEric W. Biederman force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->tpc); 514a88b5ba8SSam Ravnborg #ifdef DEBUG_SPARC_BREAKPOINT 515a88b5ba8SSam Ravnborg printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc); 516a88b5ba8SSam Ravnborg #endif 517812cb83aSKirill Tkhai exception_exit(prev_state); 518a88b5ba8SSam Ravnborg } 519a88b5ba8SSam Ravnborg 520e4265019SDavid S. Miller SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) 521a88b5ba8SSam Ravnborg { 522a88b5ba8SSam Ravnborg int nlen, err; 52342a0cc34SJann Horn char tmp[__NEW_UTS_LEN + 1]; 524a88b5ba8SSam Ravnborg 525a88b5ba8SSam Ravnborg if (len < 0) 526a88b5ba8SSam Ravnborg return -EINVAL; 527a88b5ba8SSam Ravnborg 528a88b5ba8SSam Ravnborg down_read(&uts_sem); 529a88b5ba8SSam Ravnborg 530a88b5ba8SSam Ravnborg nlen = strlen(utsname()->domainname) + 1; 531a88b5ba8SSam Ravnborg err = -EINVAL; 532a88b5ba8SSam Ravnborg if (nlen > len) 53342a0cc34SJann Horn goto out_unlock; 53442a0cc34SJann Horn memcpy(tmp, utsname()->domainname, nlen); 535a88b5ba8SSam Ravnborg 53642a0cc34SJann Horn up_read(&uts_sem); 537a88b5ba8SSam Ravnborg 53842a0cc34SJann Horn if (copy_to_user(name, tmp, nlen)) 53942a0cc34SJann Horn return -EFAULT; 54042a0cc34SJann Horn return 0; 54142a0cc34SJann Horn 54242a0cc34SJann Horn out_unlock: 543a88b5ba8SSam Ravnborg up_read(&uts_sem); 544a88b5ba8SSam Ravnborg return err; 545a88b5ba8SSam Ravnborg } 546a88b5ba8SSam Ravnborg 547251ec1c1SArnd Bergmann SYSCALL_DEFINE1(sparc_adjtimex, struct __kernel_timex __user *, txc_p) 5481a596398SArnd Bergmann { 549251ec1c1SArnd Bergmann struct __kernel_timex txc; 55011648b83SArnd Bergmann struct __kernel_old_timeval *tv = (void *)&txc.time; 5511a596398SArnd Bergmann int ret; 5521a596398SArnd Bergmann 5531a596398SArnd Bergmann /* Copy the user data space into the kernel copy 5541a596398SArnd Bergmann * structure. But bear in mind that the structures 5551a596398SArnd Bergmann * may change 5561a596398SArnd Bergmann */ 557251ec1c1SArnd Bergmann if (copy_from_user(&txc, txc_p, sizeof(txc))) 5581a596398SArnd Bergmann return -EFAULT; 5591a596398SArnd Bergmann 5601a596398SArnd Bergmann /* 5611a596398SArnd Bergmann * override for sparc64 specific timeval type: tv_usec 5621a596398SArnd Bergmann * is 32 bit wide instead of 64-bit in __kernel_timex 5631a596398SArnd Bergmann */ 564251ec1c1SArnd Bergmann txc.time.tv_usec = tv->tv_usec; 565251ec1c1SArnd Bergmann ret = do_adjtimex(&txc); 566251ec1c1SArnd Bergmann tv->tv_usec = txc.time.tv_usec; 5671a596398SArnd Bergmann 568251ec1c1SArnd Bergmann return copy_to_user(txc_p, &txc, sizeof(txc)) ? -EFAULT : ret; 5691a596398SArnd Bergmann } 5701a596398SArnd Bergmann 571251ec1c1SArnd Bergmann SYSCALL_DEFINE2(sparc_clock_adjtime, const clockid_t, which_clock, 572251ec1c1SArnd Bergmann struct __kernel_timex __user *, txc_p) 5731a596398SArnd Bergmann { 574251ec1c1SArnd Bergmann struct __kernel_timex txc; 57511648b83SArnd Bergmann struct __kernel_old_timeval *tv = (void *)&txc.time; 5761a596398SArnd Bergmann int ret; 5771a596398SArnd Bergmann 5781a596398SArnd Bergmann if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) { 5791a596398SArnd Bergmann pr_err_once("process %d (%s) attempted a POSIX timer syscall " 5801a596398SArnd Bergmann "while CONFIG_POSIX_TIMERS is not set\n", 5811a596398SArnd Bergmann current->pid, current->comm); 5821a596398SArnd Bergmann 5831a596398SArnd Bergmann return -ENOSYS; 5841a596398SArnd Bergmann } 5851a596398SArnd Bergmann 5861a596398SArnd Bergmann /* Copy the user data space into the kernel copy 5871a596398SArnd Bergmann * structure. But bear in mind that the structures 5881a596398SArnd Bergmann * may change 5891a596398SArnd Bergmann */ 590251ec1c1SArnd Bergmann if (copy_from_user(&txc, txc_p, sizeof(txc))) 5911a596398SArnd Bergmann return -EFAULT; 5921a596398SArnd Bergmann 5931a596398SArnd Bergmann /* 5941a596398SArnd Bergmann * override for sparc64 specific timeval type: tv_usec 5951a596398SArnd Bergmann * is 32 bit wide instead of 64-bit in __kernel_timex 5961a596398SArnd Bergmann */ 597251ec1c1SArnd Bergmann txc.time.tv_usec = tv->tv_usec; 598251ec1c1SArnd Bergmann ret = do_clock_adjtime(which_clock, &txc); 599251ec1c1SArnd Bergmann tv->tv_usec = txc.time.tv_usec; 6001a596398SArnd Bergmann 601251ec1c1SArnd Bergmann return copy_to_user(txc_p, &txc, sizeof(txc)) ? -EFAULT : ret; 6021a596398SArnd Bergmann } 6031a596398SArnd Bergmann 604e4265019SDavid S. Miller SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type, 605e4265019SDavid S. Miller utrap_handler_t, new_p, utrap_handler_t, new_d, 606e4265019SDavid S. Miller utrap_handler_t __user *, old_p, 607e4265019SDavid S. Miller utrap_handler_t __user *, old_d) 608a88b5ba8SSam Ravnborg { 609a88b5ba8SSam Ravnborg if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31) 610a88b5ba8SSam Ravnborg return -EINVAL; 611a88b5ba8SSam Ravnborg if (new_p == (utrap_handler_t)(long)UTH_NOCHANGE) { 612a88b5ba8SSam Ravnborg if (old_p) { 613a88b5ba8SSam Ravnborg if (!current_thread_info()->utraps) { 614a88b5ba8SSam Ravnborg if (put_user(NULL, old_p)) 615a88b5ba8SSam Ravnborg return -EFAULT; 616a88b5ba8SSam Ravnborg } else { 617a88b5ba8SSam Ravnborg if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p)) 618a88b5ba8SSam Ravnborg return -EFAULT; 619a88b5ba8SSam Ravnborg } 620a88b5ba8SSam Ravnborg } 621a88b5ba8SSam Ravnborg if (old_d) { 622a88b5ba8SSam Ravnborg if (put_user(NULL, old_d)) 623a88b5ba8SSam Ravnborg return -EFAULT; 624a88b5ba8SSam Ravnborg } 625a88b5ba8SSam Ravnborg return 0; 626a88b5ba8SSam Ravnborg } 627a88b5ba8SSam Ravnborg if (!current_thread_info()->utraps) { 628a88b5ba8SSam Ravnborg current_thread_info()->utraps = 6296396bb22SKees Cook kcalloc(UT_TRAP_INSTRUCTION_31 + 1, sizeof(long), 6306396bb22SKees Cook GFP_KERNEL); 631a88b5ba8SSam Ravnborg if (!current_thread_info()->utraps) 632a88b5ba8SSam Ravnborg return -ENOMEM; 633a88b5ba8SSam Ravnborg current_thread_info()->utraps[0] = 1; 634a88b5ba8SSam Ravnborg } else { 635a88b5ba8SSam Ravnborg if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p && 636a88b5ba8SSam Ravnborg current_thread_info()->utraps[0] > 1) { 637a88b5ba8SSam Ravnborg unsigned long *p = current_thread_info()->utraps; 638a88b5ba8SSam Ravnborg 639a88b5ba8SSam Ravnborg current_thread_info()->utraps = 6406da2ec56SKees Cook kmalloc_array(UT_TRAP_INSTRUCTION_31 + 1, 6416da2ec56SKees Cook sizeof(long), 642a88b5ba8SSam Ravnborg GFP_KERNEL); 643a88b5ba8SSam Ravnborg if (!current_thread_info()->utraps) { 644a88b5ba8SSam Ravnborg current_thread_info()->utraps = p; 645a88b5ba8SSam Ravnborg return -ENOMEM; 646a88b5ba8SSam Ravnborg } 647a88b5ba8SSam Ravnborg p[0]--; 648a88b5ba8SSam Ravnborg current_thread_info()->utraps[0] = 1; 649a88b5ba8SSam Ravnborg memcpy(current_thread_info()->utraps+1, p+1, 650a88b5ba8SSam Ravnborg UT_TRAP_INSTRUCTION_31*sizeof(long)); 651a88b5ba8SSam Ravnborg } 652a88b5ba8SSam Ravnborg } 653a88b5ba8SSam Ravnborg if (old_p) { 654a88b5ba8SSam Ravnborg if (put_user((utrap_handler_t)(current_thread_info()->utraps[type]), old_p)) 655a88b5ba8SSam Ravnborg return -EFAULT; 656a88b5ba8SSam Ravnborg } 657a88b5ba8SSam Ravnborg if (old_d) { 658a88b5ba8SSam Ravnborg if (put_user(NULL, old_d)) 659a88b5ba8SSam Ravnborg return -EFAULT; 660a88b5ba8SSam Ravnborg } 661a88b5ba8SSam Ravnborg current_thread_info()->utraps[type] = (long)new_p; 662a88b5ba8SSam Ravnborg 663a88b5ba8SSam Ravnborg return 0; 664a88b5ba8SSam Ravnborg } 665a88b5ba8SSam Ravnborg 6666de7617eSAl Viro SYSCALL_DEFINE1(memory_ordering, unsigned long, model) 667a88b5ba8SSam Ravnborg { 6686de7617eSAl Viro struct pt_regs *regs = current_pt_regs(); 669a88b5ba8SSam Ravnborg if (model >= 3) 670a88b5ba8SSam Ravnborg return -EINVAL; 671a88b5ba8SSam Ravnborg regs->tstate = (regs->tstate & ~TSTATE_MM) | (model << 14); 672a88b5ba8SSam Ravnborg return 0; 673a88b5ba8SSam Ravnborg } 674a88b5ba8SSam Ravnborg 675e4265019SDavid S. Miller SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, 676e4265019SDavid S. Miller struct sigaction __user *, oact, void __user *, restorer, 677e4265019SDavid S. Miller size_t, sigsetsize) 678a88b5ba8SSam Ravnborg { 679a88b5ba8SSam Ravnborg struct k_sigaction new_ka, old_ka; 680a88b5ba8SSam Ravnborg int ret; 681a88b5ba8SSam Ravnborg 682a88b5ba8SSam Ravnborg /* XXX: Don't preclude handling different sized sigset_t's. */ 683a88b5ba8SSam Ravnborg if (sigsetsize != sizeof(sigset_t)) 684a88b5ba8SSam Ravnborg return -EINVAL; 685a88b5ba8SSam Ravnborg 686a88b5ba8SSam Ravnborg if (act) { 687a88b5ba8SSam Ravnborg new_ka.ka_restorer = restorer; 688a88b5ba8SSam Ravnborg if (copy_from_user(&new_ka.sa, act, sizeof(*act))) 689a88b5ba8SSam Ravnborg return -EFAULT; 690a88b5ba8SSam Ravnborg } 691a88b5ba8SSam Ravnborg 692a88b5ba8SSam Ravnborg ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 693a88b5ba8SSam Ravnborg 694a88b5ba8SSam Ravnborg if (!ret && oact) { 695a88b5ba8SSam Ravnborg if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) 696a88b5ba8SSam Ravnborg return -EFAULT; 697a88b5ba8SSam Ravnborg } 698a88b5ba8SSam Ravnborg 699a88b5ba8SSam Ravnborg return ret; 700a88b5ba8SSam Ravnborg } 701a88b5ba8SSam Ravnborg 702ee076e81SAl Viro SYSCALL_DEFINE0(kern_features) 703517ffce4SDavid S. Miller { 704517ffce4SDavid S. Miller return KERN_FEATURE_MIXED_MODE_STACK; 705517ffce4SDavid S. Miller } 706