1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1994 - 2000, 2001 by Ralf Baechle 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 2001 MIPS Technologies, Inc. 9 */ 10#include <linux/config.h> 11#include <linux/init.h> 12#include <linux/sys.h> 13 14#include <asm/addrspace.h> 15#include <asm/asm.h> 16#include <asm/cacheops.h> 17#include <asm/current.h> 18#include <asm/errno.h> 19#include <asm/mipsregs.h> 20#include <asm/page.h> 21#include <asm/pgtable-bits.h> 22#include <asm/stackframe.h> 23#include <asm/processor.h> 24#include <asm/regdef.h> 25#include <asm/fpregdef.h> 26#include <asm/unistd.h> 27#include <asm/isadep.h> 28 29 30 .text 31 .align 5 32 .set push 33 .set reorder 34FEXPORT(ret_from_irq) 35FEXPORT(ret_from_exception) 36 lw t0, PT_STATUS(sp) # returning to kernel mode? 37 andi t0, t0, KU_USER 38 beqz t0, restore_all 39 40FEXPORT(ret_from_sys_call) # here to prevent code duplication 41ret_from_schedule: 42 mfc0 t0, CP0_STATUS # need_resched and signals atomic test 43 ori t0, t0, 1 44 xori t0, t0, 1 45 mtc0 t0, CP0_STATUS 46 SSNOP; SSNOP; SSNOP 47 48 lw v0, TASK_NEED_RESCHED($28) 49 lw v1, TASK_SIGPENDING($28) 50 bnez v0, reschedule 51 bnez v1, signal_return 52restore_all: .set noat 53 RESTORE_ALL_AND_RET 54 .set at 55 56/* Put this behind restore_all for the sake of the branch prediction. */ 57signal_return: 58 .type signal_return, @function 59 60 mfc0 t0, CP0_STATUS 61 ori t0, t0, 1 62 mtc0 t0, CP0_STATUS 63 64 move a0, zero 65 move a1, sp 66 jal do_signal 67 b restore_all 68 69reschedule: 70 jal schedule 71 b ret_from_schedule 72 73/* 74 * Common spurious interrupt handler. 75 */ 76 .text 77 .align 5 78LEAF(spurious_interrupt) 79 /* 80 * Someone tried to fool us by sending an interrupt but we 81 * couldn't find a cause for it. 82 */ 83 lui t1,%hi(irq_err_count) 84 lw t0,%lo(irq_err_count)(t1) 85 addiu t0,1 86 sw t0,%lo(irq_err_count)(t1) 87 j ret_from_irq 88END(spurious_interrupt) 89 90 __INIT 91 92 .set reorder 93 94NESTED(except_vec1_generic, 0, sp) 95 PANIC("Exception vector 1 called") 96END(except_vec1_generic) 97 98 /* 99 * General exception vector. Used for all CPUs except R4000 100 * and R4400 SC and MC versions. 101 */ 102NESTED(except_vec3_generic, 0, sp) 103#if R5432_CP0_INTERRUPT_WAR 104 mfc0 k0, CP0_INDEX 105#endif 106 mfc0 k1, CP0_CAUSE 107 la k0, exception_handlers 108 andi k1, k1, 0x7c 109 addu k0, k0, k1 110 lw k0, (k0) 111 jr k0 112END(except_vec3_generic) 113 .set at 114 115 /* General exception vector R4000 version. */ 116NESTED(except_vec3_r4000, 0, sp) 117 .set push 118 .set mips3 119 .set noat 120 mfc0 k1, CP0_CAUSE 121 li k0, 31<<2 122 andi k1, k1, 0x7c 123 .set noreorder 124 beq k1, k0, handle_vced 125 li k0, 14<<2 126 beq k1, k0, handle_vcei 127 la k0, exception_handlers 128 .set reorder 129 addu k0, k0, k1 130 lw k0, (k0) 131 jr k0 132 133 /* 134 * Big shit, we now may have two dirty primary cache lines for 135 * the same physical address. We can savely invalidate the 136 * line pointed to by c0_badvaddr because after return from 137 * this exception handler the load / store will be re-executed. 138 */ 139handle_vced: 140 mfc0 k0, CP0_BADVADDR 141 li k1, -4 142 and k0, k1 143 mtc0 zero, CP0_TAGLO 144 cache Index_Store_Tag_D,(k0) 145 cache Hit_Writeback_Inv_SD,(k0) 146#ifdef CONFIG_PROC_FS 147 lui k0, %hi(vced_count) 148 lw k1, %lo(vced_count)(k0) 149 addiu k1, 1 150 sw k1, %lo(vced_count)(k0) 151#endif 152 eret 153 154handle_vcei: 155 mfc0 k0, CP0_BADVADDR 156 cache Hit_Writeback_Inv_SD, (k0) # also cleans pi 157#ifdef CONFIG_PROC_FS 158 lui k0, %hi(vcei_count) 159 lw k1, %lo(vcei_count)(k0) 160 addiu k1, 1 161 sw k1, %lo(vcei_count)(k0) 162#endif 163 eret 164 .set pop 165END(except_vec3_r4000) 166 167 __FINIT 168 169/* 170 * Build a default exception handler for the exceptions that don't need 171 * special handlers. If you didn't know yet - I *like* playing games with 172 * the C preprocessor ... 173 */ 174#define __BUILD_clear_none(exception) 175#define __BUILD_clear_sti(exception) \ 176 STI 177#define __BUILD_clear_cli(exception) \ 178 CLI 179#define __BUILD_clear_fpe(exception) \ 180 cfc1 a1,fcr31; \ 181 li a2,~(0x3f<<12); \ 182 and a2,a1; \ 183 ctc1 a2,fcr31; \ 184 STI 185#define __BUILD_clear_ade(exception) \ 186 .set reorder; \ 187 MFC0 t0,CP0_BADVADDR; \ 188 .set noreorder; \ 189 REG_S t0,PT_BVADDR(sp); \ 190 KMODE 191#define __BUILD_silent(exception) 192 193#define fmt "Got %s at %08lx.\n" 194 195#define __BUILD_verbose(exception) \ 196 la a1,8f; \ 197 TEXT (#exception); \ 198 REG_L a2,PT_EPC(sp); \ 199 PRINT(fmt) 200#define __BUILD_count(exception) \ 201 .set reorder; \ 202 lw t0,exception_count_##exception; \ 203 .set noreorder; \ 204 addiu t0, 1; \ 205 sw t0,exception_count_##exception; \ 206 .data; \ 207EXPORT(exception_count_##exception); \ 208 .word 0; \ 209 .previous; 210#define BUILD_HANDLER(exception,handler,clear,verbose) \ 211 .align 5; \ 212NESTED(handle_##exception, PT_SIZE, sp); \ 213 .set noat; \ 214 SAVE_ALL; \ 215FEXPORT(handle_##exception##_int); \ 216 __BUILD_clear_##clear(exception); \ 217 .set at; \ 218 __BUILD_##verbose(exception); \ 219 jal do_##handler; \ 220 move a0, sp; \ 221 j ret_from_exception; \ 222 nop; \ 223END(handle_##exception) 224 225 BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ 226 BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ 227 BUILD_HANDLER(ibe,be,cli,silent) /* #6 */ 228 BUILD_HANDLER(dbe,be,cli,silent) /* #7 */ 229 BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ 230 BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ 231 BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ 232 BUILD_HANDLER(ov,ov,sti,silent) /* #12 */ 233 BUILD_HANDLER(tr,tr,sti,silent) /* #13 */ 234 BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */ 235 BUILD_HANDLER(mdmx,mdmx,sti,silent) /* #22 */ 236 BUILD_HANDLER(watch,watch,sti,silent) /* #23 */ 237 BUILD_HANDLER(mcheck,mcheck,cli,silent) /* #24 */ 238 BUILD_HANDLER(reserved,reserved,sti,silent) /* others */ 239 240 .set pop 241 242/* 243 * Table of syscalls 244 */ 245 .data 246 .align PTRLOG 247EXPORT(sys_call_table) 248#define SYS(call, narg) PTR call 249 250 /* Reserved space for all SVR4 syscalls. */ 251 .space (1000)*PTRSIZE 252 253#ifdef CONFIG_BINFMT_IRIX 254 /* 32bit IRIX5 system calls. */ 255#include "irix5sys.h" 256#else 257 .space (1000)*PTRSIZE /* No IRIX syscalls */ 258#endif 259 260 /* Reserved space for all the BSD43 and POSIX syscalls. */ 261 .space (2000)*PTRSIZE 262 263 /* Linux flavoured syscalls. */ 264#include "syscalls.h" 265 266/* 267 * Number of arguments of each syscall 268 */ 269EXPORT(sys_narg_table) 270#undef SYS 271#define SYS(call, narg) .byte narg 272 273 /* Reserved space for all SVR4 flavoured syscalls. */ 274 .space (1000) 275 276#ifdef CONFIG_BINFMT_IRIX 277 /* 32bit IRIX5 system calls. */ 278#include "irix5sys.h" 279#else 280 .space (1000) /* No IRIX syscalls */ 281#endif 282 283 /* Reserved space for all the BSD43 and POSIX syscalls. */ 284 .space (2000) 285 286 /* Linux flavoured syscalls. */ 287#include "syscalls.h" 288