diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 12:04:58 +0100 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2015-01-03 12:04:58 +0100 |
commit | 008d0be72b2f160382c6e880765e96b64a050c65 (patch) | |
tree | 36f48a98a3815a408e2ce1693dd182af90f80305 /release/src/linux/linux/arch/mips/kernel/entry.S | |
parent | 611becfb8726c60cb060368541ad98191d4532f5 (diff) | |
download | tomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.gz tomato-008d0be72b2f160382c6e880765e96b64a050c65.tar.bz2 |
imported original firmware WRT54GL_v4.30.11_11_US
Diffstat (limited to 'release/src/linux/linux/arch/mips/kernel/entry.S')
-rw-r--r-- | release/src/linux/linux/arch/mips/kernel/entry.S | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/release/src/linux/linux/arch/mips/kernel/entry.S b/release/src/linux/linux/arch/mips/kernel/entry.S new file mode 100644 index 00000000..cc9ebbe0 --- /dev/null +++ b/release/src/linux/linux/arch/mips/kernel/entry.S @@ -0,0 +1,291 @@ +/* + * 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) 1994 - 2000, 2001 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#include <linux/config.h> +#include <linux/init.h> +#include <linux/sys.h> + +#include <asm/addrspace.h> +#include <asm/asm.h> +#include <asm/cacheops.h> +#include <asm/current.h> +#include <asm/errno.h> +#include <asm/mipsregs.h> +#include <asm/page.h> +#include <asm/pgtable-bits.h> +#include <asm/stackframe.h> +#include <asm/processor.h> +#include <asm/regdef.h> +#include <asm/fpregdef.h> +#include <asm/unistd.h> +#include <asm/isadep.h> + + + .text + .align 5 + .set push + .set reorder +FEXPORT(ret_from_irq) +FEXPORT(ret_from_exception) + lw t0, PT_STATUS(sp) # returning to kernel mode? + andi t0, t0, KU_USER + beqz t0, restore_all + +FEXPORT(ret_from_sys_call) # here to prevent code duplication +ret_from_schedule: + mfc0 t0, CP0_STATUS # need_resched and signals atomic test + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + lw v0, TASK_NEED_RESCHED($28) + lw v1, TASK_SIGPENDING($28) + bnez v0, reschedule + bnez v1, signal_return +restore_all: .set noat + RESTORE_ALL_AND_RET + .set at + +/* Put this behind restore_all for the sake of the branch prediction. */ +signal_return: + .type signal_return, @function + + mfc0 t0, CP0_STATUS + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + + move a0, zero + move a1, sp + jal do_signal + b restore_all + +reschedule: + jal schedule + b ret_from_schedule + +/* + * Common spurious interrupt handler. + */ + .text + .align 5 +LEAF(spurious_interrupt) + /* + * Someone tried to fool us by sending an interrupt but we + * couldn't find a cause for it. + */ + lui t1,%hi(irq_err_count) + lw t0,%lo(irq_err_count)(t1) + addiu t0,1 + sw t0,%lo(irq_err_count)(t1) + j ret_from_irq +END(spurious_interrupt) + + __INIT + + .set reorder + +NESTED(except_vec1_generic, 0, sp) + PANIC("Exception vector 1 called") +END(except_vec1_generic) + + /* + * General exception vector. Used for all CPUs except R4000 + * and R4400 SC and MC versions. + */ +NESTED(except_vec3_generic, 0, sp) +#ifdef CONFIG_BCM4710 + nop + nop +#endif + mfc0 k1, CP0_CAUSE + la k0, exception_handlers + andi k1, k1, 0x7c + addu k0, k0, k1 + lw k0, (k0) + jr k0 +END(except_vec3_generic) + .set at + + /* General exception vector R4000 version. */ +NESTED(except_vec3_r4000, 0, sp) + .set push + .set mips3 + .set noat +#if defined(R5432_CP0_INTERRUPT_WAR) + mfc0 k0, CP0_INDEX +#endif + mfc0 k1, CP0_CAUSE + li k0, 31<<2 + andi k1, k1, 0x7c + .set noreorder + beq k1, k0, handle_vced + li k0, 14<<2 + beq k1, k0, handle_vcei + la k0, exception_handlers + .set reorder + addu k0, k0, k1 + lw k0, (k0) + jr k0 + + /* + * Big shit, we now may have two dirty primary cache lines for + * the same physical address. We can savely invalidate the + * line pointed to by c0_badvaddr because after return from + * this exception handler the load / store will be re-executed. + */ +handle_vced: + mfc0 k0, CP0_BADVADDR + li k1, -4 + and k0, k1 + mtc0 zero, CP0_TAGLO + cache Index_Store_Tag_D,(k0) + cache Hit_Writeback_Inv_SD,(k0) +#ifdef CONFIG_PROC_FS + lui k0, %hi(vced_count) + lw k1, %lo(vced_count)(k0) + addiu k1, 1 + sw k1, %lo(vced_count)(k0) +#endif + eret + +handle_vcei: + mfc0 k0, CP0_BADVADDR + cache Hit_Writeback_Inv_SD, (k0) # also cleans pi +#ifdef CONFIG_PROC_FS + lui k0, %hi(vcei_count) + lw k1, %lo(vcei_count)(k0) + addiu k1, 1 + sw k1, %lo(vcei_count)(k0) +#endif + eret + .set pop +END(except_vec3_r4000) + + __FINIT + +/* + * Build a default exception handler for the exceptions that don't need + * special handlers. If you didn't know yet - I *like* playing games with + * the C preprocessor ... + */ +#define __BUILD_clear_none(exception) +#define __BUILD_clear_sti(exception) \ + STI +#define __BUILD_clear_cli(exception) \ + CLI +#define __BUILD_clear_fpe(exception) \ + cfc1 a1,fcr31; \ + li a2,~(0x3f<<12); \ + and a2,a1; \ + ctc1 a2,fcr31; \ + STI +#define __BUILD_clear_ade(exception) \ + .set reorder; \ + MFC0 t0,CP0_BADVADDR; \ + .set noreorder; \ + REG_S t0,PT_BVADDR(sp); \ + KMODE +#define __BUILD_silent(exception) + +#define fmt "Got %s at %08lx.\n" + +#define __BUILD_verbose(exception) \ + la a1,8f; \ + TEXT (#exception); \ + REG_L a2,PT_EPC(sp); \ + PRINT(fmt) +#define __BUILD_count(exception) \ + .set reorder; \ + lw t0,exception_count_##exception; \ + .set noreorder; \ + addiu t0, 1; \ + sw t0,exception_count_##exception; \ + .data; \ +EXPORT(exception_count_##exception); \ + .word 0; \ + .previous; +#define BUILD_HANDLER(exception,handler,clear,verbose) \ + .align 5; \ +NESTED(handle_##exception, PT_SIZE, sp); \ + .set noat; \ + SAVE_ALL; \ +FEXPORT(handle_##exception##_int); \ + __BUILD_clear_##clear(exception); \ + .set at; \ + __BUILD_##verbose(exception); \ + jal do_##handler; \ + move a0, sp; \ + j ret_from_exception; \ + nop; \ +END(handle_##exception) + + BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ + BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ + BUILD_HANDLER(ibe,be,cli,silent) /* #6 */ + BUILD_HANDLER(dbe,be,cli,silent) /* #7 */ + BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ + BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ + BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ + BUILD_HANDLER(ov,ov,sti,silent) /* #12 */ + BUILD_HANDLER(tr,tr,sti,silent) /* #13 */ + BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */ + BUILD_HANDLER(mdmx,mdmx,sti,silent) /* #22 */ + BUILD_HANDLER(watch,watch,sti,silent) /* #23 */ + BUILD_HANDLER(mcheck,mcheck,cli,silent) /* #24 */ + BUILD_HANDLER(reserved,reserved,sti,silent) /* others */ + + .set pop + +/* + * Table of syscalls + */ + .data + .align PTRLOG +EXPORT(sys_call_table) +#define SYS(call, narg) PTR call + + /* Reserved space for all SVR4 syscalls. */ + .space (1000)*PTRSIZE + +#ifdef CONFIG_BINFMT_IRIX + /* 32bit IRIX5 system calls. */ +#include "irix5sys.h" +#else + .space (1000)*PTRSIZE /* No IRIX syscalls */ +#endif + + /* Reserved space for all the BSD43 and POSIX syscalls. */ + .space (2000)*PTRSIZE + + /* Linux flavoured syscalls. */ +#include "syscalls.h" + +/* + * Number of arguments of each syscall + */ +EXPORT(sys_narg_table) +#undef SYS +#define SYS(call, narg) .byte narg + + /* Reserved space for all SVR4 flavoured syscalls. */ + .space (1000) + +#ifdef CONFIG_BINFMT_IRIX + /* 32bit IRIX5 system calls. */ +#include "irix5sys.h" +#else + .space (1000) /* No IRIX syscalls */ +#endif + + /* Reserved space for all the BSD43 and POSIX syscalls. */ + .space (2000) + + /* Linux flavoured syscalls. */ +#include "syscalls.h" |