Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / arch / mips64 / kernel / scall_o32.S
blob97cdd13762d66e33848ba43733c8880adcf95678
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 - 2000, 2001 by Ralf Baechle
7  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8  * Copyright (C) 2001 MIPS Technologies, Inc.
9  *
10  * Hairy, the userspace application uses a different argument passing
11  * convention than the kernel, so we have to translate things from o32
12  * to ABI64 calling convention.  64-bit syscalls are also processed
13  * here for now.
14  */
15 #include <asm/asm.h>
16 #include <linux/errno.h>
17 #include <asm/mipsregs.h>
18 #include <asm/regdef.h>
19 #include <asm/stackframe.h>
20 #include <asm/unistd.h>
21 #include <asm/sysmips.h>
23         .align  5
24 NESTED(handle_sys, PT_SIZE, sp)
25         .set    noat
26         SAVE_SOME
27         STI
28         .set    at
29         ld      t1, PT_EPC(sp)          # skip syscall on return
31         subu    t0, v0, __NR_O32_Linux  # check syscall number
32         sltiu   t0, t0, __NR_O32_Linux_syscalls + 1
33         daddiu  t1, 4                   # skip to next instruction
34         beqz    t0, not_o32_scall
35         sd      t1, PT_EPC(sp)
36 #if 0
37  SAVE_ALL
38  move a1, v0
39  PRINT("Scall %ld\n")
40  RESTORE_ALL
41 #endif
43         sll     a0, a0, 0
44         sll     a1, a1, 0
45         sll     a2, a2, 0
46         sll     a3, a3, 0
48         /* XXX Put both in one cacheline, should save a bit. */
49         dsll    t0, v0, 3               # offset into table
50         ld      t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
51         lbu     t3, (sys_narg_table - __NR_O32_Linux)(v0)
53         subu    t0, t3, 5               # 5 or more arguments?
54         sd      a3, PT_R26(sp)          # save a3 for syscall restarting
55         bgez    t0, stackargs
57 stack_done:
58                 LONG_L  t0, TI_FLAGS($28)
59                                                 # syscall tracing enabled?
60                 bnez    t0, trace_a_syscall
62                 jalr    t2                      # Do The Real Thing (TM)
64                 li      t0, -EMAXERRNO - 1      # error?
65                 sltu    t0, t0, v0
66                 sd      t0, PT_R7(sp)           # set error flag
67                 beqz    t0, 1f
69                 negu    v0                      # error
70                 sd      v0, PT_R0(sp)           # flag for syscall restarting
71 1:              sd      v0, PT_R2(sp)           # result
73 FEXPORT(o32_syscall_exit)
74                 mfc0    t0, CP0_STATUS          # make need_resched and
75                 ori     t0, t0, 1               # signals dont change between
76                 xori    t0, t0, 1               # sampling and return
77                 mtc0    t0, CP0_STATUS
78                 SSNOP; SSNOP; SSNOP
80                 LONG_L  a2, TI_FLAGS($28)
81                 bnez    a2, o32_syscall_exit_work
83 restore_all:    RESTORE_SOME
84                 RESTORE_SP
85                 eret
87 o32_syscall_exit_work:
88                 SAVE_STATIC
89                 j       syscall_exit_work
91 /* ------------------------------------------------------------------------ */
93 trace_a_syscall:
94         SAVE_STATIC
95         sd      a4, PT_R8(sp)
96         sd      a5, PT_R9(sp)
97         sd      a6, PT_R10(sp)
98         sd      a7, PT_R11(sp)
100         sd      t2,PT_R1(sp)
101         jal     do_syscall_trace
102         ld      t2,PT_R1(sp)
104         ld      a0, PT_R4(sp)           # Restore argument registers
105         ld      a1, PT_R5(sp)
106         ld      a2, PT_R6(sp)
107         ld      a3, PT_R7(sp)
108         ld      a4, PT_R8(sp)
109         ld      a5, PT_R9(sp)
111         jalr    t2
113         li      t0, -EMAXERRNO - 1      # error?
114         sltu    t0, t0, v0
115         sd      t0, PT_R7(sp)           # set error flag
116         beqz    t0, 1f
118         negu    v0                      # error
119         sd      v0, PT_R0(sp)           # set flag for syscall restarting
120 1:      sd      v0, PT_R2(sp)           # result
122         j       syscall_exit
124 /* ------------------------------------------------------------------------ */
126         /*
127          * More than four arguments.  Try to deal with it by copying the
128          * stack arguments from the user stack to the kernel stack.
129          * This Sucks (TM).
130          */
131 stackargs:
132         ld      t0, PT_R29(sp)          # get old user stack pointer
133         subu    t3, 4
134         sll     t1, t3, 2               # stack valid?
136         addu    t1, t0                  # end address
137         or      t0, t1
138         bltz    t0, bad_stack           # -> sp is bad
140         ld      t0, PT_R29(sp)          # get old user stack pointer
141         PTR_LA  t1, 3f                  # copy 1 to 2 arguments
142         sll     t3, t3, 2
143         subu    t1, t3
144         jr      t1
146         /* Ok, copy the args from the luser stack to the kernel stack */
147         .set    push
148         .set    noreorder
149         .set    nomacro
150 1:      lw      a5, 20(t0)              # argument #6 from usp
151 2:      lw      a4, 16(t0)              # argument #5 from usp
152 3:      .set    pop
154         j       stack_done              # go back
156         .section __ex_table,"a"
157         PTR     1b, bad_stack
158         PTR     2b, bad_stack
159         .previous
161         /*
162          * The stackpointer for a call with more than 4 arguments is bad.
163          */
164 bad_stack:
165                 negu    v0                      # error
166                 sd      v0, PT_R0(sp)
167                 sd      v0, PT_R2(sp)
168                 li      t0, 1                   # set error flag
169                 sd      t0, PT_R7(sp)
170                 j       o32_syscall_exit
172 not_o32_scall:
173                 /*
174                  * This is not an o32 compatibility syscall, pass it on
175                  * to the 64-bit syscall handlers.
176                  */
177 #ifdef CONFIG_MIPS32_N32
178                 j       handle_sysn32
179 #else
180                 j       handle_sys64
181 #endif
183 illegal_syscall:
184                 /* This also isn't a 64-bit syscall, throw an error.  */
185                 li      v0, ENOSYS              # error
186                 sd      v0, PT_R2(sp)
187                 li      t0, 1                   # set error flag
188                 sd      t0, PT_R7(sp)
189                 j       o32_syscall_exit
190                 END(handle_sys)
192 LEAF(mips_atomic_set)
193                 andi    v0, a1, 3               # must be word aligned
194                 bnez    v0, bad_alignment
196                 ld      v1, TI_ADDR_LIMIT($28)  # in legal address range?
197                 daddiu  a0, a1, 4
198                 or      a0, a0, a1
199                 and     a0, a0, v1
200                 bnez    a0, bad_address
202                 /* Ok, this is the ll/sc case.  World is sane :-)  */
203 1:              ll      v0, (a1)
204                 move    a0, a2
205 2:              sc      a0, (a1)
206                 beqz    a0, 1b
208                 .section __ex_table,"a"
209                 PTR     1b, bad_stack
210                 PTR     2b, bad_stack
211                 .previous
213 1:              sd      v0, PT_R2(sp)           # result
215                 /* Success, so skip usual error handling garbage.  */
216                 LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
217                 bltz    t0, 1f
218                 b       o32_syscall_exit
220 1:              SAVE_STATIC
221                 jal     do_syscall_trace
222                 li      a3, 0                   # success
223                 j       syscall_exit
225 bad_address:
226                 li      v0, -EFAULT
227                 jr      ra
229 bad_alignment:
230                 li      v0, -EINVAL
231                 jr      ra
232                 END(mips_atomic_set)
234 LEAF(sys32_sysmips)
235                 beq     a0, MIPS_ATOMIC_SET, mips_atomic_set
236                 j       sys_sysmips
237                 END(sys32_sysmips)
239 LEAF(sys32_syscall)
240         ld      t0, PT_R29(sp)          # user sp
242         sltu    v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1
243         beqz    v0, enosys
245         dsll    v0, a0, 3
246         dla     v1, sys32_syscall
247         ld      t2, (sys_call_table - (__NR_O32_Linux * 8))(v0)
248         lbu     t3, (sys_narg_table - __NR_O32_Linux)(a0)
250         li      v0, -EINVAL
251         beq     t2, v1, out             # do not recurse
253         beqz    t2, enosys              # null function pointer?
255         andi    v0, t0, 0x3             # unaligned stack pointer?
256         bnez    v0, sigsegv
258         daddiu  v0, t0, 16              # v0 = usp + 16
259         daddu   t1, v0, 12              # 3 32-bit arguments
260         ld      v1, TI_ADDR_LIMIT($28)
261         or      v0, v0, t1
262         and     v1, v1, v0
263         bnez    v1, efault
265         move    a0, a1                  # shift argument registers
266         move    a1, a2
267         move    a2, a3
269 1:      lw      a3, 16(t0)
270 2:      lw      t3, 20(t0)
271 3:      lw      t1, 24(t0)
273         .section __ex_table,"a"
274         PTR     1b, efault
275         PTR     2b, efault
276         PTR     3b, efault
277         .previous
279         sw      t3, 16(sp)              # put into new stackframe
280         sw      t1, 20(sp)
282         bnez    t1, 1f                  # zero arguments?
283         daddu   a0, sp, 32              # then pass sp in a0
286         sw      t3, 16(sp)
287         sw      v1, 20(sp)
288         jr      t2
289         /* Unreached */
291 enosys: li      v0, -ENOSYS
292         b       out
294 sigsegv:
295         li      a0, _SIGSEGV
296         move    a1, $28
297         jal     force_sig
298         /* Fall through */
300 efault: li      v0, -EFAULT
302 out:    jr      ra
303         END(sys32_syscall)
305         .macro  syscalltable
306         sys     sys32_syscall   0                       /* 4000 */
307         sys     sys_exit        1
308         sys     sys_fork        0
309         sys     sys_read        3
310         sys     sys_write       3
311         sys     sys_open        3                       /* 4005 */
312         sys     sys_close       1
313         sys     sys_waitpid     3
314         sys     sys_creat       2
315         sys     sys_link        2
316         sys     sys_unlink      1                       /* 4010 */
317         sys     sys32_execve    0
318         sys     sys_chdir       1
319         sys     sys_time        1
320         sys     sys_mknod       3
321         sys     sys_chmod       2                       /* 4015 */
322         sys     sys_lchown      3
323         sys     sys_ni_syscall  0
324         sys     sys_ni_syscall  0                       /* was sys_stat */
325         sys     sys_lseek       3
326         sys     sys_getpid      0                       /* 4020 */
327         sys     sys_mount       5
328         sys     sys_oldumount   1
329         sys     sys_setuid      1
330         sys     sys_getuid      0
331         sys     sys_stime       1                       /* 4025 */
332         sys     sys32_ptrace    4
333         sys     sys_alarm       1
334         sys     sys_ni_syscall  0                       /* was sys_fstat */
335         sys     sys_pause       0
336         sys     sys32_utime     2                       /* 4030 */
337         sys     sys_ni_syscall  0
338         sys     sys_ni_syscall  0
339         sys     sys_access      2
340         sys     sys_nice        1
341         sys     sys_ni_syscall  0                       /* 4035 */
342         sys     sys_sync        0
343         sys     sys_kill        2
344         sys     sys_rename      2
345         sys     sys_mkdir       2
346         sys     sys_rmdir       1                       /* 4040 */
347         sys     sys_dup         1
348         sys     sys_pipe        0
349         sys     sys32_times     1
350         sys     sys_ni_syscall  0
351         sys     sys_brk         1                       /* 4045 */
352         sys     sys_setgid      1
353         sys     sys_getgid      0
354         sys     sys_ni_syscall  0       /* was signal   2 */
355         sys     sys_geteuid     0
356         sys     sys_getegid     0                       /* 4050 */
357         sys     sys_acct        0
358         sys     sys_umount      2
359         sys     sys_ni_syscall  0
360         sys     sys32_ioctl     3
361         sys     sys32_fcntl     3                       /* 4055 */
362         sys     sys_ni_syscall  2
363         sys     sys_setpgid     2
364         sys     sys_ni_syscall, 0
365         sys     sys_ni_syscall  0       /* was sys_olduname  */
366         sys     sys_umask       1                       /* 4060 */
367         sys     sys_chroot      1
368         sys     sys_ustat       2
369         sys     sys_dup2        2
370         sys     sys_getppid     0
371         sys     sys_getpgrp     0                       /* 4065 */
372         sys     sys_setsid      0
373         sys     sys32_sigaction 3
374         sys     sys_sgetmask    0
375         sys     sys_ssetmask    1
376         sys     sys_setreuid    2                       /* 4070 */
377         sys     sys_setregid    2
378         sys     sys32_sigsuspend        0
379         sys     sys32_sigpending        1
380         sys     sys_sethostname 2
381         sys     sys32_setrlimit 2                       /* 4075 */
382         sys     sys32_getrlimit 2
383         sys     sys32_getrusage 2
384         sys     sys32_gettimeofday 2
385         sys     sys32_settimeofday 2
386         sys     sys_getgroups   2                       /* 4080 */
387         sys     sys_setgroups   2
388         sys     sys_ni_syscall  0                       /* old_select */
389         sys     sys_symlink     2
390         sys     sys_ni_syscall  0                       /* was sys_lstat */
391         sys     sys_readlink    3                       /* 4085 */
392         sys     sys_uselib      1
393         sys     sys_swapon      2
394         sys     sys_reboot      3
395         sys     sys32_readdir   3
396         sys     sys_mmap        6                       /* 4090 */
397         sys     sys_munmap      2
398         sys     sys_truncate    2
399         sys     sys_ftruncate   2
400         sys     sys_fchmod      2
401         sys     sys_fchown      3                       /* 4095 */
402         sys     sys_getpriority 2
403         sys     sys_setpriority 3
404         sys     sys_ni_syscall  0
405         sys     sys32_statfs    2
406         sys     sys32_fstatfs   2                       /* 4100 */
407         sys     sys_ni_syscall  0       /* sys_ioperm */
408         sys     sys_socketcall  2
409         sys     sys_syslog      3
410         sys     sys32_setitimer 3
411         sys     sys32_getitimer 2                       /* 4105 */
412         sys     sys32_newstat   2
413         sys     sys32_newlstat  2
414         sys     sys32_newfstat  2
415         sys     sys_ni_syscall  0       /* was sys_uname */
416         sys     sys_ni_syscall  0       /* sys_ioperm  *//* 4110 */
417         sys     sys_vhangup     0
418         sys     sys_ni_syscall  0       /* was sys_idle  */
419         sys     sys_ni_syscall  0       /* sys_vm86 */
420         sys     sys32_wait4     4
421         sys     sys_swapoff     1                       /* 4115 */
422         sys     sys32_sysinfo   1
423         sys     sys32_ipc               6
424         sys     sys_fsync       1
425         sys     sys32_sigreturn 0
426         sys     sys_clone       0                       /* 4120 */
427         sys     sys_setdomainname 2
428         sys     sys32_newuname  1
429         sys     sys_ni_syscall  0       /* sys_modify_ldt */
430         sys     sys32_adjtimex  1
431         sys     sys_mprotect    3                       /* 4125 */
432         sys     sys32_sigprocmask       3
433         sys     sys_ni_syscall  0                       /* was creat_module */
434         sys     sys_init_module 5
435         sys     sys_delete_module 1
436         sys     sys_ni_syscall  0               /* 4130, get_kernel_syms */
437         sys     sys_quotactl    0
438         sys     sys_getpgid     1
439         sys     sys_fchdir      1
440         sys     sys_bdflush     2
441         sys     sys_sysfs       3                       /* 4135 */
442         sys     sys32_personality       1
443         sys     sys_ni_syscall  0 /* for afs_syscall */
444         sys     sys_setfsuid    1
445         sys     sys_setfsgid    1
446         sys     sys32_llseek    5                       /* 4140 */
447         sys     sys32_getdents  3
448         sys     sys32_select    5
449         sys     sys_flock       2
450         sys     sys_msync       3
451         sys     sys32_readv     3                       /* 4145 */
452         sys     sys32_writev    3
453         sys     sys_cacheflush  3
454         sys     sys_cachectl    3
455         sys     sys32_sysmips   4
456         sys     sys_ni_syscall  0                       /* 4150 */
457         sys     sys_getsid      1
458         sys     sys_fdatasync   0
459         sys     sys32_sysctl    1
460         sys     sys_mlock       2
461         sys     sys_munlock     2                       /* 4155 */
462         sys     sys_mlockall    1
463         sys     sys_munlockall  0
464         sys     sys_sched_setparam 2
465         sys     sys_sched_getparam 2
466         sys     sys_sched_setscheduler 3                /* 4160 */
467         sys     sys_sched_getscheduler 1
468         sys     sys_sched_yield 0
469         sys     sys_sched_get_priority_max 1
470         sys     sys_sched_get_priority_min 1
471         sys     sys32_sched_rr_get_interval 2           /* 4165 */
472         sys     sys32_nanosleep 2
473         sys     sys_mremap      4
474         sys     sys_accept      3
475         sys     sys_bind        3
476         sys     sys_connect     3                       /* 4170 */
477         sys     sys_getpeername 3
478         sys     sys_getsockname 3
479         sys     sys_getsockopt  5
480         sys     sys_listen      2
481         sys     sys_recv        4                       /* 4175 */
482         sys     sys_recvfrom    6
483         sys     sys32_recvmsg   3
484         sys     sys_send        4
485         sys     sys32_sendmsg   3
486         sys     sys_sendto      6                       /* 4180 */
487         sys     sys32_setsockopt        5
488         sys     sys_shutdown    2
489         sys     sys_socket      3
490         sys     sys_socketpair  4
491         sys     sys_setresuid   3                       /* 4185 */
492         sys     sys_getresuid   3
493         sys     sys_ni_syscall  0                       /* was query_module */
494         sys     sys_poll        3
495         sys     sys_nfsservctl  3
496         sys     sys_setresgid   3                       /* 4190 */
497         sys     sys_getresgid   3
498         sys     sys_prctl       5
499         sys     sys32_rt_sigreturn 0
500         sys     sys32_rt_sigaction 4
501         sys     sys32_rt_sigprocmask 4                  /* 4195 */
502         sys     sys32_rt_sigpending 2
503         sys     sys32_rt_sigtimedwait 4
504         sys     sys32_rt_sigqueueinfo 3
505         sys     sys32_rt_sigsuspend 0
506         sys     sys32_pread     6                       /* 4200 */
507         sys     sys32_pwrite    6
508         sys     sys_chown       3
509         sys     sys_getcwd      2
510         sys     sys_capget      2
511         sys     sys_capset      2                       /* 4205 */
512         sys     sys32_sigaltstack       0
513         sys     sys32_sendfile  4
514         sys     sys_ni_syscall  0
515         sys     sys_ni_syscall  0
516         sys     sys32_mmap2     6                       /* 4210 */
517         sys     sys32_truncate64        4
518         sys     sys32_ftruncate64       4
519         sys     sys_newstat     2
520         sys     sys_newlstat    2
521         sys     sys_newfstat    2                       /* 4215 */
522         sys     sys_pivot_root  2
523         sys     sys_mincore     3
524         sys     sys_madvise     3
525         sys     sys_getdents64  3
526         sys     sys32_fcntl64   3                       /* 4220 */
527         sys     sys_ni_syscall  0
528         sys     sys_gettid      0
529         sys     sys32_readahead 5
530         sys     sys_setxattr    5
531         sys     sys_lsetxattr   5                       /* 4225 */
532         sys     sys_fsetxattr   5
533         sys     sys_getxattr    4
534         sys     sys_lgetxattr   4
535         sys     sys_fgetxattr   4
536         sys     sys_listxattr   3                       /* 4230 */
537         sys     sys_llistxattr  3
538         sys     sys_flistxattr  3
539         sys     sys_removexattr 2
540         sys     sys_lremovexattr        2
541         sys     sys_fremovexattr        2               /* 4235 */
542         sys     sys_tkill               2
543         sys     sys_sendfile64          5
544         sys     sys_futex               2
545         sys     sys32_sched_setaffinity 3
546         sys     sys32_sched_getaffinity 3               /* 4240 */
547         sys     sys_io_setup            2
548         sys     sys_io_destroy          1
549         sys     sys_io_getevents        5
550         sys     sys_io_submit           3
551         sys     sys_io_cancel           3               /* 4245 */
552         sys     sys_exit_group          1
553         sys     sys_lookup_dcookie      3
554         sys     sys_epoll_create        1
555         sys     sys_epoll_ctl           4
556         sys     sys_epoll_wait          3               /* 4250 */
557         sys     sys_remap_file_pages    5
558         sys     sys_set_tid_address     1
559         .endm
561         .macro  sys function, nargs
562         PTR     \function
563         .endm
565         .align  3
566 sys_call_table:
567         syscalltable
569         .macro  sys function, nargs
570         .byte   \nargs
571         .endm
573 sys_narg_table:
574         syscalltable