Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | // SPDX-License-Identifier: GPL-2.0 /* linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/sparc * platform. */ #include <linux/errno.h> #include <linux/types.h> #include <linux/sched/signal.h> #include <linux/sched/mm.h> #include <linux/sched/debug.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/sem.h> #include <linux/msg.h> #include <linux/shm.h> #include <linux/stat.h> #include <linux/syscalls.h> #include <linux/mman.h> #include <linux/utsname.h> #include <linux/smp.h> #include <linux/ipc.h> #include <linux/uaccess.h> #include <asm/unistd.h> #include "systbls.h" /* #define DEBUG_UNIMP_SYSCALL */ /* XXX Make this per-binary type, this way we can detect the type of * XXX a binary. Every Sparc executable calls this very early on. */ SYSCALL_DEFINE0(getpagesize) { return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */ } unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct vm_unmapped_area_info info; if (flags & MAP_FIXED) { /* We do not accept a shared mapping if it would violate * cache aliasing constraints. */ if ((flags & MAP_SHARED) && ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) return -EINVAL; return addr; } /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE) return -ENOMEM; if (!addr) addr = TASK_UNMAPPED_BASE; info.flags = 0; info.length = len; info.low_limit = addr; info.high_limit = TASK_SIZE; info.align_mask = (flags & MAP_SHARED) ? (PAGE_MASK & (SHMLBA - 1)) : 0; info.align_offset = pgoff << PAGE_SHIFT; return vm_unmapped_area(&info); } /* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way unix traditionally does this, though. */ SYSCALL_DEFINE0(sparc_pipe) { int fd[2]; int error; error = do_pipe_flags(fd, 0); if (error) goto out; current_pt_regs()->u_regs[UREG_I1] = fd[1]; error = fd[0]; out: return error; } int sparc_mmap_check(unsigned long addr, unsigned long len) { /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) return -EINVAL; return 0; } /* Linux version of mmap */ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, pgoff) { /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have. */ return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); } SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { /* no alignment check? */ return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); } SYSCALL_DEFINE5(sparc_remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags) { /* This works on an existing mmap so we don't need to validate * the range as that was done at the original mmap call. */ return sys_remap_file_pages(start, size, prot, (pgoff >> (PAGE_SHIFT - 12)), flags); } SYSCALL_DEFINE0(nis_syscall) { static int count = 0; struct pt_regs *regs = current_pt_regs(); if (count++ > 5) return -ENOSYS; printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, task_pid_nr(current), (int)regs->u_regs[1]); #ifdef DEBUG_UNIMP_SYSCALL show_regs (regs); #endif return -ENOSYS; } /* #define DEBUG_SPARC_BREAKPOINT */ asmlinkage void sparc_breakpoint (struct pt_regs *regs) { #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc); #endif force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc); #ifdef DEBUG_SPARC_BREAKPOINT printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc); #endif } SYSCALL_DEFINE3(sparc_sigaction, int, sig, struct old_sigaction __user *,act, struct old_sigaction __user *,oact) { WARN_ON_ONCE(sig >= 0); return sys_sigaction(-sig, act, oact); } SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, struct sigaction __user *, oact, void __user *, restorer, size_t, sigsetsize) { struct k_sigaction new_ka, old_ka; int ret; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) return -EINVAL; if (act) { new_ka.ka_restorer = restorer; if (copy_from_user(&new_ka.sa, act, sizeof(*act))) return -EFAULT; } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) return -EFAULT; } return ret; } SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) { int nlen, err; char tmp[__NEW_UTS_LEN + 1]; if (len < 0) return -EINVAL; down_read(&uts_sem); nlen = strlen(utsname()->domainname) + 1; err = -EINVAL; if (nlen > len) goto out_unlock; memcpy(tmp, utsname()->domainname, nlen); up_read(&uts_sem); if (copy_to_user(name, tmp, nlen)) return -EFAULT; return 0; out_unlock: up_read(&uts_sem); return err; } |