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