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