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