summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/entry.S
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
committer <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
commite7c2a72e2680827d6a733931273a93461c0d8d1b (patch)
treec9abeda78ef7504062bb2e816bcf3e3c9d680112 /arch/mips/kernel/entry.S
parentec6044459060a8c9ce7f64405c465d141898548c (diff)
Import of Linux/MIPS 1.3.0
Diffstat (limited to 'arch/mips/kernel/entry.S')
-rw-r--r--arch/mips/kernel/entry.S625
1 files changed, 625 insertions, 0 deletions
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
new file mode 100644
index 000000000..787e2bbf4
--- /dev/null
+++ b/arch/mips/kernel/entry.S
@@ -0,0 +1,625 @@
+/*
+ * arch/mips/kernel/entry.S
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * written by Ralf Baechle and Andreas Busse
+ */
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch. The ISA dependend TLB
+ * code is in arch/mips/kernel/tlb.S
+ */
+
+#include <linux/sys.h>
+
+#include <asm/asm.h>
+#include <asm/errno.h>
+#include <asm/segment.h>
+#include <asm/mipsregs.h>
+#include <asm/mipsconfig.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/stackframe.h>
+#include <asm/processor.h>
+
+/*
+ * These are offsets into the task-struct.
+ */
+state = 0
+counter = 4
+priority = 8
+signal = 12
+blocked = 16
+flags = 20
+errno = 24
+exec_domain = 60
+
+ .text
+ .set noreorder
+ .align 4
+handle_bottom_half:
+ lui s0,%hi(intr_count)
+ lw s1,%lo(intr_count)(s0)
+ mfc0 s3,CP0_STATUS # Enable IRQs
+ addiu s2,s1,1
+ sw s2,%lo(intr_count)(s0)
+ ori t0,s3,0x1f
+ xori t0,0x1e
+ jal do_bottom_half
+ mtc0 t0,CP0_STATUS # delay slot
+ mtc0 s3,CP0_STATUS # Restore old IRQ state
+ j 9f
+ sw s1,%lo(intr_count)(s0) # delay slot
+
+reschedule:
+ lui ra,%hi(ret_from_sys_call)
+ j schedule
+ addiu ra,%lo(ret_from_sys_call) # delay slot
+
+ .align 5
+ NESTED(handle_sys, FR_SIZE, sp)
+ .set noat
+ SAVE_ALL
+ STI
+ .set at
+ /*
+ * Compute return address. We assume that syscalls never
+ * appear in delay slots. For the Linux/MIPS libc this
+ * assumption is always true.
+ */
+ lw t3,FR_EPC(sp)
+ lw s1,FR_REG2(sp)
+ li t0,-ENOSYS
+ addiu t3,4
+ sw t3,FR_EPC(sp)
+ li t2,NR_syscalls
+ bge s1,t2,ret_from_sys_call
+ sw t0,FR_REG2(sp) # delay slot
+ sll s1,PTRLOG
+ lw s1,sys_call_table(s1)
+ lw s0,current
+
+ beqz s1,ret_from_sys_call
+ lw t0,flags(s0) # delay slot
+ sll t0,26 # PF_TRACESYS
+ bltz t0,1f
+ sw zero,errno(s0) # delay slot
+
+#if 0
+ lw t0,FR_ORIG_REG2(sp)
+ beq t0,4,1f
+ nop
+ la t0,sys_call_names
+ lw t1,FR_ORIG_REG2(sp)
+ sll t1,2
+ addu t0,t1
+ lw a1,(t0)
+ PRINT("%s(")
+ lw a1,FR_REG4(sp)
+ lw a2,FR_REG5(sp)
+ lw a3,FR_REG6(sp)
+ PRINT("%08lx, %08lx, %08lx, ")
+ lw a1,FR_REG7(sp)
+ lw a2,FR_EPC(sp)
+ lw a3,FR_REG31(sp)
+ PRINT("%08lx) epc %08lx ra %08lx ")
+1:
+#endif
+ lw a0,FR_REG4(sp)
+ lw a1,FR_REG5(sp)
+ lw a2,FR_REG6(sp)
+ lw a3,FR_REG7(sp)
+ lw t0,FR_REG3(sp)
+ jalr s1 # do the real work
+ sw t0,PTRSIZE*4(sp) # delay slot
+
+#if 0
+ lw t0,FR_ORIG_REG2(sp)
+ beq t0,4,1f
+ nop
+ sw v0,xxx
+ lw a1,xxx
+ PRINT("res %08lx\n")
+ lw v0,xxx
+ .data
+xxx: .word 0
+ .text
+1:
+#endif
+
+ lw t0,errno(s0)
+ sw v0,FR_REG2(sp) # save return value
+ subu t0,zero,t0
+ beqz t0,ret_from_sys_call
+ nop # delay slot
+ /*
+ * Fixme: should set error flag
+ */
+ j ret_from_sys_call
+ sw t0,FR_REG2(sp) # delay slot
+
+ .align 4
+1: jal syscall_trace
+ nop # delay slot
+
+ lw a0,FR_REG4(sp)
+ lw a1,FR_REG5(sp)
+ lw a2,FR_REG6(sp)
+ lw a3,FR_REG7(sp)
+ lw t0,FR_REG3(sp)
+ jalr s1 # do the real work
+ sw t0,PTRSIZE*4(sp) # delay slot
+
+ lw t0,errno(s0)
+ sw v0,FR_REG2(sp)
+ subu t0,zero,t0 # delay slot
+ beqz t0,1f
+ nop # delay slot
+ /*
+ * Fixme: should set error flag
+ */
+1: jal syscall_trace
+ sw t0,FR_REG2(sp) # delay slot
+
+ .align 4
+ .globl ret_from_sys_call
+ret_from_sys_call:
+ lw t0,intr_count # bottom half
+ bnez t0,return
+9:
+ lw t0,bh_mask # delay slot
+ lw t1,bh_active # unused delay slot
+ and t0,t1
+ bnez t0,handle_bottom_half
+
+ lw t0,FR_STATUS(sp) # returning to kernel mode?
+ andi t1,t0,0x10
+ beqz t1,return # -> yes
+
+ mfc0 t0,CP0_STATUS # delay slot
+ lw t1,need_resched
+ ori t0,0x1f # enable irqs
+ xori t0,0x1e
+ bnez t1,reschedule
+ mtc0 t0,CP0_STATUS # delay slot
+
+ lw s0,current
+ lw t0,task
+ lw t1,state(s0) # state
+ beq s0,t0,return # task[0] cannot have signals
+ lw t0,counter(s0) # counter
+ bnez t1,reschedule # state == 0 ?
+ lw a0,blocked(s0)
+ # save blocked in a0 for
+ # signal handling
+ beqz t0,reschedule # counter == 0 ?
+ lw t0,signal(s0)
+ nor t1,zero,a0
+ and t1,t0,t1
+ beqz t1,return
+ nop
+
+ jal do_signal
+ move a1,sp # delay slot
+
+ .set noat
+ .globl return
+return: RESTORE_ALL
+ ERET
+ .set at
+ END(handle_sys)
+
+/*
+ * Beware: interrupt, fast_interrupt and bad_interrupt have unusal
+ * calling conventions!
+ *
+ * t1 - interrupt number
+ * s2 - destroyed
+ * return values:
+ * v0 - return routine
+ */
+ .text
+ .set at
+ .align 5
+ NESTED(interrupt, FR_SIZE, sp)
+ move s2,ra
+ mfc0 t0,CP0_STATUS # enable IRQs
+ ori t0,0x1f
+ xori t0,0x1e
+ mtc0 t0,CP0_STATUS
+ move a0,t1
+ jal do_IRQ
+ move a1,sp # delay slot
+ mfc0 t0,CP0_STATUS # disable IRQs
+ ori t0,1
+ xori t0,1
+ la v0,ret_from_sys_call
+ jr s2
+ mtc0 t0,CP0_STATUS # delay slot
+ END(interrupt)
+
+ .align 5
+ NESTED(fast_interrupt, FR_SIZE, sp)
+ move s2,ra
+ move a0,t1
+ jal do_fast_IRQ
+ move a1,sp # delay slot
+ lui v0,%hi(return)
+ jr s2
+ addiu v0,%lo(return) # delay slot
+ END(fast_interrupt)
+
+ LEAF(bad_interrupt)
+ /*
+ * Don't return & unblock the pic
+ */
+ j return
+ nop
+ END(bad_interrupt)
+
+ .align 5
+ LEAF(spurious_interrupt)
+ /*
+ * Nothing happened... (whistle)
+ */
+ lui t1,%hi(spurious_count)
+ lw t0,%lo(spurious_count)(t1)
+ la v0,return
+ addiu t0,1
+ jr ra
+ sw t0,%lo(spurious_count)(t1)
+ END(spurious_interrupt)
+
+
+
+/*
+ * Build a default exception handler for the other R4x00 exceptions
+ */
+#define BUILD_HANDLER(exception) \
+ .align 5; \
+ NESTED(handle_##exception, FR_SIZE, sp); \
+ .set noat; \
+ SAVE_ALL; \
+ STI; \
+ .set at; \
+ la a1,8f; \
+ TEXT (#exception); \
+ lw a2,FR_EPC(sp); \
+ PRINT("Got %s at %08x.\n"); \
+ li a0,0; \
+ li t0,-1; /* not a sys call */ \
+ sw t0,FR_ORIG_REG2(sp); \
+ jal do_##exception; \
+ move a0,sp; /* delay slot */ \
+ j ret_from_sys_call; \
+ nop; /* delay slot */ \
+ END(handle_##exception)
+
+ BUILD_HANDLER(adel)
+ BUILD_HANDLER(ades)
+ BUILD_HANDLER(ibe)
+ BUILD_HANDLER(dbe)
+ BUILD_HANDLER(ov)
+ BUILD_HANDLER(fpe)
+ BUILD_HANDLER(bp)
+ BUILD_HANDLER(tr)
+ BUILD_HANDLER(ri)
+ BUILD_HANDLER(cpu)
+ BUILD_HANDLER(vcei)
+ BUILD_HANDLER(vced)
+ BUILD_HANDLER(watch)
+ BUILD_HANDLER(reserved)
+
+
+/*
+ * Exception handler table with 32 entries.
+ * This might be extended to handle software exceptions
+ */
+ .bss
+ .align 2
+ EXPORT(exception_handlers)
+ .fill 32,4,0
+
+/*
+ * Table of syscalls
+ */
+ .data
+ EXPORT(sys_call_table)
+ PTR sys_setup /* 0 */
+ PTR sys_exit
+ PTR sys_fork
+ PTR sys_read
+ PTR sys_write
+ PTR sys_open /* 5 */
+ PTR sys_close
+ PTR sys_waitpid
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 10 */
+ PTR sys_execve
+ PTR sys_chdir
+ PTR sys_time
+ PTR sys_mknod
+ PTR sys_chmod /* 15 */
+ PTR sys_chown
+ PTR sys_break
+ PTR sys_stat
+ PTR sys_lseek
+ PTR sys_getpid /* 20 */
+ PTR sys_mount
+ PTR sys_umount
+ PTR sys_setuid
+ PTR sys_getuid
+ PTR sys_stime /* 25 */
+ PTR sys_ptrace
+ PTR sys_alarm
+ PTR sys_fstat
+ PTR sys_pause
+ PTR sys_utime /* 30 */
+ PTR sys_stty
+ PTR sys_gtty
+ PTR sys_access
+ PTR sys_nice
+ PTR sys_ftime /* 35 */
+ PTR sys_sync
+ PTR sys_kill
+ PTR sys_rename
+ PTR sys_mkdir
+ PTR sys_rmdir /* 40 */
+ PTR sys_dup
+ PTR sys_pipe
+ PTR sys_times
+ PTR sys_prof
+ PTR sys_brk /* 45 */
+ PTR sys_setgid
+ PTR sys_getgid
+ PTR sys_signal
+ PTR sys_geteuid
+ PTR sys_getegid /* 50 */
+ PTR sys_acct
+ PTR sys_phys
+ PTR sys_lock
+ PTR sys_ioctl
+ PTR sys_fcntl /* 55 */
+ PTR sys_mpx
+ PTR sys_setpgid
+ PTR sys_ulimit
+ PTR sys_olduname
+ PTR sys_umask /* 60 */
+ PTR sys_chroot
+ PTR sys_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 65 */
+ PTR sys_setsid
+ PTR sys_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 70 */
+ PTR sys_setregid
+ PTR sys_sigsuspend
+ PTR sys_sigpending
+ PTR sys_sethostname
+ PTR sys_setrlimit /* 75 */
+ PTR sys_getrlimit
+ PTR sys_getrusage
+ PTR sys_gettimeofday
+ PTR sys_settimeofday
+ PTR sys_getgroups /* 80 */
+ PTR sys_setgroups
+ PTR sys_select
+ PTR sys_symlink
+ PTR sys_lstat
+ PTR sys_readlink /* 85 */
+ PTR sys_uselib
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR old_readdir
+ PTR sys_mmap /* 90 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+ PTR sys_fchmod
+ PTR sys_fchown /* 95 */
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_profil
+ PTR sys_statfs
+ PTR sys_fstatfs /* 100 */
+ PTR sys_ioperm
+ PTR sys_socketcall
+ PTR sys_syslog
+ PTR sys_setitimer
+ PTR sys_getitimer /* 105 */
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat
+ PTR sys_uname
+ PTR sys_iopl /* 110 */
+ PTR sys_vhangup
+ PTR sys_idle
+ PTR sys_vm86
+ PTR sys_wait4
+ PTR sys_swapoff /* 115 */
+ PTR sys_sysinfo
+ PTR sys_ipc
+ PTR sys_fsync
+ PTR sys_sigreturn
+ PTR sys_clone /* 120 */
+ PTR sys_setdomainname
+ PTR sys_newuname
+ PTR 0 #sys_modify_ldt
+ PTR sys_adjtimex
+ PTR sys_mprotect /* 125 */
+ PTR sys_sigprocmask
+ PTR sys_create_module
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_get_kernel_syms /* 130 */
+ PTR sys_quotactl
+ PTR sys_getpgid
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 135 */
+ PTR sys_personality
+ PTR 0 /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+ PTR sys_llseek /* 140 */
+ PTR sys_getdents
+ PTR sys_select
+ PTR sys_flock
+ .space (NR_syscalls-140)*4
+
+ .bss
+ EXPORT(IRQ_vectors)
+ .fill 16,4,0
+
+ .text
+sys_call_names:
+ TTABLE ("setup")
+ TTABLE ("exit")
+ TTABLE ("fork")
+ TTABLE ("read")
+ TTABLE ("write")
+ TTABLE ("open")
+ TTABLE ("close")
+ TTABLE ("waitpid")
+ TTABLE ("creat")
+ TTABLE ("link")
+ TTABLE ("unlink")
+ TTABLE ("execve")
+ TTABLE ("chdir")
+ TTABLE ("time")
+ TTABLE ("mknod")
+ TTABLE ("chmod")
+ TTABLE ("chown")
+ TTABLE ("break")
+ TTABLE ("stat")
+ TTABLE ("lseek")
+ TTABLE ("getpid")
+ TTABLE ("mount")
+ TTABLE ("umount")
+ TTABLE ("setuid")
+ TTABLE ("getuid")
+ TTABLE ("stime")
+ TTABLE ("ptrace")
+ TTABLE ("alarm")
+ TTABLE ("fstat")
+ TTABLE ("pause")
+ TTABLE ("utime")
+ TTABLE ("stty")
+ TTABLE ("gtty")
+ TTABLE ("access")
+ TTABLE ("nice")
+ TTABLE ("ftime")
+ TTABLE ("sync")
+ TTABLE ("kill")
+ TTABLE ("rename")
+ TTABLE ("mkdir")
+ TTABLE ("rmdir")
+ TTABLE ("dup")
+ TTABLE ("pipe")
+ TTABLE ("times")
+ TTABLE ("prof")
+ TTABLE ("brk")
+ TTABLE ("setgid")
+ TTABLE ("getgid")
+ TTABLE ("signal")
+ TTABLE ("geteuid")
+ TTABLE ("getegid")
+ TTABLE ("acct")
+ TTABLE ("phys")
+ TTABLE ("lock")
+ TTABLE ("ioctl")
+ TTABLE ("fcntl")
+ TTABLE ("mpx")
+ TTABLE ("setpgid")
+ TTABLE ("ulimit")
+ TTABLE ("olduname")
+ TTABLE ("umask")
+ TTABLE ("chroot")
+ TTABLE ("ustat")
+ TTABLE ("dup2")
+ TTABLE ("getppid")
+ TTABLE ("getpgrp")
+ TTABLE ("setsid")
+ TTABLE ("sigaction")
+ TTABLE ("sgetmask")
+ TTABLE ("ssetmask")
+ TTABLE ("setreuid")
+ TTABLE ("setregid")
+ TTABLE ("sigsuspend")
+ TTABLE ("sigpending")
+ TTABLE ("sethostname")
+ TTABLE ("setrlimit")
+ TTABLE ("getrlimit")
+ TTABLE ("getrusage")
+ TTABLE ("gettimeofday")
+ TTABLE ("settimeofday")
+ TTABLE ("getgroups")
+ TTABLE ("setgroups")
+ TTABLE ("select")
+ TTABLE ("symlink")
+ TTABLE ("lstat")
+ TTABLE ("readlink")
+ TTABLE ("uselib")
+ TTABLE ("swapon")
+ TTABLE ("reboot")
+ TTABLE ("readdir")
+ TTABLE ("mmap")
+ TTABLE ("munmap")
+ TTABLE ("truncate")
+ TTABLE ("ftruncate")
+ TTABLE ("fchmod")
+ TTABLE ("fchown")
+ TTABLE ("getpriority")
+ TTABLE ("setpriority")
+ TTABLE ("profil")
+ TTABLE ("statfs")
+ TTABLE ("fstatfs")
+ TTABLE ("ioperm")
+ TTABLE ("socketcall")
+ TTABLE ("syslog")
+ TTABLE ("setitimer")
+ TTABLE ("getitimer")
+ TTABLE ("newstat")
+ TTABLE ("newlstat")
+ TTABLE ("newfstat")
+ TTABLE ("uname")
+ TTABLE ("iopl")
+ TTABLE ("vhangup")
+ TTABLE ("idle")
+ TTABLE ("vm86")
+ TTABLE ("wait4")
+ TTABLE ("swapoff")
+ TTABLE ("sysinfo")
+ TTABLE ("ipc")
+ TTABLE ("fsync")
+ TTABLE ("sigreturn")
+ TTABLE ("clone")
+ TTABLE ("setdomainname")
+ TTABLE ("newuname")
+ TTABLE ("modify_ldt (unused)")
+ TTABLE ("adjtimex")
+ TTABLE ("mprotect")
+ TTABLE ("sigprocmask")
+ TTABLE ("create_module")
+ TTABLE ("init_module")
+ TTABLE ("delete_module")
+ TTABLE ("get_kernel_syms")
+ TTABLE ("quotactl")
+ TTABLE ("getpgid")
+ TTABLE ("fchdir")
+ TTABLE ("bdflush")
+ TTABLE ("sysfs")
+ TTABLE ("personality")
+ TTABLE ("afs_syscall") /* for afs_syscall */
+ TTABLE ("setfsuid")
+ TTABLE ("setfsgid")
+ TTABLE ("llseek")
+ TTABLE ("sys_getdents")
+ TTABLE ("sys_select")
+ TTABLE ("sys_flock")