X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Fscall32-o32.S;h=344f2e29eb616816da5cf0de6ed95a219f6d6958;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=24eab2f9d7dd53b867d059b706ddefe05e5ea049;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 24eab2f9d..344f2e29e 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -5,6 +5,7 @@ * * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle * Copyright (C) 2001 MIPS Technologies, Inc. + * Copyright (C) 2004 Thiemo Seufer */ #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include /* Highest syscall used of any syscall flavour */ @@ -31,26 +33,30 @@ NESTED(handle_sys, PT_SIZE, sp) lw t1, PT_EPC(sp) # skip syscall on return +#if defined(CONFIG_BINFMT_IRIX) sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number +#else + subu v0, v0, __NR_O32_Linux # check syscall number + sltiu t0, v0, __NR_O32_Linux_syscalls + 1 +#endif addiu t1, 4 # skip to next instruction sw t1, PT_EPC(sp) beqz t0, illegal_syscall - /* XXX Put both in one cacheline, should save a bit. */ - sll t0, v0, 2 - lw t2, sys_call_table(t0) # syscall routine - lbu t3, sys_narg_table(v0) # number of arguments - beqz t2, illegal_syscall; + sll t0, v0, 3 + la t1, sys_call_table + addu t1, t0 + lw t2, (t1) # syscall routine + lw t3, 4(t1) # >= 0 if we need stack arguments + beqz t2, illegal_syscall - subu t0, t3, 5 # 5 or more arguments? sw a3, PT_R26(sp) # save a3 for syscall restarting - bgez t0, stackargs + bgez t3, stackargs stack_done: - sw a3, PT_R26(sp) # save for syscall restart - LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + lw t0, TI_FLAGS($28) # syscall tracing enabled? li t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT - and t0, t1, t0 + and t0, t1 bnez t0, syscall_trace_entry # -> yes jalr t2 # Do The Real Thing (TM) @@ -65,13 +71,13 @@ stack_done: # restarting 1: sw v0, PT_R2(sp) # result -EXPORT(o32_syscall_exit) +o32_syscall_exit: local_irq_disable # make sure need_resched and # signals dont change between # sampling and return - LONG_L a2, TI_FLAGS($28) # current->work + lw a2, TI_FLAGS($28) # current->work li t0, _TIF_ALLWORK_MASK - and t0, a2, t0 + and t0, a2 bnez t0, o32_syscall_exit_work j restore_partial @@ -83,17 +89,16 @@ o32_syscall_exit_work: syscall_trace_entry: SAVE_STATIC - sw t2, PT_R1(sp) + move s0, t2 move a0, sp li a1, 0 jal do_syscall_trace - lw t2, PT_R1(sp) lw a0, PT_R4(sp) # Restore argument registers lw a1, PT_R5(sp) lw a2, PT_R6(sp) lw a3, PT_R7(sp) - jalr t2 + jalr s0 li t0, -EMAXERRNO - 1 # error? sltu t0, t0, v0 @@ -116,49 +121,48 @@ syscall_trace_entry: */ stackargs: lw t0, PT_R29(sp) # get old user stack pointer - subu t3, 4 - sll t1, t3, 2 # stack valid? - addu t1, t0 # end address - or t0, t1 - bltz t0, bad_stack # -> sp is bad - - lw t0, PT_R29(sp) # get old user stack pointer - PTR_LA t1, 4f # copy 1 to 3 arguments - sll t3, t3, 4 - subu t1, t3 - jr t1 - - /* Ok, copy the args from the luser stack to the kernel stack */ /* - * I know Ralf doesn't like nops but this avoids code - * duplication for R3000 targets (and this is the - * only place where ".set reorder" doesn't help). - * Harald. + * We intentionally keep the kernel stack a little below the top of + * userspace so we don't have to do a slower byte accurate check here. + */ + lw t5, TI_ADDR_LIMIT($28) + addu t4, t0, 32 + and t5, t4 + bltz t5, bad_stack # -> sp is bad + + /* Ok, copy the args from the luser stack to the kernel stack. + * t3 is the precomputed number of instruction bytes needed to + * load or store arguments 6-8. */ + + la t1, 5f # load up to 3 arguments + subu t1, t3 +1: lw t5, 16(t0) # argument #5 from usp .set push .set noreorder .set nomacro -1: lw t1, 24(t0) # argument #7 from usp - nop - sw t1, 24(sp) - nop -2: lw t1, 20(t0) # argument #5 from usp - nop - sw t1, 20(sp) - nop -3: lw t1, 16(t0) # argument #5 from usp - nop - sw t1, 16(sp) - nop -4: .set pop - - j stack_done # go back + jr t1 + addiu t1, 6f - 5f + +2: lw t8, 28(t0) # argument #8 from usp +3: lw t7, 24(t0) # argument #7 from usp +4: lw t6, 20(t0) # argument #6 from usp +5: jr t1 + sw t5, 16(sp) # argument #5 to ksp + + sw t8, 28(sp) # argument #8 to ksp + sw t7, 24(sp) # argument #7 to ksp + sw t6, 20(sp) # argument #6 to ksp +6: j stack_done # go back + nop + .set pop .section __ex_table,"a" PTR 1b,bad_stack PTR 2b,bad_stack PTR 3b,bad_stack + PTR 4b,bad_stack .previous /* @@ -177,7 +181,7 @@ bad_stack: * The system call does not exist in this kernel */ illegal_syscall: - li v0, ENOSYS # error + li v0, -ENOSYS # error sw v0, PT_R2(sp) li t0, 1 # set error flag sw t0, PT_R7(sp) @@ -199,7 +203,11 @@ illegal_syscall: 1: ll v0, (a1) move a0, a2 2: sc a0, (a1) +#if R10000_LLSC_WAR + beqzl a0, 1b +#else beqz a0, 1b +#endif .section __ex_table,"a" PTR 1b, bad_stack @@ -234,12 +242,12 @@ illegal_syscall: sw v0, PT_R2(sp) # result /* Success, so skip usual error handling garbage. */ - LONG_L a2, TI_FLAGS($28) # syscall tracing enabled? + lw a2, TI_FLAGS($28) # syscall tracing enabled? li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT and t0, a2, t0 bnez t0, 1f - b o32_syscall_exit + j o32_syscall_exit 1: SAVE_STATIC move a0, sp @@ -265,69 +273,49 @@ bad_alignment: END(sys_sysmips) LEAF(sys_syscall) - lw t0, PT_R29(sp) # user sp - - sltu v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1 - beqz v0, enosys - - sll v0, a0, 2 - la v1, sys_syscall - lw t2, sys_call_table(v0) # function pointer - lbu t4, sys_narg_table(a0) # number of arguments - - li v0, -EINVAL - beq t2, v1, out # do not recurse +#if defined(CONFIG_BINFMT_IRIX) + sltiu v0, a0, MAX_SYSCALL_NO + 1 # check syscall number +#else + subu t0, a0, __NR_O32_Linux # check syscall number + sltiu v0, t0, __NR_O32_Linux_syscalls + 1 +#endif + sll t1, t0, 3 + beqz v0, einval - beqz t2, enosys # null function pointer? + lw t2, sys_call_table(t1) # syscall routine - andi v0, t0, 0x3 # unaligned stack pointer? - bnez v0, sigsegv +#if defined(CONFIG_BINFMT_IRIX) + li v1, 4000 # nr of sys_syscall +#else + li v1, 4000 - __NR_O32_Linux # index of sys_syscall +#endif + beq t0, v1, einval # do not recurse - addu v0, t0, 16 # v0 = usp + 16 - addu t1, v0, 12 # 3 32-bit arguments - lw v1, TI_ADDR_LIMIT($28) - or v0, v0, t1 - and v1, v1, v0 - bltz v1, efault + /* Some syscalls like execve get their arguments from struct pt_regs + and claim zero arguments in the syscall table. Thus we have to + assume the worst case and shuffle around all potential arguments. + If you want performance, don't use indirect syscalls. */ move a0, a1 # shift argument registers move a1, a2 move a2, a3 - -1: lw a3, 16(t0) -2: lw t3, 20(t0) -3: lw t4, 24(t0) - - .section __ex_table, "a" - .word 1b, efault - .word 2b, efault - .word 3b, efault - .previous - - sw t3, 16(sp) # put into new stackframe - sw t4, 20(sp) - - bnez t4, 1f # zero arguments? - addu a0, sp, 32 # then pass sp in a0 -1: - - sw t3, 16(sp) - sw v1, 20(sp) + lw a3, 16(sp) + lw t4, 20(sp) + lw t5, 24(sp) + lw t6, 28(sp) + sw t4, 16(sp) + sw t5, 20(sp) + sw t6, 24(sp) + sw a0, PT_R4(sp) # .. and push back a0 - a3, some + sw a1, PT_R5(sp) # syscalls expect them there + sw a2, PT_R6(sp) + sw a3, PT_R7(sp) + sw a3, PT_R26(sp) # update a3 for syscall restarting jr t2 /* Unreached */ -enosys: li v0, -ENOSYS - b out - -sigsegv: - li a0, _SIGSEGV - move a1, $28 - jal force_sig - /* Fall through */ - -efault: li v0, -EFAULT - -out: jr ra +einval: li v0, -EINVAL + jr ra END(sys_syscall) .macro fifty ptr, nargs, from=1, to=50 @@ -345,12 +333,14 @@ out: jr ra .endm .macro syscalltable +#if defined(CONFIG_BINFMT_IRIX) mille sys_ni_syscall 0 /* 0 - 999 SVR4 flavour */ - #include "irix5sys.h" /* 1000 - 1999 32-bit IRIX */ + mille sys_ni_syscall 0 /* 1000 - 1999 32-bit IRIX */ mille sys_ni_syscall 0 /* 2000 - 2999 BSD43 flavour */ mille sys_ni_syscall 0 /* 3000 - 3999 POSIX flavour */ +#endif - sys sys_syscall 0 /* 4000 */ + sys sys_syscall 8 /* 4000 */ sys sys_exit 1 sys sys_fork 0 sys sys_read 3 @@ -401,7 +391,7 @@ out: jr ra sys sys_ni_syscall 0 /* was signal(2) */ sys sys_geteuid 0 sys sys_getegid 0 /* 4050 */ - sys sys_acct 0 + sys sys_acct 1 sys sys_umount 2 sys sys_ni_syscall 0 sys sys_ioctl 3 @@ -481,7 +471,7 @@ out: jr ra sys sys_init_module 5 sys sys_delete_module 1 sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */ - sys sys_quotactl 0 + sys sys_quotactl 4 sys sys_getpgid 1 sys sys_fchdir 1 sys sys_bdflush 2 @@ -502,7 +492,7 @@ out: jr ra sys sys_sysmips 4 sys sys_ni_syscall 0 /* 4150 */ sys sys_getsid 1 - sys sys_fdatasync 0 + sys sys_fdatasync 1 sys sys_sysctl 1 sys sys_mlock 2 sys sys_munlock 2 /* 4155 */ @@ -618,7 +608,7 @@ out: jr ra sys sys_clock_nanosleep 4 /* 4265 */ sys sys_tgkill 3 sys sys_utimes 2 - sys sys_ni_syscall 0 /* sys_mbind */ + sys sys_mbind 4 sys sys_ni_syscall 0 /* sys_get_mempolicy */ sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */ sys sys_mq_open 4 @@ -628,22 +618,24 @@ out: jr ra sys sys_mq_notify 2 /* 4275 */ sys sys_mq_getsetattr 3 sys sys_ni_syscall 0 /* sys_vserver */ + sys sys_waitid 4 + sys sys_ni_syscall 0 /* available, was setaltroot */ + sys sys_add_key 5 + sys sys_request_key 4 + sys sys_keyctl 5 .endm + /* We pre-compute the number of _instruction_ bytes needed to + load or store the arguments 6-8. Negative values are ignored. */ + .macro sys function, nargs PTR \function + LONG (\nargs << 2) - (5 << 2) .endm .align 3 -sys_call_table: + .type sys_call_table,@object +EXPORT(sys_call_table) syscalltable .size sys_call_table, . - sys_call_table - - .macro sys function, nargs - .byte \nargs - .endm - -sys_narg_table: - syscalltable - .size sys_narg_table, . - sys_narg_table