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, 2003 Ralf Baechle 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 * Copyright (C) 2001 MIPS Technologies, Inc. 9 * Copyright (C) 2002 Maciej W. Rozycki 10 */ 11#include <linux/init.h> 12 13#include <asm/asm.h> 14#include <asm/asmmacro.h> 15#include <asm/cacheops.h> 16#include <asm/regdef.h> 17#include <asm/fpregdef.h> 18#include <asm/mipsregs.h> 19#include <asm/stackframe.h> 20#include <asm/war.h> 21 22#define PANIC_PIC(msg) \ 23 .set push; \ 24 .set reorder; \ 25 PTR_LA a0,8f; \ 26 .set noat; \ 27 PTR_LA AT, panic; \ 28 jr AT; \ 299: b 9b; \ 30 .set pop; \ 31 TEXT(msg) 32 33 __INIT 34 35NESTED(except_vec0_generic, 0, sp) 36 PANIC_PIC("Exception vector 0 called") 37 END(except_vec0_generic) 38 39NESTED(except_vec1_generic, 0, sp) 40 PANIC_PIC("Exception vector 1 called") 41 END(except_vec1_generic) 42 43/* 44 * General exception vector for all other CPUs. 45 * 46 * Be careful when changing this, it has to be at most 128 bytes 47 * to fit into space reserved for the exception handler. 48 */ 49NESTED(except_vec3_generic, 0, sp) 50 .set push 51 .set noat 52#if R5432_CP0_INTERRUPT_WAR 53 mfc0 k0, CP0_INDEX 54#endif 55 mfc0 k1, CP0_CAUSE 56 andi k1, k1, 0x7c 57#ifdef CONFIG_64BIT 58 dsll k1, k1, 1 59#endif 60 PTR_L k0, exception_handlers(k1) 61 jr k0 62 .set pop 63 END(except_vec3_generic) 64 65/* 66 * General exception handler for CPUs with virtual coherency exception. 67 * 68 * Be careful when changing this, it has to be at most 256 (as a special 69 * exception) bytes to fit into space reserved for the exception handler. 70 */ 71NESTED(except_vec3_r4000, 0, sp) 72 .set push 73 .set mips3 74 .set noat 75 mfc0 k1, CP0_CAUSE 76 li k0, 31<<2 77 andi k1, k1, 0x7c 78 .set push 79 .set noreorder 80 .set nomacro 81 beq k1, k0, handle_vced 82 li k0, 14<<2 83 beq k1, k0, handle_vcei 84#ifdef CONFIG_64BIT 85 dsll k1, k1, 1 86#endif 87 .set pop 88 PTR_L k0, exception_handlers(k1) 89 jr k0 90 91 /* 92 * Big shit, we now may have two dirty primary cache lines for the same 93 * physical address. We can safely invalidate the line pointed to by 94 * c0_badvaddr because after return from this exception handler the 95 * load / store will be re-executed. 96 */ 97handle_vced: 98 MFC0 k0, CP0_BADVADDR 99 li k1, -4 # Is this ... 100 and k0, k1 # ... really needed? 101 mtc0 zero, CP0_TAGLO 102 cache Index_Store_Tag_D, (k0) 103 cache Hit_Writeback_Inv_SD, (k0) 104#ifdef CONFIG_PROC_FS 105 PTR_LA k0, vced_count 106 lw k1, (k0) 107 addiu k1, 1 108 sw k1, (k0) 109#endif 110 eret 111 112handle_vcei: 113 MFC0 k0, CP0_BADVADDR 114 cache Hit_Writeback_Inv_SD, (k0) # also cleans pi 115#ifdef CONFIG_PROC_FS 116 PTR_LA k0, vcei_count 117 lw k1, (k0) 118 addiu k1, 1 119 sw k1, (k0) 120#endif 121 eret 122 .set pop 123 END(except_vec3_r4000) 124 125 __FINIT 126 127 .align 5 128NESTED(handle_int, PT_SIZE, sp) 129 SAVE_ALL 130 CLI 131 132 PTR_LA ra, ret_from_irq 133 move a0, sp 134 j plat_irq_dispatch 135 END(handle_int) 136 137 __INIT 138 139/* 140 * Special interrupt vector for MIPS64 ISA & embedded MIPS processors. 141 * This is a dedicated interrupt exception vector which reduces the 142 * interrupt processing overhead. The jump instruction will be replaced 143 * at the initialization time. 144 * 145 * Be careful when changing this, it has to be at most 128 bytes 146 * to fit into space reserved for the exception handler. 147 */ 148NESTED(except_vec4, 0, sp) 1491: j 1b /* Dummy, will be replaced */ 150 END(except_vec4) 151 152/* 153 * EJTAG debug exception handler. 154 * The EJTAG debug exception entry point is 0xbfc00480, which 155 * normally is in the boot PROM, so the boot PROM must do a 156 * unconditional jump to this vector. 157 */ 158NESTED(except_vec_ejtag_debug, 0, sp) 159 j ejtag_debug_handler 160 END(except_vec_ejtag_debug) 161 162 __FINIT 163 164/* 165 * Vectored interrupt handler. 166 * This prototype is copied to ebase + n*IntCtl.VS and patched 167 * to invoke the handler 168 */ 169NESTED(except_vec_vi, 0, sp) 170 SAVE_SOME 171 SAVE_AT 172 .set push 173 .set noreorder 174#ifdef CONFIG_MIPS_MT_SMTC 175 /* 176 * To keep from blindly blocking *all* interrupts 177 * during service by SMTC kernel, we also want to 178 * pass the IM value to be cleared. 179 */ 180EXPORT(except_vec_vi_mori) 181 ori a0, $0, 0 182#endif /* CONFIG_MIPS_MT_SMTC */ 183EXPORT(except_vec_vi_lui) 184 lui v0, 0 /* Patched */ 185 j except_vec_vi_handler 186EXPORT(except_vec_vi_ori) 187 ori v0, 0 /* Patched */ 188 .set pop 189 END(except_vec_vi) 190EXPORT(except_vec_vi_end) 191 192/* 193 * Common Vectored Interrupt code 194 * Complete the register saves and invoke the handler which is passed in $v0 195 */ 196NESTED(except_vec_vi_handler, 0, sp) 197 SAVE_TEMP 198 SAVE_STATIC 199#ifdef CONFIG_MIPS_MT_SMTC 200 /* 201 * SMTC has an interesting problem that interrupts are level-triggered, 202 * and the CLI macro will clear EXL, potentially causing a duplicate 203 * interrupt service invocation. So we need to clear the associated 204 * IM bit of Status prior to doing CLI, and restore it after the 205 * service routine has been invoked - we must assume that the 206 * service routine will have cleared the state, and any active 207 * level represents a new or otherwised unserviced event... 208 */ 209 mfc0 t1, CP0_STATUS 210 and t0, a0, t1 211 mfc0 t2, CP0_TCCONTEXT 212 or t0, t0, t2 213 mtc0 t0, CP0_TCCONTEXT 214 xor t1, t1, t0 215 mtc0 t1, CP0_STATUS 216 _ehb 217#endif /* CONFIG_MIPS_MT_SMTC */ 218 CLI 219 move a0, sp 220 jalr v0 221 j ret_from_irq 222 END(except_vec_vi_handler) 223 224/* 225 * EJTAG debug exception handler. 226 */ 227NESTED(ejtag_debug_handler, PT_SIZE, sp) 228 .set push 229 .set noat 230 MTC0 k0, CP0_DESAVE 231 mfc0 k0, CP0_DEBUG 232 233 sll k0, k0, 30 # Check for SDBBP. 234 bgez k0, ejtag_return 235 236 PTR_LA k0, ejtag_debug_buffer 237 LONG_S k1, 0(k0) 238 SAVE_ALL 239 move a0, sp 240 jal ejtag_exception_handler 241 RESTORE_ALL 242 PTR_LA k0, ejtag_debug_buffer 243 LONG_L k1, 0(k0) 244 245ejtag_return: 246 MFC0 k0, CP0_DESAVE 247 .set mips32 248 deret 249 .set pop 250 END(ejtag_debug_handler) 251 252/* 253 * This buffer is reserved for the use of the EJTAG debug 254 * handler. 255 */ 256 .data 257EXPORT(ejtag_debug_buffer) 258 .fill LONGSIZE 259 .previous 260 261 __INIT 262 263/* 264 * NMI debug exception handler for MIPS reference boards. 265 * The NMI debug exception entry point is 0xbfc00000, which 266 * normally is in the boot PROM, so the boot PROM must do a 267 * unconditional jump to this vector. 268 */ 269NESTED(except_vec_nmi, 0, sp) 270 j nmi_handler 271 END(except_vec_nmi) 272 273 __FINIT 274 275NESTED(nmi_handler, PT_SIZE, sp) 276 .set push 277 .set noat 278 SAVE_ALL 279 move a0, sp 280 jal nmi_exception_handler 281 RESTORE_ALL 282 .set mips3 283 eret 284 .set pop 285 END(nmi_handler) 286 287 .macro __build_clear_none 288 .endm 289 290 .macro __build_clear_sti 291 STI 292 .endm 293 294 .macro __build_clear_cli 295 CLI 296 .endm 297 298 .macro __build_clear_fpe 299 cfc1 a1, fcr31 300 li a2, ~(0x3f << 12) 301 and a2, a1 302 ctc1 a2, fcr31 303 STI 304 .endm 305 306 .macro __build_clear_ade 307 MFC0 t0, CP0_BADVADDR 308 PTR_S t0, PT_BVADDR(sp) 309 KMODE 310 .endm 311 312 .macro __BUILD_silent exception 313 .endm 314 315 /* Gas tries to parse the PRINT argument as a string containing 316 string escapes and emits bogus warnings if it believes to 317 recognize an unknown escape code. So make the arguments 318 start with an n and gas will believe \n is ok ... */ 319 .macro __BUILD_verbose nexception 320 LONG_L a1, PT_EPC(sp) 321#ifdef CONFIG_32BIT 322 PRINT("Got \nexception at %08lx\012") 323#endif 324#ifdef CONFIG_64BIT 325 PRINT("Got \nexception at %016lx\012") 326#endif 327 .endm 328 329 .macro __BUILD_count exception 330 LONG_L t0,exception_count_\exception 331 LONG_ADDIU t0, 1 332 LONG_S t0,exception_count_\exception 333 .comm exception_count\exception, 8, 8 334 .endm 335 336 .macro __BUILD_HANDLER exception handler clear verbose ext 337 .align 5 338 NESTED(handle_\exception, PT_SIZE, sp) 339 .set noat 340 SAVE_ALL 341 FEXPORT(handle_\exception\ext) 342 __BUILD_clear_\clear 343 .set at 344 __BUILD_\verbose \exception 345 move a0, sp 346 jal do_\handler 347 j ret_from_exception 348 END(handle_\exception) 349 .endm 350 351 .macro BUILD_HANDLER exception handler clear verbose 352 __BUILD_HANDLER \exception \handler \clear \verbose _int 353 .endm 354 355 BUILD_HANDLER adel ade ade silent /* #4 */ 356 BUILD_HANDLER ades ade ade silent /* #5 */ 357 BUILD_HANDLER ibe be cli silent /* #6 */ 358 BUILD_HANDLER dbe be cli silent /* #7 */ 359 BUILD_HANDLER bp bp sti silent /* #9 */ 360 BUILD_HANDLER ri ri sti silent /* #10 */ 361 BUILD_HANDLER cpu cpu sti silent /* #11 */ 362 BUILD_HANDLER ov ov sti silent /* #12 */ 363 BUILD_HANDLER tr tr sti silent /* #13 */ 364 BUILD_HANDLER fpe fpe fpe silent /* #15 */ 365 BUILD_HANDLER mdmx mdmx sti silent /* #22 */ 366 BUILD_HANDLER watch watch sti verbose /* #23 */ 367 BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ 368 BUILD_HANDLER mt mt sti verbose /* #25 */ 369 BUILD_HANDLER dsp dsp sti silent /* #26 */ 370 BUILD_HANDLER reserved reserved sti verbose /* others */ 371 372#ifdef CONFIG_64BIT 373/* A temporary overflow handler used by check_daddi(). */ 374 375 __INIT 376 377 BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */ 378#endif 379