blob: 2258fc69e14d39373b925fc5af12dfbb705cbd19 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
7 * Copyright (C) 2001 MIPS Technologies, Inc.
8 * Copyright (C) 2004 Thiemo Seufer
9 */
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <asm/asm.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>
21#include <asm/war.h>
Sam Ravnborg048eb582005-09-09 22:32:31 +020022#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
24/* Highest syscall used of any syscall flavour */
25#define MAX_SYSCALL_NO __NR_O32_Linux + __NR_O32_Linux_syscalls
26
27 .align 5
28NESTED(handle_sys, PT_SIZE, sp)
29 .set noat
30 SAVE_SOME
31 STI
32 .set at
33
34 lw t1, PT_EPC(sp) # skip syscall on return
35
36#if defined(CONFIG_BINFMT_IRIX)
37 sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
38#else
39 subu v0, v0, __NR_O32_Linux # check syscall number
40 sltiu t0, v0, __NR_O32_Linux_syscalls + 1
41#endif
42 addiu t1, 4 # skip to next instruction
43 sw t1, PT_EPC(sp)
44 beqz t0, illegal_syscall
45
46 sll t0, v0, 3
47 la t1, sys_call_table
48 addu t1, t0
49 lw t2, (t1) # syscall routine
50 lw t3, 4(t1) # >= 0 if we need stack arguments
51 beqz t2, illegal_syscall
52
53 sw a3, PT_R26(sp) # save a3 for syscall restarting
54 bgez t3, stackargs
55
56stack_done:
57 lw t0, TI_FLAGS($28) # syscall tracing enabled?
58 li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
59 and t0, t1
60 bnez t0, syscall_trace_entry # -> yes
61
62 jalr t2 # Do The Real Thing (TM)
63
64 li t0, -EMAXERRNO - 1 # error?
65 sltu t0, t0, v0
66 sw t0, PT_R7(sp) # set error flag
67 beqz t0, 1f
68
69 negu v0 # error
70 sw v0, PT_R0(sp) # set flag for syscall
71 # restarting
721: sw v0, PT_R2(sp) # result
73
74o32_syscall_exit:
75 local_irq_disable # make sure need_resched and
76 # signals dont change between
77 # sampling and return
78 lw a2, TI_FLAGS($28) # current->work
79 li t0, _TIF_ALLWORK_MASK
80 and t0, a2
81 bnez t0, o32_syscall_exit_work
82
83 j restore_partial
84
85o32_syscall_exit_work:
86 j syscall_exit_work_partial
87
88/* ------------------------------------------------------------------------ */
89
90syscall_trace_entry:
91 SAVE_STATIC
92 move s0, t2
93 move a0, sp
94 li a1, 0
95 jal do_syscall_trace
96
97 lw a0, PT_R4(sp) # Restore argument registers
98 lw a1, PT_R5(sp)
99 lw a2, PT_R6(sp)
100 lw a3, PT_R7(sp)
101 jalr s0
102
103 li t0, -EMAXERRNO - 1 # error?
104 sltu t0, t0, v0
105 sw t0, PT_R7(sp) # set error flag
106 beqz t0, 1f
107
108 negu v0 # error
109 sw v0, PT_R0(sp) # set flag for syscall
110 # restarting
1111: sw v0, PT_R2(sp) # result
112
113 j syscall_exit
114
115/* ------------------------------------------------------------------------ */
116
117 /*
118 * More than four arguments. Try to deal with it by copying the
119 * stack arguments from the user stack to the kernel stack.
120 * This Sucks (TM).
121 */
122stackargs:
123 lw t0, PT_R29(sp) # get old user stack pointer
124
125 /*
126 * We intentionally keep the kernel stack a little below the top of
127 * userspace so we don't have to do a slower byte accurate check here.
128 */
129 lw t5, TI_ADDR_LIMIT($28)
130 addu t4, t0, 32
131 and t5, t4
132 bltz t5, bad_stack # -> sp is bad
133
134 /* Ok, copy the args from the luser stack to the kernel stack.
135 * t3 is the precomputed number of instruction bytes needed to
136 * load or store arguments 6-8.
137 */
138
139 la t1, 5f # load up to 3 arguments
140 subu t1, t3
1411: lw t5, 16(t0) # argument #5 from usp
142 .set push
143 .set noreorder
144 .set nomacro
145 jr t1
146 addiu t1, 6f - 5f
147
1482: lw t8, 28(t0) # argument #8 from usp
1493: lw t7, 24(t0) # argument #7 from usp
1504: lw t6, 20(t0) # argument #6 from usp
1515: jr t1
152 sw t5, 16(sp) # argument #5 to ksp
153
154 sw t8, 28(sp) # argument #8 to ksp
155 sw t7, 24(sp) # argument #7 to ksp
156 sw t6, 20(sp) # argument #6 to ksp
1576: j stack_done # go back
158 nop
159 .set pop
160
161 .section __ex_table,"a"
162 PTR 1b,bad_stack
163 PTR 2b,bad_stack
164 PTR 3b,bad_stack
165 PTR 4b,bad_stack
166 .previous
167
168 /*
169 * The stackpointer for a call with more than 4 arguments is bad.
170 * We probably should handle this case a bit more drastic.
171 */
172bad_stack:
173 negu v0 # error
174 sw v0, PT_R0(sp)
175 sw v0, PT_R2(sp)
176 li t0, 1 # set error flag
177 sw t0, PT_R7(sp)
178 j o32_syscall_exit
179
180 /*
181 * The system call does not exist in this kernel
182 */
183illegal_syscall:
184 li v0, -ENOSYS # error
185 sw v0, PT_R2(sp)
186 li t0, 1 # set error flag
187 sw t0, PT_R7(sp)
188 j o32_syscall_exit
189 END(handle_sys)
190
191 LEAF(mips_atomic_set)
192 andi v0, a1, 3 # must be word aligned
193 bnez v0, bad_alignment
194
195 lw v1, TI_ADDR_LIMIT($28) # in legal address range?
196 addiu a0, a1, 4
197 or a0, a0, a1
198 and a0, a0, v1
199 bltz a0, bad_address
200
201#ifdef CONFIG_CPU_HAS_LLSC
202 /* Ok, this is the ll/sc case. World is sane :-) */
2031: ll v0, (a1)
204 move a0, a2
2052: sc a0, (a1)
206#if R10000_LLSC_WAR
207 beqzl a0, 1b
208#else
209 beqz a0, 1b
210#endif
211
212 .section __ex_table,"a"
213 PTR 1b, bad_stack
214 PTR 2b, bad_stack
215 .previous
216#else
217 sw a1, 16(sp)
218 sw a2, 20(sp)
219
220 move a0, sp
221 move a2, a1
222 li a1, 1
223 jal do_page_fault
224
225 lw a1, 16(sp)
226 lw a2, 20(sp)
227
228 /*
229 * At this point the page should be readable and writable unless
230 * there was no more memory available.
231 */
2321: lw v0, (a1)
2332: sw a2, (a1)
234
235 .section __ex_table,"a"
236 PTR 1b, no_mem
237 PTR 2b, no_mem
238 .previous
239#endif
240
241 sw zero, PT_R7(sp) # success
242 sw v0, PT_R2(sp) # result
243
Ralf Baechleedcb98d2005-11-29 13:01:01 +0000244 j o32_syscall_exit # continue like a normal syscall
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246no_mem: li v0, -ENOMEM
247 jr ra
248
249bad_address:
250 li v0, -EFAULT
251 jr ra
252
253bad_alignment:
254 li v0, -EINVAL
255 jr ra
256 END(mips_atomic_set)
257
258 LEAF(sys_sysmips)
259 beq a0, MIPS_ATOMIC_SET, mips_atomic_set
260 j _sys_sysmips
261 END(sys_sysmips)
262
263 LEAF(sys_syscall)
264#if defined(CONFIG_BINFMT_IRIX)
265 sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number
266#else
267 subu t0, a0, __NR_O32_Linux # check syscall number
268 sltiu v0, t0, __NR_O32_Linux_syscalls + 1
269#endif
270 sll t1, t0, 3
271 beqz v0, einval
272
273 lw t2, sys_call_table(t1) # syscall routine
274
275#if defined(CONFIG_BINFMT_IRIX)
276 li v1, 4000 # nr of sys_syscall
277#else
278 li v1, 4000 - __NR_O32_Linux # index of sys_syscall
279#endif
280 beq t0, v1, einval # do not recurse
281
282 /* Some syscalls like execve get their arguments from struct pt_regs
283 and claim zero arguments in the syscall table. Thus we have to
284 assume the worst case and shuffle around all potential arguments.
285 If you want performance, don't use indirect syscalls. */
286
287 move a0, a1 # shift argument registers
288 move a1, a2
289 move a2, a3
290 lw a3, 16(sp)
291 lw t4, 20(sp)
292 lw t5, 24(sp)
293 lw t6, 28(sp)
294 sw t4, 16(sp)
295 sw t5, 20(sp)
296 sw t6, 24(sp)
297 sw a0, PT_R4(sp) # .. and push back a0 - a3, some
298 sw a1, PT_R5(sp) # syscalls expect them there
299 sw a2, PT_R6(sp)
300 sw a3, PT_R7(sp)
301 sw a3, PT_R26(sp) # update a3 for syscall restarting
302 jr t2
303 /* Unreached */
304
305einval: li v0, -EINVAL
306 jr ra
307 END(sys_syscall)
308
309 .macro fifty ptr, nargs, from=1, to=50
310 sys \ptr \nargs
311 .if \to-\from
312 fifty \ptr,\nargs,"(\from+1)",\to
313 .endif
314 .endm
315
316 .macro mille ptr, nargs, from=1, to=20
317 fifty \ptr,\nargs
318 .if \to-\from
319 mille \ptr,\nargs,"(\from+1)",\to
320 .endif
321 .endm
322
323 .macro syscalltable
324#if defined(CONFIG_BINFMT_IRIX)
325 mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */
326 mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */
327 mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */
328 mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */
329#endif
330
331 sys sys_syscall 8 /* 4000 */
332 sys sys_exit 1
333 sys sys_fork 0
334 sys sys_read 3
335 sys sys_write 3
336 sys sys_open 3 /* 4005 */
337 sys sys_close 1
338 sys sys_waitpid 3
339 sys sys_creat 2
340 sys sys_link 2
341 sys sys_unlink 1 /* 4010 */
342 sys sys_execve 0
343 sys sys_chdir 1
344 sys sys_time 1
345 sys sys_mknod 3
346 sys sys_chmod 2 /* 4015 */
347 sys sys_lchown 3
348 sys sys_ni_syscall 0
349 sys sys_ni_syscall 0 /* was sys_stat */
350 sys sys_lseek 3
351 sys sys_getpid 0 /* 4020 */
352 sys sys_mount 5
353 sys sys_oldumount 1
354 sys sys_setuid 1
355 sys sys_getuid 0
356 sys sys_stime 1 /* 4025 */
357 sys sys_ptrace 4
358 sys sys_alarm 1
359 sys sys_ni_syscall 0 /* was sys_fstat */
360 sys sys_pause 0
361 sys sys_utime 2 /* 4030 */
362 sys sys_ni_syscall 0
363 sys sys_ni_syscall 0
364 sys sys_access 2
365 sys sys_nice 1
366 sys sys_ni_syscall 0 /* 4035 */
367 sys sys_sync 0
368 sys sys_kill 2
369 sys sys_rename 2
370 sys sys_mkdir 2
371 sys sys_rmdir 1 /* 4040 */
372 sys sys_dup 1
373 sys sys_pipe 0
374 sys sys_times 1
375 sys sys_ni_syscall 0
376 sys sys_brk 1 /* 4045 */
377 sys sys_setgid 1
378 sys sys_getgid 0
379 sys sys_ni_syscall 0 /* was signal(2) */
380 sys sys_geteuid 0
381 sys sys_getegid 0 /* 4050 */
382 sys sys_acct 1
383 sys sys_umount 2
384 sys sys_ni_syscall 0
385 sys sys_ioctl 3
386 sys sys_fcntl 3 /* 4055 */
387 sys sys_ni_syscall 2
388 sys sys_setpgid 2
389 sys sys_ni_syscall 0
390 sys sys_olduname 1
391 sys sys_umask 1 /* 4060 */
392 sys sys_chroot 1
393 sys sys_ustat 2
394 sys sys_dup2 2
395 sys sys_getppid 0
396 sys sys_getpgrp 0 /* 4065 */
397 sys sys_setsid 0
398 sys sys_sigaction 3
399 sys sys_sgetmask 0
400 sys sys_ssetmask 1
401 sys sys_setreuid 2 /* 4070 */
402 sys sys_setregid 2
403 sys sys_sigsuspend 0
404 sys sys_sigpending 1
405 sys sys_sethostname 2
406 sys sys_setrlimit 2 /* 4075 */
407 sys sys_getrlimit 2
408 sys sys_getrusage 2
409 sys sys_gettimeofday 2
410 sys sys_settimeofday 2
411 sys sys_getgroups 2 /* 4080 */
412 sys sys_setgroups 2
413 sys sys_ni_syscall 0 /* old_select */
414 sys sys_symlink 2
415 sys sys_ni_syscall 0 /* was sys_lstat */
416 sys sys_readlink 3 /* 4085 */
417 sys sys_uselib 1
418 sys sys_swapon 2
419 sys sys_reboot 3
420 sys old_readdir 3
421 sys old_mmap 6 /* 4090 */
422 sys sys_munmap 2
423 sys sys_truncate 2
424 sys sys_ftruncate 2
425 sys sys_fchmod 2
426 sys sys_fchown 3 /* 4095 */
427 sys sys_getpriority 2
428 sys sys_setpriority 3
429 sys sys_ni_syscall 0
430 sys sys_statfs 2
431 sys sys_fstatfs 2 /* 4100 */
432 sys sys_ni_syscall 0 /* was ioperm(2) */
433 sys sys_socketcall 2
434 sys sys_syslog 3
435 sys sys_setitimer 3
436 sys sys_getitimer 2 /* 4105 */
437 sys sys_newstat 2
438 sys sys_newlstat 2
439 sys sys_newfstat 2
440 sys sys_uname 1
441 sys sys_ni_syscall 0 /* 4110 was iopl(2) */
442 sys sys_vhangup 0
443 sys sys_ni_syscall 0 /* was sys_idle() */
444 sys sys_ni_syscall 0 /* was sys_vm86 */
445 sys sys_wait4 4
446 sys sys_swapoff 1 /* 4115 */
447 sys sys_sysinfo 1
448 sys sys_ipc 6
449 sys sys_fsync 1
450 sys sys_sigreturn 0
451 sys sys_clone 0 /* 4120 */
452 sys sys_setdomainname 2
453 sys sys_newuname 1
454 sys sys_ni_syscall 0 /* sys_modify_ldt */
455 sys sys_adjtimex 1
456 sys sys_mprotect 3 /* 4125 */
457 sys sys_sigprocmask 3
458 sys sys_ni_syscall 0 /* was create_module */
459 sys sys_init_module 5
460 sys sys_delete_module 1
461 sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
462 sys sys_quotactl 4
463 sys sys_getpgid 1
464 sys sys_fchdir 1
465 sys sys_bdflush 2
466 sys sys_sysfs 3 /* 4135 */
467 sys sys_personality 1
468 sys sys_ni_syscall 0 /* for afs_syscall */
469 sys sys_setfsuid 1
470 sys sys_setfsgid 1
471 sys sys_llseek 5 /* 4140 */
472 sys sys_getdents 3
473 sys sys_select 5
474 sys sys_flock 2
475 sys sys_msync 3
476 sys sys_readv 3 /* 4145 */
477 sys sys_writev 3
478 sys sys_cacheflush 3
479 sys sys_cachectl 3
480 sys sys_sysmips 4
481 sys sys_ni_syscall 0 /* 4150 */
482 sys sys_getsid 1
483 sys sys_fdatasync 1
484 sys sys_sysctl 1
485 sys sys_mlock 2
486 sys sys_munlock 2 /* 4155 */
487 sys sys_mlockall 1
488 sys sys_munlockall 0
489 sys sys_sched_setparam 2
490 sys sys_sched_getparam 2
491 sys sys_sched_setscheduler 3 /* 4160 */
492 sys sys_sched_getscheduler 1
493 sys sys_sched_yield 0
494 sys sys_sched_get_priority_max 1
495 sys sys_sched_get_priority_min 1
496 sys sys_sched_rr_get_interval 2 /* 4165 */
497 sys sys_nanosleep, 2
498 sys sys_mremap, 4
499 sys sys_accept 3
500 sys sys_bind 3
501 sys sys_connect 3 /* 4170 */
502 sys sys_getpeername 3
503 sys sys_getsockname 3
504 sys sys_getsockopt 5
505 sys sys_listen 2
506 sys sys_recv 4 /* 4175 */
507 sys sys_recvfrom 6
508 sys sys_recvmsg 3
509 sys sys_send 4
510 sys sys_sendmsg 3
511 sys sys_sendto 6 /* 4180 */
512 sys sys_setsockopt 5
513 sys sys_shutdown 2
514 sys sys_socket 3
515 sys sys_socketpair 4
516 sys sys_setresuid 3 /* 4185 */
517 sys sys_getresuid 3
518 sys sys_ni_syscall 0 /* was sys_query_module */
519 sys sys_poll 3
520 sys sys_nfsservctl 3
521 sys sys_setresgid 3 /* 4190 */
522 sys sys_getresgid 3
523 sys sys_prctl 5
524 sys sys_rt_sigreturn 0
525 sys sys_rt_sigaction 4
526 sys sys_rt_sigprocmask 4 /* 4195 */
527 sys sys_rt_sigpending 2
528 sys sys_rt_sigtimedwait 4
529 sys sys_rt_sigqueueinfo 3
530 sys sys_rt_sigsuspend 0
531 sys sys_pread64 6 /* 4200 */
532 sys sys_pwrite64 6
533 sys sys_chown 3
534 sys sys_getcwd 2
535 sys sys_capget 2
536 sys sys_capset 2 /* 4205 */
537 sys sys_sigaltstack 0
538 sys sys_sendfile 4
539 sys sys_ni_syscall 0
540 sys sys_ni_syscall 0
541 sys sys_mmap2 6 /* 4210 */
542 sys sys_truncate64 4
543 sys sys_ftruncate64 4
544 sys sys_stat64 2
545 sys sys_lstat64 2
546 sys sys_fstat64 2 /* 4215 */
547 sys sys_pivot_root 2
548 sys sys_mincore 3
549 sys sys_madvise 3
550 sys sys_getdents64 3
551 sys sys_fcntl64 3 /* 4220 */
552 sys sys_ni_syscall 0
553 sys sys_gettid 0
554 sys sys_readahead 5
555 sys sys_setxattr 5
556 sys sys_lsetxattr 5 /* 4225 */
557 sys sys_fsetxattr 5
558 sys sys_getxattr 4
559 sys sys_lgetxattr 4
560 sys sys_fgetxattr 4
561 sys sys_listxattr 3 /* 4230 */
562 sys sys_llistxattr 3
563 sys sys_flistxattr 3
564 sys sys_removexattr 2
565 sys sys_lremovexattr 2
566 sys sys_fremovexattr 2 /* 4235 */
567 sys sys_tkill 2
568 sys sys_sendfile64 5
Thiemo Seufer90a67b52005-03-13 00:07:00 +0000569 sys sys_futex 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 sys sys_sched_setaffinity 3
571 sys sys_sched_getaffinity 3 /* 4240 */
572 sys sys_io_setup 2
573 sys sys_io_destroy 1
574 sys sys_io_getevents 5
575 sys sys_io_submit 3
576 sys sys_io_cancel 3 /* 4245 */
577 sys sys_exit_group 1
Ralf Baechle0d507d62005-10-18 12:48:31 +0100578 sys sys_lookup_dcookie 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 sys sys_epoll_create 1
580 sys sys_epoll_ctl 4
581 sys sys_epoll_wait 3 /* 4250 */
582 sys sys_remap_file_pages 5
583 sys sys_set_tid_address 1
584 sys sys_restart_syscall 0
585 sys sys_fadvise64_64 7
586 sys sys_statfs64 3 /* 4255 */
587 sys sys_fstatfs64 2
588 sys sys_timer_create 3
589 sys sys_timer_settime 4
590 sys sys_timer_gettime 2
591 sys sys_timer_getoverrun 1 /* 4260 */
592 sys sys_timer_delete 1
593 sys sys_clock_settime 2
594 sys sys_clock_gettime 2
595 sys sys_clock_getres 2
596 sys sys_clock_nanosleep 4 /* 4265 */
597 sys sys_tgkill 3
598 sys sys_utimes 2
599 sys sys_mbind 4
600 sys sys_ni_syscall 0 /* sys_get_mempolicy */
601 sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
602 sys sys_mq_open 4
603 sys sys_mq_unlink 1
604 sys sys_mq_timedsend 5
605 sys sys_mq_timedreceive 5
606 sys sys_mq_notify 2 /* 4275 */
607 sys sys_mq_getsetattr 3
608 sys sys_ni_syscall 0 /* sys_vserver */
Ralf Baechlea19050f2005-02-16 21:19:59 +0000609 sys sys_waitid 5
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 sys sys_ni_syscall 0 /* available, was setaltroot */
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000611 sys sys_add_key 5 /* 4280 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 sys sys_request_key 4
613 sys sys_keyctl 5
Ralf Baechle3c370262005-04-13 17:43:59 +0000614 sys sys_set_thread_area 1
Ralf Baechle7db36c82005-07-13 11:48:45 +0000615 sys sys_inotify_init 0
616 sys sys_inotify_add_watch 3 /* 4285 */
617 sys sys_inotify_rm_watch 2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 .endm
619
620 /* We pre-compute the number of _instruction_ bytes needed to
621 load or store the arguments 6-8. Negative values are ignored. */
622
623 .macro sys function, nargs
624 PTR \function
625 LONG (\nargs << 2) - (5 << 2)
626 .endm
627
628 .align 3
629 .type sys_call_table,@object
630EXPORT(sys_call_table)
631 syscalltable
632 .size sys_call_table, . - sys_call_table