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