aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/scall32-o32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/scall32-o32.S')
-rw-r--r--arch/mips/kernel/scall32-o32.S641
1 files changed, 641 insertions, 0 deletions
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
new file mode 100644
index 000000000000..344f2e29eb61
--- /dev/null
+++ b/arch/mips/kernel/scall32-o32.S
@@ -0,0 +1,641 @@
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, 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>
22#include <asm/offset.h>
23
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
244 /* Success, so skip usual error handling garbage. */
245 lw a2, TI_FLAGS($28) # syscall tracing enabled?
246 li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
247 and t0, a2, t0
248 bnez t0, 1f
249
250 j o32_syscall_exit
251
2521: SAVE_STATIC
253 move a0, sp
254 li a1, 1
255 jal do_syscall_trace
256 j syscall_exit
257
258no_mem: li v0, -ENOMEM
259 jr ra
260
261bad_address:
262 li v0, -EFAULT
263 jr ra
264
265bad_alignment:
266 li v0, -EINVAL
267 jr ra
268 END(mips_atomic_set)
269
270 LEAF(sys_sysmips)
271 beq a0, MIPS_ATOMIC_SET, mips_atomic_set
272 j _sys_sysmips
273 END(sys_sysmips)
274
275 LEAF(sys_syscall)
276#if defined(CONFIG_BINFMT_IRIX)
277 sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number
278#else
279 subu t0, a0, __NR_O32_Linux # check syscall number
280 sltiu v0, t0, __NR_O32_Linux_syscalls + 1
281#endif
282 sll t1, t0, 3
283 beqz v0, einval
284
285 lw t2, sys_call_table(t1) # syscall routine
286
287#if defined(CONFIG_BINFMT_IRIX)
288 li v1, 4000 # nr of sys_syscall
289#else
290 li v1, 4000 - __NR_O32_Linux # index of sys_syscall
291#endif
292 beq t0, v1, einval # do not recurse
293
294 /* Some syscalls like execve get their arguments from struct pt_regs
295 and claim zero arguments in the syscall table. Thus we have to
296 assume the worst case and shuffle around all potential arguments.
297 If you want performance, don't use indirect syscalls. */
298
299 move a0, a1 # shift argument registers
300 move a1, a2
301 move a2, a3
302 lw a3, 16(sp)
303 lw t4, 20(sp)
304 lw t5, 24(sp)
305 lw t6, 28(sp)
306 sw t4, 16(sp)
307 sw t5, 20(sp)
308 sw t6, 24(sp)
309 sw a0, PT_R4(sp) # .. and push back a0 - a3, some
310 sw a1, PT_R5(sp) # syscalls expect them there
311 sw a2, PT_R6(sp)
312 sw a3, PT_R7(sp)
313 sw a3, PT_R26(sp) # update a3 for syscall restarting
314 jr t2
315 /* Unreached */
316
317einval: li v0, -EINVAL
318 jr ra
319 END(sys_syscall)
320
321 .macro fifty ptr, nargs, from=1, to=50
322 sys \ptr \nargs
323 .if \to-\from
324 fifty \ptr,\nargs,"(\from+1)",\to
325 .endif
326 .endm
327
328 .macro mille ptr, nargs, from=1, to=20
329 fifty \ptr,\nargs
330 .if \to-\from
331 mille \ptr,\nargs,"(\from+1)",\to
332 .endif
333 .endm
334
335 .macro syscalltable
336#if defined(CONFIG_BINFMT_IRIX)
337 mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */
338 mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */
339 mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */
340 mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */
341#endif
342
343 sys sys_syscall 8 /* 4000 */
344 sys sys_exit 1
345 sys sys_fork 0
346 sys sys_read 3
347 sys sys_write 3
348 sys sys_open 3 /* 4005 */
349 sys sys_close 1
350 sys sys_waitpid 3
351 sys sys_creat 2
352 sys sys_link 2
353 sys sys_unlink 1 /* 4010 */
354 sys sys_execve 0
355 sys sys_chdir 1
356 sys sys_time 1
357 sys sys_mknod 3
358 sys sys_chmod 2 /* 4015 */
359 sys sys_lchown 3
360 sys sys_ni_syscall 0
361 sys sys_ni_syscall 0 /* was sys_stat */
362 sys sys_lseek 3
363 sys sys_getpid 0 /* 4020 */
364 sys sys_mount 5
365 sys sys_oldumount 1
366 sys sys_setuid 1
367 sys sys_getuid 0
368 sys sys_stime 1 /* 4025 */
369 sys sys_ptrace 4
370 sys sys_alarm 1
371 sys sys_ni_syscall 0 /* was sys_fstat */
372 sys sys_pause 0
373 sys sys_utime 2 /* 4030 */
374 sys sys_ni_syscall 0
375 sys sys_ni_syscall 0
376 sys sys_access 2
377 sys sys_nice 1
378 sys sys_ni_syscall 0 /* 4035 */
379 sys sys_sync 0
380 sys sys_kill 2
381 sys sys_rename 2
382 sys sys_mkdir 2
383 sys sys_rmdir 1 /* 4040 */
384 sys sys_dup 1
385 sys sys_pipe 0
386 sys sys_times 1
387 sys sys_ni_syscall 0
388 sys sys_brk 1 /* 4045 */
389 sys sys_setgid 1
390 sys sys_getgid 0
391 sys sys_ni_syscall 0 /* was signal(2) */
392 sys sys_geteuid 0
393 sys sys_getegid 0 /* 4050 */
394 sys sys_acct 1
395 sys sys_umount 2
396 sys sys_ni_syscall 0
397 sys sys_ioctl 3
398 sys sys_fcntl 3 /* 4055 */
399 sys sys_ni_syscall 2
400 sys sys_setpgid 2
401 sys sys_ni_syscall 0
402 sys sys_olduname 1
403 sys sys_umask 1 /* 4060 */
404 sys sys_chroot 1
405 sys sys_ustat 2
406 sys sys_dup2 2
407 sys sys_getppid 0
408 sys sys_getpgrp 0 /* 4065 */
409 sys sys_setsid 0
410 sys sys_sigaction 3
411 sys sys_sgetmask 0
412 sys sys_ssetmask 1
413 sys sys_setreuid 2 /* 4070 */
414 sys sys_setregid 2
415 sys sys_sigsuspend 0
416 sys sys_sigpending 1
417 sys sys_sethostname 2
418 sys sys_setrlimit 2 /* 4075 */
419 sys sys_getrlimit 2
420 sys sys_getrusage 2
421 sys sys_gettimeofday 2
422 sys sys_settimeofday 2
423 sys sys_getgroups 2 /* 4080 */
424 sys sys_setgroups 2
425 sys sys_ni_syscall 0 /* old_select */
426 sys sys_symlink 2
427 sys sys_ni_syscall 0 /* was sys_lstat */
428 sys sys_readlink 3 /* 4085 */
429 sys sys_uselib 1
430 sys sys_swapon 2
431 sys sys_reboot 3
432 sys old_readdir 3
433 sys old_mmap 6 /* 4090 */
434 sys sys_munmap 2
435 sys sys_truncate 2
436 sys sys_ftruncate 2
437 sys sys_fchmod 2
438 sys sys_fchown 3 /* 4095 */
439 sys sys_getpriority 2
440 sys sys_setpriority 3
441 sys sys_ni_syscall 0
442 sys sys_statfs 2
443 sys sys_fstatfs 2 /* 4100 */
444 sys sys_ni_syscall 0 /* was ioperm(2) */
445 sys sys_socketcall 2
446 sys sys_syslog 3
447 sys sys_setitimer 3
448 sys sys_getitimer 2 /* 4105 */
449 sys sys_newstat 2
450 sys sys_newlstat 2
451 sys sys_newfstat 2
452 sys sys_uname 1
453 sys sys_ni_syscall 0 /* 4110 was iopl(2) */
454 sys sys_vhangup 0
455 sys sys_ni_syscall 0 /* was sys_idle() */
456 sys sys_ni_syscall 0 /* was sys_vm86 */
457 sys sys_wait4 4
458 sys sys_swapoff 1 /* 4115 */
459 sys sys_sysinfo 1
460 sys sys_ipc 6
461 sys sys_fsync 1
462 sys sys_sigreturn 0
463 sys sys_clone 0 /* 4120 */
464 sys sys_setdomainname 2
465 sys sys_newuname 1
466 sys sys_ni_syscall 0 /* sys_modify_ldt */
467 sys sys_adjtimex 1
468 sys sys_mprotect 3 /* 4125 */
469 sys sys_sigprocmask 3
470 sys sys_ni_syscall 0 /* was create_module */
471 sys sys_init_module 5
472 sys sys_delete_module 1
473 sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
474 sys sys_quotactl 4
475 sys sys_getpgid 1
476 sys sys_fchdir 1
477 sys sys_bdflush 2
478 sys sys_sysfs 3 /* 4135 */
479 sys sys_personality 1
480 sys sys_ni_syscall 0 /* for afs_syscall */
481 sys sys_setfsuid 1
482 sys sys_setfsgid 1
483 sys sys_llseek 5 /* 4140 */
484 sys sys_getdents 3
485 sys sys_select 5
486 sys sys_flock 2
487 sys sys_msync 3
488 sys sys_readv 3 /* 4145 */
489 sys sys_writev 3
490 sys sys_cacheflush 3
491 sys sys_cachectl 3
492 sys sys_sysmips 4
493 sys sys_ni_syscall 0 /* 4150 */
494 sys sys_getsid 1
495 sys sys_fdatasync 1
496 sys sys_sysctl 1
497 sys sys_mlock 2
498 sys sys_munlock 2 /* 4155 */
499 sys sys_mlockall 1
500 sys sys_munlockall 0
501 sys sys_sched_setparam 2
502 sys sys_sched_getparam 2
503 sys sys_sched_setscheduler 3 /* 4160 */
504 sys sys_sched_getscheduler 1
505 sys sys_sched_yield 0
506 sys sys_sched_get_priority_max 1
507 sys sys_sched_get_priority_min 1
508 sys sys_sched_rr_get_interval 2 /* 4165 */
509 sys sys_nanosleep, 2
510 sys sys_mremap, 4
511 sys sys_accept 3
512 sys sys_bind 3
513 sys sys_connect 3 /* 4170 */
514 sys sys_getpeername 3
515 sys sys_getsockname 3
516 sys sys_getsockopt 5
517 sys sys_listen 2
518 sys sys_recv 4 /* 4175 */
519 sys sys_recvfrom 6
520 sys sys_recvmsg 3
521 sys sys_send 4
522 sys sys_sendmsg 3
523 sys sys_sendto 6 /* 4180 */
524 sys sys_setsockopt 5
525 sys sys_shutdown 2
526 sys sys_socket 3
527 sys sys_socketpair 4
528 sys sys_setresuid 3 /* 4185 */
529 sys sys_getresuid 3
530 sys sys_ni_syscall 0 /* was sys_query_module */
531 sys sys_poll 3
532 sys sys_nfsservctl 3
533 sys sys_setresgid 3 /* 4190 */
534 sys sys_getresgid 3
535 sys sys_prctl 5
536 sys sys_rt_sigreturn 0
537 sys sys_rt_sigaction 4
538 sys sys_rt_sigprocmask 4 /* 4195 */
539 sys sys_rt_sigpending 2
540 sys sys_rt_sigtimedwait 4
541 sys sys_rt_sigqueueinfo 3
542 sys sys_rt_sigsuspend 0
543 sys sys_pread64 6 /* 4200 */
544 sys sys_pwrite64 6
545 sys sys_chown 3
546 sys sys_getcwd 2
547 sys sys_capget 2
548 sys sys_capset 2 /* 4205 */
549 sys sys_sigaltstack 0
550 sys sys_sendfile 4
551 sys sys_ni_syscall 0
552 sys sys_ni_syscall 0
553 sys sys_mmap2 6 /* 4210 */
554 sys sys_truncate64 4
555 sys sys_ftruncate64 4
556 sys sys_stat64 2
557 sys sys_lstat64 2
558 sys sys_fstat64 2 /* 4215 */
559 sys sys_pivot_root 2
560 sys sys_mincore 3
561 sys sys_madvise 3
562 sys sys_getdents64 3
563 sys sys_fcntl64 3 /* 4220 */
564 sys sys_ni_syscall 0
565 sys sys_gettid 0
566 sys sys_readahead 5
567 sys sys_setxattr 5
568 sys sys_lsetxattr 5 /* 4225 */
569 sys sys_fsetxattr 5
570 sys sys_getxattr 4
571 sys sys_lgetxattr 4
572 sys sys_fgetxattr 4
573 sys sys_listxattr 3 /* 4230 */
574 sys sys_llistxattr 3
575 sys sys_flistxattr 3
576 sys sys_removexattr 2
577 sys sys_lremovexattr 2
578 sys sys_fremovexattr 2 /* 4235 */
579 sys sys_tkill 2
580 sys sys_sendfile64 5
581 sys sys_futex 2
582 sys sys_sched_setaffinity 3
583 sys sys_sched_getaffinity 3 /* 4240 */
584 sys sys_io_setup 2
585 sys sys_io_destroy 1
586 sys sys_io_getevents 5
587 sys sys_io_submit 3
588 sys sys_io_cancel 3 /* 4245 */
589 sys sys_exit_group 1
590 sys sys_lookup_dcookie 3
591 sys sys_epoll_create 1
592 sys sys_epoll_ctl 4
593 sys sys_epoll_wait 3 /* 4250 */
594 sys sys_remap_file_pages 5
595 sys sys_set_tid_address 1
596 sys sys_restart_syscall 0
597 sys sys_fadvise64_64 7
598 sys sys_statfs64 3 /* 4255 */
599 sys sys_fstatfs64 2
600 sys sys_timer_create 3
601 sys sys_timer_settime 4
602 sys sys_timer_gettime 2
603 sys sys_timer_getoverrun 1 /* 4260 */
604 sys sys_timer_delete 1
605 sys sys_clock_settime 2
606 sys sys_clock_gettime 2
607 sys sys_clock_getres 2
608 sys sys_clock_nanosleep 4 /* 4265 */
609 sys sys_tgkill 3
610 sys sys_utimes 2
611 sys sys_mbind 4
612 sys sys_ni_syscall 0 /* sys_get_mempolicy */
613 sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
614 sys sys_mq_open 4
615 sys sys_mq_unlink 1
616 sys sys_mq_timedsend 5
617 sys sys_mq_timedreceive 5
618 sys sys_mq_notify 2 /* 4275 */
619 sys sys_mq_getsetattr 3
620 sys sys_ni_syscall 0 /* sys_vserver */
621 sys sys_waitid 4
622 sys sys_ni_syscall 0 /* available, was setaltroot */
623 sys sys_add_key 5
624 sys sys_request_key 4
625 sys sys_keyctl 5
626
627 .endm
628
629 /* We pre-compute the number of _instruction_ bytes needed to
630 load or store the arguments 6-8. Negative values are ignored. */
631
632 .macro sys function, nargs
633 PTR \function
634 LONG (\nargs << 2) - (5 << 2)
635 .endm
636
637 .align 3
638 .type sys_call_table,@object
639EXPORT(sys_call_table)
640 syscalltable
641 .size sys_call_table, . - sys_call_table