summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/scall_o32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/scall_o32.S')
-rw-r--r--arch/mips/kernel/scall_o32.S98
1 files changed, 60 insertions, 38 deletions
diff --git a/arch/mips/kernel/scall_o32.S b/arch/mips/kernel/scall_o32.S
index eb25c34e5..6c46dedda 100644
--- a/arch/mips/kernel/scall_o32.S
+++ b/arch/mips/kernel/scall_o32.S
@@ -1,9 +1,13 @@
/*
- * Handle ABI O32 style syscalls.
+ * arch/mips/kernel/scall_o32.S
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
*
* Copyright (C) 1997, 1998 by Ralf Baechle
*
- * $Id: scall_o32.S,v 1.1 1998/03/12 19:06:20 ralf Exp $
+ * $Id: scall_o32.S,v 1.3 1998/03/26 07:39:10 ralf Exp $
*/
#include <asm/asm.h>
#include <linux/errno.h>
@@ -25,18 +29,11 @@
.align 5
NESTED(handle_sys, PT_SIZE, sp)
.set noat
- SAVE_ALL
+ SAVE_SOME
STI
.set at
- /*
- * By convention "li v0,<syscallno>" is always preceeding
- * the syscall instruction. So if we're in a delay slot
- * userland is screwed up.
- */
- lw t0, PT_CAUSE(sp) # delay slot?
lw t1, PT_EPC(sp) # skip syscall on return
- bltz t0, sigill_and_out
sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
addiu t1, 4 # skip to next instruction
@@ -45,18 +42,19 @@ NESTED(handle_sys, PT_SIZE, sp)
/* XXX Put both in one cacheline, should save a bit. */
sll t0, v0, 2
- lw s0, sys_call_table(t0) # syscall routine
- lbu s1, sys_narg_table(v0) # number of arguments
- beqz s0, illegal_syscall;
+ lw t2, sys_call_table(t0) # syscall routine
+ lbu t3, sys_narg_table(v0) # number of arguments
+ beqz t2, illegal_syscall;
- subu t0, s1, 5 # 5 or more arguments?
- bgezal t0, stackargs
+ subu t0, t3, 5 # 5 or more arguments?
+ bgez t0, stackargs
- lw s3, TASK_FLAGS($28) # syscall tracing enabled?
- andi s3, PF_TRACESYS
- bnez s3, trace_a_syscall
+stack_done:
+ lw t0, TASK_FLAGS($28) # syscall tracing enabled?
+ andi t0, PF_TRACESYS
+ bnez t0, trace_a_syscall
- jalr s0 # Do The Real Thing (TM)
+ jalr t2 # Do The Real Thing (TM)
li t0, -EMAXERRNO - 1 # error?
sltu t0, t0, v0
@@ -66,14 +64,49 @@ NESTED(handle_sys, PT_SIZE, sp)
negu v0 # error
sw v0, PT_R0(sp) # set flag for syscall restarting
1: sw v0, PT_R2(sp) # result
- j ret_from_sys_call
+
+EXPORT(o32_ret_from_sys_call)
+ lw t0,bh_mask
+ lw t1,bh_active # unused delay slot
+ and t0,t1
+ bnez t0,o32_handle_bottom_half
+
+9: lw t0,PT_STATUS(sp) # returning to kernel mode?
+ andi t1, t0, 0x10
+ lw t2, need_resched
+ beqz t1, o32_return # -> yes
+ bnez t2, o32_reschedule
+ lw v0, TASK_SIGPENDING($28)
+ move a0, zero
+ beqz v0, o32_return
+ move a1, sp
+ SAVE_STATIC
+ jal do_signal
+
+o32_return:
+ RESTORE_SOME
+ RESTORE_SP
+ .set mips3
+ eret
+ .set mips0
+
+o32_handle_bottom_half:
+ jal do_bottom_half
+ b 9b
+o32_reschedule:
+ SAVE_STATIC
+ jal schedule
+ b o32_ret_from_sys_call
/* ------------------------------------------------------------------------ */
trace_a_syscall:
+ SAVE_STATIC
+ sw t2,PT_R1(sp)
jal syscall_trace
+ sw t2,PT_R1(sp)
- jalr s0 # Do The Real Thing (TM)
+ jalr t2 # Do The Real Thing (TM)
li t0, -EMAXERRNO - 1 # error?
sltu t0, t0, v0
@@ -95,20 +128,18 @@ trace_a_syscall:
* This Sucks (TM).
*/
stackargs:
- move s3, ra # save return address
-
lw t0, PT_R29(sp) # get old user stack pointer
- subu s2, s1, 4
- sll t1, s2, 2 # stack valid?
+ subu t3, 4
+ sll t1, t3, 2 # stack valid?
addu t1, t0 # end address
- or t2, t0, t1
+ or t0, t1
bltz t0, bad_stack # -> sp is bad
lw t0, PT_R29(sp) # get old user stack pointer
la t1, 3f # copy 1 to 2 arguments
- sll s2, s2, 3
- subu t1, s2
+ sll t3, t3, 3
+ subu t1, t3
jr t1
/* Ok, copy the args from the luser stack to the kernel stack */
@@ -117,7 +148,7 @@ stackargs:
2: lw t1, 16(t0) # argument #5 from usp
sw t1, 16(sp)
-3: jr s3 # go back
+3: j stack_done # go back
.section __ex_table,"a"
PTR 1b,bad_stack
@@ -144,12 +175,3 @@ illegal_syscall:
li t0, 1 # set error flag
sw t0, PT_R7(sp)
j ret_from_sys_call
-
-sigill_and_out:
- li t0, -1 # not a sys call
- REG_S t0, PT_OR2(sp)
- li a0, SIGILL
- move a2, $28
- jal force_sig
- j ret_from_sys_call
- END(handle_sys)