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/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 174EXPORT(except_vec_vi_lui) 175 lui v0, 0 /* Patched */ 176 j except_vec_vi_handler 177EXPORT(except_vec_vi_ori) 178 ori v0, 0 /* Patched */ 179 .set pop 180 END(except_vec_vi) 181EXPORT(except_vec_vi_end) 182 183/* 184 * Common Vectored Interrupt code 185 * Complete the register saves and invoke the handler which is passed in $v0 186 */ 187NESTED(except_vec_vi_handler, 0, sp) 188 SAVE_TEMP 189 SAVE_STATIC 190 CLI 191 move a0, sp 192 jalr v0 193 j ret_from_irq 194 END(except_vec_vi_handler) 195 196/* 197 * EJTAG debug exception handler. 198 */ 199NESTED(ejtag_debug_handler, PT_SIZE, sp) 200 .set push 201 .set noat 202 MTC0 k0, CP0_DESAVE 203 mfc0 k0, CP0_DEBUG 204 205 sll k0, k0, 30 # Check for SDBBP. 206 bgez k0, ejtag_return 207 208 PTR_LA k0, ejtag_debug_buffer 209 LONG_S k1, 0(k0) 210 SAVE_ALL 211 move a0, sp 212 jal ejtag_exception_handler 213 RESTORE_ALL 214 PTR_LA k0, ejtag_debug_buffer 215 LONG_L k1, 0(k0) 216 217ejtag_return: 218 MFC0 k0, CP0_DESAVE 219 .set mips32 220 deret 221 .set pop 222 END(ejtag_debug_handler) 223 224/* 225 * This buffer is reserved for the use of the EJTAG debug 226 * handler. 227 */ 228 .data 229EXPORT(ejtag_debug_buffer) 230 .fill LONGSIZE 231 .previous 232 233 __INIT 234 235/* 236 * NMI debug exception handler for MIPS reference boards. 237 * The NMI debug exception entry point is 0xbfc00000, which 238 * normally is in the boot PROM, so the boot PROM must do a 239 * unconditional jump to this vector. 240 */ 241NESTED(except_vec_nmi, 0, sp) 242 j nmi_handler 243 END(except_vec_nmi) 244 245 __FINIT 246 247NESTED(nmi_handler, PT_SIZE, sp) 248 .set push 249 .set noat 250 SAVE_ALL 251 move a0, sp 252 jal nmi_exception_handler 253 RESTORE_ALL 254 .set mips3 255 eret 256 .set pop 257 END(nmi_handler) 258 259 .macro __build_clear_none 260 .endm 261 262 .macro __build_clear_sti 263 STI 264 .endm 265 266 .macro __build_clear_cli 267 CLI 268 .endm 269 270 .macro __build_clear_fpe 271 cfc1 a1, fcr31 272 li a2, ~(0x3f << 12) 273 and a2, a1 274 ctc1 a2, fcr31 275 STI 276 .endm 277 278 .macro __build_clear_ade 279 MFC0 t0, CP0_BADVADDR 280 PTR_S t0, PT_BVADDR(sp) 281 KMODE 282 .endm 283 284 .macro __BUILD_silent exception 285 .endm 286 287 /* Gas tries to parse the PRINT argument as a string containing 288 string escapes and emits bogus warnings if it believes to 289 recognize an unknown escape code. So make the arguments 290 start with an n and gas will believe \n is ok ... */ 291 .macro __BUILD_verbose nexception 292 LONG_L a1, PT_EPC(sp) 293#ifdef CONFIG_32BIT 294 PRINT("Got \nexception at %08lx\012") 295#endif 296#ifdef CONFIG_64BIT 297 PRINT("Got \nexception at %016lx\012") 298#endif 299 .endm 300 301 .macro __BUILD_count exception 302 LONG_L t0,exception_count_\exception 303 LONG_ADDIU t0, 1 304 LONG_S t0,exception_count_\exception 305 .comm exception_count\exception, 8, 8 306 .endm 307 308 .macro __BUILD_HANDLER exception handler clear verbose ext 309 .align 5 310 NESTED(handle_\exception, PT_SIZE, sp) 311 .set noat 312 SAVE_ALL 313 FEXPORT(handle_\exception\ext) 314 __BUILD_clear_\clear 315 .set at 316 __BUILD_\verbose \exception 317 move a0, sp 318 jal do_\handler 319 j ret_from_exception 320 END(handle_\exception) 321 .endm 322 323 .macro BUILD_HANDLER exception handler clear verbose 324 __BUILD_HANDLER \exception \handler \clear \verbose _int 325 .endm 326 327 BUILD_HANDLER adel ade ade silent /* #4 */ 328 BUILD_HANDLER ades ade ade silent /* #5 */ 329 BUILD_HANDLER ibe be cli silent /* #6 */ 330 BUILD_HANDLER dbe be cli silent /* #7 */ 331 BUILD_HANDLER bp bp sti silent /* #9 */ 332 BUILD_HANDLER ri ri sti silent /* #10 */ 333 BUILD_HANDLER cpu cpu sti silent /* #11 */ 334 BUILD_HANDLER ov ov sti silent /* #12 */ 335 BUILD_HANDLER tr tr sti silent /* #13 */ 336 BUILD_HANDLER fpe fpe fpe silent /* #15 */ 337 BUILD_HANDLER mdmx mdmx sti silent /* #22 */ 338 BUILD_HANDLER watch watch sti verbose /* #23 */ 339 BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ 340 BUILD_HANDLER mt mt sti verbose /* #25 */ 341 BUILD_HANDLER dsp dsp sti silent /* #26 */ 342 BUILD_HANDLER reserved reserved sti verbose /* others */ 343 344#ifdef CONFIG_64BIT 345/* A temporary overflow handler used by check_daddi(). */ 346 347 __INIT 348 349 BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */ 350#endif 351