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
6 * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
7 * Copyright (C) 2001 MIPS Technologies, Inc.
8 * Copyright (C) 2004 Thiemo Seufer
10 #include <linux/config.h>
11 #include <linux/errno.h>
13 #include <asm/asmmacro.h>
14 #include <asm/mipsregs.h>
15 #include <asm/regdef.h>
16 #include <asm/stackframe.h>
17 #include <asm/isadep.h>
18 #include <asm/sysmips.h>
19 #include <asm/thread_info.h>
20 #include <asm/unistd.h>
22 #include <asm/asm-offsets.h>
24 /* Highest syscall used of any syscall flavour */
25 #define MAX_SYSCALL_NO __NR_O32_Linux + __NR_O32_Linux_syscalls
28 NESTED(handle_sys, PT_SIZE, sp)
34 lw t1, PT_EPC(sp) # skip syscall on return
36 #if defined(CONFIG_BINFMT_IRIX)
37 sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
39 subu v0, v0, __NR_O32_Linux # check syscall number
40 sltiu t0, v0, __NR_O32_Linux_syscalls + 1
42 addiu t1, 4 # skip to next instruction
44 beqz t0, illegal_syscall
49 lw t2, (t1) # syscall routine
50 lw t3, 4(t1) # >= 0 if we need stack arguments
51 beqz t2, illegal_syscall
53 sw a3, PT_R26(sp) # save a3 for syscall restarting
57 lw t0, TI_FLAGS($28) # syscall tracing enabled?
58 li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
60 bnez t0, syscall_trace_entry # -> yes
62 jalr t2 # Do The Real Thing (TM)
64 li t0, -EMAXERRNO - 1 # error?
66 sw t0, PT_R7(sp) # set error flag
70 sw v0, PT_R0(sp) # set flag for syscall
72 1: sw v0, PT_R2(sp) # result
75 local_irq_disable # make sure need_resched and
76 # signals dont change between
78 lw a2, TI_FLAGS($28) # current->work
79 li t0, _TIF_ALLWORK_MASK
81 bnez t0, o32_syscall_exit_work
85 o32_syscall_exit_work:
86 j syscall_exit_work_partial
88 /* ------------------------------------------------------------------------ */
99 lw a0, PT_R4(sp) # Restore argument registers
105 li t0, -EMAXERRNO - 1 # error?
107 sw t0, PT_R7(sp) # set error flag
111 sw v0, PT_R0(sp) # set flag for syscall
113 1: sw v0, PT_R2(sp) # result
117 /* ------------------------------------------------------------------------ */
120 * More than four arguments. Try to deal with it by copying the
121 * stack arguments from the user stack to the kernel stack.
125 lw t0, PT_R29(sp) # get old user stack pointer
128 * We intentionally keep the kernel stack a little below the top of
129 * userspace so we don't have to do a slower byte accurate check here.
131 lw t5, TI_ADDR_LIMIT($28)
134 bltz t5, bad_stack # -> sp is bad
136 /* Ok, copy the args from the luser stack to the kernel stack.
137 * t3 is the precomputed number of instruction bytes needed to
138 * load or store arguments 6-8.
141 la t1, 5f # load up to 3 arguments
143 1: lw t5, 16(t0) # argument #5 from usp
150 2: lw t8, 28(t0) # argument #8 from usp
151 3: lw t7, 24(t0) # argument #7 from usp
152 4: lw t6, 20(t0) # argument #6 from usp
154 sw t5, 16(sp) # argument #5 to ksp
156 sw t8, 28(sp) # argument #8 to ksp
157 sw t7, 24(sp) # argument #7 to ksp
158 sw t6, 20(sp) # argument #6 to ksp
159 6: j stack_done # go back
163 .section __ex_table,"a"
171 * The stackpointer for a call with more than 4 arguments is bad.
172 * We probably should handle this case a bit more drastic.
178 li t0, 1 # set error flag
183 * The system call does not exist in this kernel
186 li v0, -ENOSYS # error
188 li t0, 1 # set error flag
193 LEAF(mips_atomic_set)
194 andi v0, a1, 3 # must be word aligned
195 bnez v0, bad_alignment
197 lw v1, TI_ADDR_LIMIT($28) # in legal address range?
203 #ifdef CONFIG_CPU_HAS_LLSC
204 /* Ok, this is the ll/sc case. World is sane :-) */
214 .section __ex_table,"a"
231 * At this point the page should be readable and writable unless
232 * there was no more memory available.
237 .section __ex_table,"a"
243 sw zero, PT_R7(sp) # success
244 sw v0, PT_R2(sp) # result
246 j o32_syscall_exit # continue like a normal syscall
248 no_mem: li v0, -ENOMEM
261 beq a0, MIPS_ATOMIC_SET, mips_atomic_set
266 #if defined(CONFIG_BINFMT_IRIX)
267 sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number
269 subu t0, a0, __NR_O32_Linux # check syscall number
270 sltiu v0, t0, __NR_O32_Linux_syscalls + 1
275 lw t2, sys_call_table(t1) # syscall routine
277 #if defined(CONFIG_BINFMT_IRIX)
278 li v1, 4000 # nr of sys_syscall
280 li v1, 4000 - __NR_O32_Linux # index of sys_syscall
282 beq t0, v1, einval # do not recurse
284 /* Some syscalls like execve get their arguments from struct pt_regs
285 and claim zero arguments in the syscall table. Thus we have to
286 assume the worst case and shuffle around all potential arguments.
287 If you want performance, don't use indirect syscalls. */
289 move a0, a1 # shift argument registers
299 sw a0, PT_R4(sp) # .. and push back a0 - a3, some
300 sw a1, PT_R5(sp) # syscalls expect them there
303 sw a3, PT_R26(sp) # update a3 for syscall restarting
307 einval: li v0, -EINVAL
311 .macro fifty ptr, nargs, from=1, to=50
314 fifty \ptr,\nargs,"(\from+1)",\to
318 .macro mille ptr, nargs, from=1, to=20
321 mille \ptr,\nargs,"(\from+1)",\to
326 #if defined(CONFIG_BINFMT_IRIX)
327 mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */
328 mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */
329 mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */
330 mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */
333 sys sys_syscall 8 /* 4000 */
338 sys sys_open 3 /* 4005 */
343 sys sys_unlink 1 /* 4010 */
348 sys sys_chmod 2 /* 4015 */
351 sys sys_ni_syscall 0 /* was sys_stat */
353 sys sys_getpid 0 /* 4020 */
358 sys sys_stime 1 /* 4025 */
361 sys sys_ni_syscall 0 /* was sys_fstat */
363 sys sys_utime 2 /* 4030 */
368 sys sys_ni_syscall 0 /* 4035 */
373 sys sys_rmdir 1 /* 4040 */
378 sys sys_brk 1 /* 4045 */
381 sys sys_ni_syscall 0 /* was signal(2) */
383 sys sys_getegid 0 /* 4050 */
388 sys sys_fcntl 3 /* 4055 */
393 sys sys_umask 1 /* 4060 */
398 sys sys_getpgrp 0 /* 4065 */
403 sys sys_setreuid 2 /* 4070 */
407 sys sys_sethostname 2
408 sys sys_setrlimit 2 /* 4075 */
411 sys sys_gettimeofday 2
412 sys sys_settimeofday 2
413 sys sys_getgroups 2 /* 4080 */
415 sys sys_ni_syscall 0 /* old_select */
417 sys sys_ni_syscall 0 /* was sys_lstat */
418 sys sys_readlink 3 /* 4085 */
423 sys old_mmap 6 /* 4090 */
428 sys sys_fchown 3 /* 4095 */
429 sys sys_getpriority 2
430 sys sys_setpriority 3
433 sys sys_fstatfs 2 /* 4100 */
434 sys sys_ni_syscall 0 /* was ioperm(2) */
438 sys sys_getitimer 2 /* 4105 */
443 sys sys_ni_syscall 0 /* 4110 was iopl(2) */
445 sys sys_ni_syscall 0 /* was sys_idle() */
446 sys sys_ni_syscall 0 /* was sys_vm86 */
448 sys sys_swapoff 1 /* 4115 */
453 sys sys_clone 0 /* 4120 */
454 sys sys_setdomainname 2
456 sys sys_ni_syscall 0 /* sys_modify_ldt */
458 sys sys_mprotect 3 /* 4125 */
459 sys sys_sigprocmask 3
460 sys sys_ni_syscall 0 /* was create_module */
461 sys sys_init_module 5
462 sys sys_delete_module 1
463 sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
468 sys sys_sysfs 3 /* 4135 */
469 sys sys_personality 1
470 sys sys_ni_syscall 0 /* for afs_syscall */
473 sys sys_llseek 5 /* 4140 */
478 sys sys_readv 3 /* 4145 */
483 sys sys_ni_syscall 0 /* 4150 */
488 sys sys_munlock 2 /* 4155 */
491 sys sys_sched_setparam 2
492 sys sys_sched_getparam 2
493 sys sys_sched_setscheduler 3 /* 4160 */
494 sys sys_sched_getscheduler 1
495 sys sys_sched_yield 0
496 sys sys_sched_get_priority_max 1
497 sys sys_sched_get_priority_min 1
498 sys sys_sched_rr_get_interval 2 /* 4165 */
503 sys sys_connect 3 /* 4170 */
504 sys sys_getpeername 3
505 sys sys_getsockname 3
508 sys sys_recv 4 /* 4175 */
513 sys sys_sendto 6 /* 4180 */
518 sys sys_setresuid 3 /* 4185 */
520 sys sys_ni_syscall 0 /* was sys_query_module */
523 sys sys_setresgid 3 /* 4190 */
526 sys sys_rt_sigreturn 0
527 sys sys_rt_sigaction 4
528 sys sys_rt_sigprocmask 4 /* 4195 */
529 sys sys_rt_sigpending 2
530 sys sys_rt_sigtimedwait 4
531 sys sys_rt_sigqueueinfo 3
532 sys sys_rt_sigsuspend 0
533 sys sys_pread64 6 /* 4200 */
538 sys sys_capset 2 /* 4205 */
539 sys sys_sigaltstack 0
543 sys sys_mmap2 6 /* 4210 */
545 sys sys_ftruncate64 4
548 sys sys_fstat64 2 /* 4215 */
553 sys sys_fcntl64 3 /* 4220 */
558 sys sys_lsetxattr 5 /* 4225 */
563 sys sys_listxattr 3 /* 4230 */
566 sys sys_removexattr 2
567 sys sys_lremovexattr 2
568 sys sys_fremovexattr 2 /* 4235 */
572 sys sys_sched_setaffinity 3
573 sys sys_sched_getaffinity 3 /* 4240 */
576 sys sys_io_getevents 5
578 sys sys_io_cancel 3 /* 4245 */
580 sys sys_lookup_dcookie 4
581 sys sys_epoll_create 1
583 sys sys_epoll_wait 3 /* 4250 */
584 sys sys_remap_file_pages 5
585 sys sys_set_tid_address 1
586 sys sys_restart_syscall 0
587 sys sys_fadvise64_64 7
588 sys sys_statfs64 3 /* 4255 */
590 sys sys_timer_create 3
591 sys sys_timer_settime 4
592 sys sys_timer_gettime 2
593 sys sys_timer_getoverrun 1 /* 4260 */
594 sys sys_timer_delete 1
595 sys sys_clock_settime 2
596 sys sys_clock_gettime 2
597 sys sys_clock_getres 2
598 sys sys_clock_nanosleep 4 /* 4265 */
602 sys sys_ni_syscall 0 /* sys_get_mempolicy */
603 sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
606 sys sys_mq_timedsend 5
607 sys sys_mq_timedreceive 5
608 sys sys_mq_notify 2 /* 4275 */
609 sys sys_mq_getsetattr 3
610 sys sys_ni_syscall 0 /* sys_vserver */
612 sys sys_ni_syscall 0 /* available, was setaltroot */
613 sys sys_add_key 5 /* 4280 */
614 sys sys_request_key 4
616 sys sys_set_thread_area 1
617 sys sys_inotify_init 0
618 sys sys_inotify_add_watch 3 /* 4285 */
619 sys sys_inotify_rm_watch 2
620 sys sys_migrate_pages 4
623 sys sys_mknodat 4 /* 4290 */
628 sys sys_renameat 4 /* 4295 */
633 sys sys_faccessat 3 /* 4300 */
639 /* We pre-compute the number of _instruction_ bytes needed to
640 load or store the arguments 6-8. Negative values are ignored. */
642 .macro sys function, nargs
644 LONG (\nargs << 2) - (5 << 2)
648 .type sys_call_table,@object
649 EXPORT(sys_call_table)
651 .size sys_call_table, . - sys_call_table