~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/syscall.c

Version: ~ [ linux-5.14-rc3 ] ~ [ linux-5.13.5 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.53 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.135 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.198 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.240 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.276 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.276 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file "COPYING" in the main directory of this archive
  4  * for more details.
  5  *
  6  * Copyright (C) 1995, 1996, 1997, 2000, 2001, 05 by Ralf Baechle
  7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8  * Copyright (C) 2001 MIPS Technologies, Inc.
  9  */
 10 #include <linux/capability.h>
 11 #include <linux/errno.h>
 12 #include <linux/linkage.h>
 13 #include <linux/fs.h>
 14 #include <linux/smp.h>
 15 #include <linux/ptrace.h>
 16 #include <linux/string.h>
 17 #include <linux/syscalls.h>
 18 #include <linux/file.h>
 19 #include <linux/utsname.h>
 20 #include <linux/unistd.h>
 21 #include <linux/sem.h>
 22 #include <linux/msg.h>
 23 #include <linux/shm.h>
 24 #include <linux/compiler.h>
 25 #include <linux/ipc.h>
 26 #include <linux/uaccess.h>
 27 #include <linux/slab.h>
 28 #include <linux/elf.h>
 29 
 30 #include <asm/asm.h>
 31 #include <asm/asm-eva.h>
 32 #include <asm/branch.h>
 33 #include <asm/cachectl.h>
 34 #include <asm/cacheflush.h>
 35 #include <asm/asm-offsets.h>
 36 #include <asm/signal.h>
 37 #include <asm/sim.h>
 38 #include <asm/shmparam.h>
 39 #include <asm/sysmips.h>
 40 #include <asm/uaccess.h>
 41 #include <asm/switch_to.h>
 42 
 43 /*
 44  * For historic reasons the pipe(2) syscall on MIPS has an unusual calling
 45  * convention.  It returns results in registers $v0 / $v1 which means there
 46  * is no need for it to do verify the validity of a userspace pointer
 47  * argument.  Historically that used to be expensive in Linux.  These days
 48  * the performance advantage is negligible.
 49  */
 50 asmlinkage int sysm_pipe(void)
 51 {
 52         int fd[2];
 53         int error = do_pipe_flags(fd, 0);
 54         if (error)
 55                 return error;
 56         current_pt_regs()->regs[3] = fd[1];
 57         return fd[0];
 58 }
 59 
 60 SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
 61         unsigned long, prot, unsigned long, flags, unsigned long,
 62         fd, off_t, offset)
 63 {
 64         unsigned long result;
 65 
 66         result = -EINVAL;
 67         if (offset & ~PAGE_MASK)
 68                 goto out;
 69 
 70         result = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 71 
 72 out:
 73         return result;
 74 }
 75 
 76 SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
 77         unsigned long, prot, unsigned long, flags, unsigned long, fd,
 78         unsigned long, pgoff)
 79 {
 80         if (pgoff & (~PAGE_MASK >> 12))
 81                 return -EINVAL;
 82 
 83         return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT-12));
 84 }
 85 
 86 save_static_function(sys_fork);
 87 save_static_function(sys_clone);
 88 
 89 SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 90 {
 91         struct thread_info *ti = task_thread_info(current);
 92 
 93         ti->tp_value = addr;
 94         if (cpu_has_userlocal)
 95                 write_c0_userlocal(addr);
 96 
 97         return 0;
 98 }
 99 
100 static inline int mips_atomic_set(unsigned long addr, unsigned long new)
101 {
102         unsigned long old, tmp;
103         struct pt_regs *regs;
104         unsigned int err;
105 
106         if (unlikely(addr & 3))
107                 return -EINVAL;
108 
109         if (unlikely(!access_ok(VERIFY_WRITE, addr, 4)))
110                 return -EINVAL;
111 
112         if (cpu_has_llsc && R10000_LLSC_WAR) {
113                 __asm__ __volatile__ (
114                 "       .set    arch=r4000                              \n"
115                 "       li      %[err], 0                               \n"
116                 "1:     ll      %[old], (%[addr])                       \n"
117                 "       move    %[tmp], %[new]                          \n"
118                 "2:     sc      %[tmp], (%[addr])                       \n"
119                 "       beqzl   %[tmp], 1b                              \n"
120                 "3:                                                     \n"
121                 "       .section .fixup,\"ax\"                          \n"
122                 "4:     li      %[err], %[efault]                       \n"
123                 "       j       3b                                      \n"
124                 "       .previous                                       \n"
125                 "       .section __ex_table,\"a\"                       \n"
126                 "       "STR(PTR)"      1b, 4b                          \n"
127                 "       "STR(PTR)"      2b, 4b                          \n"
128                 "       .previous                                       \n"
129                 "       .set    mips0                                   \n"
130                 : [old] "=&r" (old),
131                   [err] "=&r" (err),
132                   [tmp] "=&r" (tmp)
133                 : [addr] "r" (addr),
134                   [new] "r" (new),
135                   [efault] "i" (-EFAULT)
136                 : "memory");
137         } else if (cpu_has_llsc) {
138                 __asm__ __volatile__ (
139                 "       .set    arch=r4000                              \n"
140                 "       li      %[err], 0                               \n"
141                 "1:                                                     \n"
142                 user_ll("%[old]", "(%[addr])")
143                 "       move    %[tmp], %[new]                          \n"
144                 "2:                                                     \n"
145                 user_sc("%[tmp]", "(%[addr])")
146                 "       beqz    %[tmp], 4f                              \n"
147                 "3:                                                     \n"
148                 "       .subsection 2                                   \n"
149                 "4:     b       1b                                      \n"
150                 "       .previous                                       \n"
151                 "                                                       \n"
152                 "       .section .fixup,\"ax\"                          \n"
153                 "5:     li      %[err], %[efault]                       \n"
154                 "       j       3b                                      \n"
155                 "       .previous                                       \n"
156                 "       .section __ex_table,\"a\"                       \n"
157                 "       "STR(PTR)"      1b, 5b                          \n"
158                 "       "STR(PTR)"      2b, 5b                          \n"
159                 "       .previous                                       \n"
160                 "       .set    mips0                                   \n"
161                 : [old] "=&r" (old),
162                   [err] "=&r" (err),
163                   [tmp] "=&r" (tmp)
164                 : [addr] "r" (addr),
165                   [new] "r" (new),
166                   [efault] "i" (-EFAULT)
167                 : "memory");
168         } else {
169                 do {
170                         preempt_disable();
171                         ll_bit = 1;
172                         ll_task = current;
173                         preempt_enable();
174 
175                         err = __get_user(old, (unsigned int *) addr);
176                         err |= __put_user(new, (unsigned int *) addr);
177                         if (err)
178                                 break;
179                         rmb();
180                 } while (!ll_bit);
181         }
182 
183         if (unlikely(err))
184                 return err;
185 
186         regs = current_pt_regs();
187         regs->regs[2] = old;
188         regs->regs[7] = 0;      /* No error */
189 
190         /*
191          * Don't let your children do this ...
192          */
193         __asm__ __volatile__(
194         "       move    $29, %0                                         \n"
195         "       j       syscall_exit                                    \n"
196         : /* no outputs */
197         : "r" (regs));
198 
199         /* unreached.  Honestly.  */
200         unreachable();
201 }
202 
203 /*
204  * mips_atomic_set() normally returns directly via syscall_exit potentially
205  * clobbering static registers, so be sure to preserve them.
206  */
207 save_static_function(sys_sysmips);
208 
209 SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
210 {
211         switch (cmd) {
212         case MIPS_ATOMIC_SET:
213                 return mips_atomic_set(arg1, arg2);
214 
215         case MIPS_FIXADE:
216                 if (arg1 & ~3)
217                         return -EINVAL;
218 
219                 if (arg1 & 1)
220                         set_thread_flag(TIF_FIXADE);
221                 else
222                         clear_thread_flag(TIF_FIXADE);
223                 if (arg1 & 2)
224                         set_thread_flag(TIF_LOGADE);
225                 else
226                         clear_thread_flag(TIF_LOGADE);
227 
228                 return 0;
229 
230         case FLUSH_CACHE:
231                 __flush_cache_all();
232                 return 0;
233         }
234 
235         return -EINVAL;
236 }
237 
238 /*
239  * No implemented yet ...
240  */
241 SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
242 {
243         return -ENOSYS;
244 }
245 
246 /*
247  * If we ever come here the user sp is bad.  Zap the process right away.
248  * Due to the bad stack signaling wouldn't work.
249  */
250 asmlinkage void bad_stack(void)
251 {
252         do_exit(SIGSEGV);
253 }
254 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp