patch-2.1.101 linux/arch/mips/kernel/scall_o32.S
Next file: linux/arch/mips/kernel/setup.c
Previous file: linux/arch/mips/kernel/r6000_fpu.S
Back to the patch index
Back to the overall index
- Lines: 178
- Date:
Fri May 8 00:13:24 1998
- Orig file:
v2.1.100/linux/arch/mips/kernel/scall_o32.S
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S
@@ -0,0 +1,177 @@
+/*
+ * 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/05/01 01:34:21 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <linux/errno.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/unistd.h>
+
+/* This duplicates the definition from <linux/sched.h> */
+#define PF_TRACESYS 0x00000020 /* tracing system calls */
+
+/* This duplicates the definition from <asm/signal.h> */
+#define SIGILL 4 /* Illegal instruction (ANSI). */
+
+/* Highest syscall used of any syscall flavour */
+#define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls
+
+ .align 5
+NESTED(handle_sys, PT_SIZE, sp)
+ .set noat
+ SAVE_SOME
+ STI
+ .set at
+
+ lw t1, PT_EPC(sp) # skip syscall on return
+
+ sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+ addiu t1, 4 # skip to next instruction
+ beqz t0, illegal_syscall
+ sw t1, PT_EPC(sp)
+
+ /* 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;
+
+ subu t0, t3, 5 # 5 or more arguments?
+ bgez t0, stackargs
+
+stack_done:
+ lw t0, TASK_FLAGS($28) # syscall tracing enabled?
+ andi t0, PF_TRACESYS
+ bnez t0, trace_a_syscall
+
+ jalr t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sw t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sw v0, PT_R0(sp) # set flag for syscall restarting
+1: sw v0, PT_R2(sp) # result
+
+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 t2 # Do The Real Thing (TM)
+
+ li t0, -EMAXERRNO - 1 # error?
+ sltu t0, t0, v0
+ sw t0, PT_R7(sp) # set error flag
+ beqz t0, 1f
+
+ negu v0 # error
+ sw v0, PT_R0(sp) # set flag for syscall restarting
+1: sw v0, PT_R2(sp) # result
+
+ jal syscall_trace
+ j ret_from_sys_call
+
+/* ------------------------------------------------------------------------ */
+
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ */
+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
+ la t1, 3f # copy 1 to 2 arguments
+ sll t3, t3, 3
+ subu t1, t3
+ jr t1
+
+ /* Ok, copy the args from the luser stack to the kernel stack */
+1: lw t1, 20(t0) # argument #6 from usp
+ sw t1, 20(sp)
+2: lw t1, 16(t0) # argument #5 from usp
+ sw t1, 16(sp)
+
+3: j stack_done # go back
+
+ .section __ex_table,"a"
+ PTR 1b,bad_stack
+ PTR 2b,bad_stack
+ .previous
+
+ /*
+ * The stackpointer for a call with more than 4 arguments is bad.
+ */
+bad_stack:
+ negu v0 # error
+ sw v0, PT_R0(sp)
+ sw v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sw t0, PT_R7(sp)
+ j ret_from_sys_call
+
+ /*
+ * The system call does not exist in this kernel
+ */
+illegal_syscall:
+ li v0, ENOSYS # error
+ sw v0, PT_R2(sp)
+ li t0, 1 # set error flag
+ sw t0, PT_R7(sp)
+ j ret_from_sys_call
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov