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