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