/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include .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 #if defined(CONFIG_RTHAL) lw t0, (rthal + 8) # sti beqz t0, 1f nop lw t0, (rthal + 4) # cli jal t0 nop 1: #endif 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) 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 #if defined(CONFIG_RTHAL) #define RT_RA 0 #define RT_R0 4 #define RT_R1 8 #define RT_R2 12 #define RT_R3 16 #define RT_R4 20 #define RT_R5 24 #define RT_R6 28 #define RT_R7 32 #define RT_R8 36 #define RT_R9 40 #define RT_R10 44 #define RT_R11 48 #define RT_R12 52 #define RT_R13 56 #define RT_R14 60 #define RT_R15 64 #define RT_R16 68 #define RT_R17 72 #define RT_R18 76 #define RT_R19 80 #define RT_R20 84 #define RT_R21 88 #define RT_R22 92 #define RT_R23 96 #define RT_R24 100 #define RT_R25 104 #define RT_R26 108 #define RT_R27 112 #define RT_R28 116 #define RT_R29 120 #define RT_R30 124 #define RT_R31 128 #define RT_SIZE 132 .set push .set noreorder .set noat .set nomacro NESTED(rthal_sw_thread, RT_SIZE, sp) .set push subu sp, RT_SIZE sw $1, RT_R1(sp) sw $2, RT_R2(sp) sw $3, RT_R3(sp) sw $4, RT_R4(sp) sw $5, RT_R5(sp) sw $6, RT_R6(sp) sw $7, RT_R7(sp) sw $8, RT_R8(sp) sw $9, RT_R9(sp) sw $10, RT_R10(sp) sw $11, RT_R11(sp) sw $12, RT_R12(sp) sw $13, RT_R13(sp) sw $14, RT_R14(sp) sw $15, RT_R15(sp) sw $16, RT_R16(sp) sw $17, RT_R17(sp) sw $18, RT_R18(sp) sw $19, RT_R19(sp) sw $20, RT_R20(sp) sw $21, RT_R21(sp) sw $22, RT_R22(sp) sw $23, RT_R23(sp) sw $24, RT_R24(sp) sw $25, RT_R25(sp) sw $26, RT_R26(sp) sw $27, RT_R27(sp) sw $28, RT_R28(sp) sw $29, RT_R29(sp) sw $30, RT_R30(sp) sw $31, RT_R31(sp) lw $8, ($4) sw $29, ($8) sw $5, ($4) lw $29, ($5) .set pop lw $1, RT_R1(sp) lw $2, RT_R2(sp) lw $3, RT_R3(sp) lw $4, RT_R4(sp) lw $5, RT_R5(sp) lw $6, RT_R6(sp) lw $7, RT_R7(sp) lw $8, RT_R8(sp) lw $9, RT_R9(sp) lw $10, RT_R10(sp) lw $11, RT_R11(sp) lw $12, RT_R12(sp) lw $13, RT_R13(sp) lw $14, RT_R14(sp) lw $15, RT_R15(sp) lw $16, RT_R16(sp) lw $17, RT_R17(sp) lw $18, RT_R18(sp) lw $19, RT_R19(sp) lw $20, RT_R20(sp) lw $21, RT_R21(sp) lw $22, RT_R22(sp) lw $23, RT_R23(sp) lw $24, RT_R24(sp) lw $25, RT_R25(sp) lw $26, RT_R26(sp) lw $27, RT_R27(sp) lw $28, RT_R28(sp) lw $30, RT_R30(sp) lw $31, RT_R31(sp) addu sp, RT_SIZE j $31 nop .set at .set reorder .set macro END(rthal_sw_thread) #endif /* CONFIG_RTHAL */ /* * 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"