1/* 2 * arch/xtensa/kernel/vectors.S 3 * 4 * This file contains all exception vectors (user, kernel, and double), 5 * as well as the window vectors (overflow and underflow), and the debug 6 * vector. These are the primary vectors executed by the processor if an 7 * exception occurs. 8 * 9 * This file is subject to the terms and conditions of the GNU General 10 * Public License. See the file "COPYING" in the main directory of 11 * this archive for more details. 12 * 13 * Copyright (C) 2005 - 2008 Tensilica, Inc. 14 * 15 * Chris Zankel <chris@zankel.net> 16 * 17 */ 18 19/* 20 * We use a two-level table approach. The user and kernel exception vectors 21 * use a first-level dispatch table to dispatch the exception to a registered 22 * fast handler or the default handler, if no fast handler was registered. 23 * The default handler sets up a C-stack and dispatches the exception to a 24 * registerd C handler in the second-level dispatch table. 25 * 26 * Fast handler entry condition: 27 * 28 * a0: trashed, original value saved on stack (PT_AREG0) 29 * a1: a1 30 * a2: new stack pointer, original value in depc 31 * a3: dispatch table 32 * depc: a2, original value saved on stack (PT_DEPC) 33 * excsave_1: a3 34 * 35 * The value for PT_DEPC saved to stack also functions as a boolean to 36 * indicate that the exception is either a double or a regular exception: 37 * 38 * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception 39 * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception 40 * 41 * Note: Neither the kernel nor the user exception handler generate literals. 42 * 43 */ 44 45#include <linux/linkage.h> 46#include <asm/ptrace.h> 47#include <asm/current.h> 48#include <asm/asm-offsets.h> 49#include <asm/pgtable.h> 50#include <asm/processor.h> 51#include <asm/page.h> 52#include <asm/thread_info.h> 53 54#define WINDOW_VECTORS_SIZE 0x180 55 56 57/* 58 * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0) 59 * 60 * We get here when an exception occurred while we were in userland. 61 * We switch to the kernel stack and jump to the first level handler 62 * associated to the exception cause. 63 * 64 * Note: the saved kernel stack pointer (EXC_TABLE_KSTK) is already 65 * decremented by PT_USER_SIZE. 66 */ 67 68 .section .UserExceptionVector.text, "ax" 69 70ENTRY(_UserExceptionVector) 71 72 xsr a3, excsave1 # save a3 and get dispatch table 73 wsr a2, depc # save a2 74 l32i a2, a3, EXC_TABLE_KSTK # load kernel stack to a2 75 s32i a0, a2, PT_AREG0 # save a0 to ESF 76 rsr a0, exccause # retrieve exception cause 77 s32i a0, a2, PT_DEPC # mark it as a regular exception 78 addx4 a0, a0, a3 # find entry in table 79 l32i a0, a0, EXC_TABLE_FAST_USER # load handler 80 jx a0 81 82ENDPROC(_UserExceptionVector) 83 84/* 85 * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0) 86 * 87 * We get this exception when we were already in kernel space. 88 * We decrement the current stack pointer (kernel) by PT_SIZE and 89 * jump to the first-level handler associated with the exception cause. 90 * 91 * Note: we need to preserve space for the spill region. 92 */ 93 94 .section .KernelExceptionVector.text, "ax" 95 96ENTRY(_KernelExceptionVector) 97 98 xsr a3, excsave1 # save a3, and get dispatch table 99 wsr a2, depc # save a2 100 addi a2, a1, -16-PT_SIZE # adjust stack pointer 101 s32i a0, a2, PT_AREG0 # save a0 to ESF 102 rsr a0, exccause # retrieve exception cause 103 s32i a0, a2, PT_DEPC # mark it as a regular exception 104 addx4 a0, a0, a3 # find entry in table 105 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address 106 jx a0 107 108ENDPROC(_KernelExceptionVector) 109 110/* 111 * Double exception vector (Exceptions with PS.EXCM == 1) 112 * We get this exception when another exception occurs while were are 113 * already in an exception, such as window overflow/underflow exception, 114 * or 'expected' exceptions, for example memory exception when we were trying 115 * to read data from an invalid address in user space. 116 * 117 * Note that this vector is never invoked for level-1 interrupts, because such 118 * interrupts are disabled (masked) when PS.EXCM is set. 119 * 120 * We decode the exception and take the appropriate action. However, the 121 * double exception vector is much more careful, because a lot more error 122 * cases go through the double exception vector than through the user and 123 * kernel exception vectors. 124 * 125 * Occasionally, the kernel expects a double exception to occur. This usually 126 * happens when accessing user-space memory with the user's permissions 127 * (l32e/s32e instructions). The kernel state, though, is not always suitable 128 * for immediate transfer of control to handle_double, where "normal" exception 129 * processing occurs. Also in kernel mode, TLB misses can occur if accessing 130 * vmalloc memory, possibly requiring repair in a double exception handler. 131 * 132 * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as 133 * a boolean variable and a pointer to a fixup routine. If the variable 134 * EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of 135 * zero indicates to use the default kernel/user exception handler. 136 * There is only one exception, when the value is identical to the exc_table 137 * label, the kernel is in trouble. This mechanism is used to protect critical 138 * sections, mainly when the handler writes to the stack to assert the stack 139 * pointer is valid. Once the fixup/default handler leaves that area, the 140 * EXC_TABLE_FIXUP variable is reset to the fixup handler or zero. 141 * 142 * Procedures wishing to use this mechanism should set EXC_TABLE_FIXUP to the 143 * nonzero address of a fixup routine before it could cause a double exception 144 * and reset it before it returns. 145 * 146 * Some other things to take care of when a fast exception handler doesn't 147 * specify a particular fixup handler but wants to use the default handlers: 148 * 149 * - The original stack pointer (in a1) must not be modified. The fast 150 * exception handler should only use a2 as the stack pointer. 151 * 152 * - If the fast handler manipulates the stack pointer (in a2), it has to 153 * register a valid fixup handler and cannot use the default handlers. 154 * 155 * - The handler can use any other generic register from a3 to a15, but it 156 * must save the content of these registers to stack (PT_AREG3...PT_AREGx) 157 * 158 * - These registers must be saved before a double exception can occur. 159 * 160 * - If we ever implement handling signals while in double exceptions, the 161 * number of registers a fast handler has saved (excluding a0 and a1) must 162 * be written to PT_AREG1. (1 if only a3 is used, 2 for a3 and a4, etc. ) 163 * 164 * The fixup handlers are special handlers: 165 * 166 * - Fixup entry conditions differ from regular exceptions: 167 * 168 * a0: DEPC 169 * a1: a1 170 * a2: trashed, original value in EXC_TABLE_DOUBLE_A2 171 * a3: exctable 172 * depc: a0 173 * excsave_1: a3 174 * 175 * - When the kernel enters the fixup handler, it still assumes it is in a 176 * critical section, so EXC_TABLE_FIXUP variable is set to exc_table. 177 * The fixup handler, therefore, has to re-register itself as the fixup 178 * handler before it returns from the double exception. 179 * 180 * - Fixup handler can share the same exception frame with the fast handler. 181 * The kernel stack pointer is not changed when entering the fixup handler. 182 * 183 * - Fixup handlers can jump to the default kernel and user exception 184 * handlers. Before it jumps, though, it has to setup a exception frame 185 * on stack. Because the default handler resets the register fixup handler 186 * the fixup handler must make sure that the default handler returns to 187 * it instead of the exception address, so it can re-register itself as 188 * the fixup handler. 189 * 190 * In case of a critical condition where the kernel cannot recover, we jump 191 * to unrecoverable_exception with the following entry conditions. 192 * All registers a0...a15 are unchanged from the last exception, except: 193 * 194 * a0: last address before we jumped to the unrecoverable_exception. 195 * excsave_1: a0 196 * 197 * 198 * See the handle_alloca_user and spill_registers routines for example clients. 199 * 200 * FIXME: Note: we currently don't allow signal handling coming from a double 201 * exception, so the item markt with (*) is not required. 202 */ 203 204 .section .DoubleExceptionVector.text, "ax" 205 .begin literal_prefix .DoubleExceptionVector 206 207ENTRY(_DoubleExceptionVector) 208 209 /* Deliberately destroy excsave (don't assume it's value was valid). */ 210 211 wsr a3, excsave1 # save a3 212 213 /* Check for kernel double exception (usually fatal). */ 214 215 rsr a3, ps 216 _bbci.l a3, PS_UM_BIT, .Lksp 217 218 /* Check if we are currently handling a window exception. */ 219 /* Note: We don't need to indicate that we enter a critical section. */ 220 221 xsr a0, depc # get DEPC, save a0 222 223 movi a3, XCHAL_WINDOW_VECTORS_VADDR 224 _bltu a0, a3, .Lfixup 225 addi a3, a3, WINDOW_VECTORS_SIZE 226 _bgeu a0, a3, .Lfixup 227 228 /* Window overflow/underflow exception. Get stack pointer. */ 229 230 mov a3, a2 231 /* This explicit literal and the following references to it are made 232 * in order to fit DoubleExceptionVector.literals into the available 233 * 16-byte gap before DoubleExceptionVector.text in the absence of 234 * link time relaxation. See kernel/vmlinux.lds.S 235 */ 236 .literal .Lexc_table, exc_table 237 l32r a2, .Lexc_table 238 l32i a2, a2, EXC_TABLE_KSTK 239 240 /* Check for overflow/underflow exception, jump if overflow. */ 241 242 _bbci.l a0, 6, .Lovfl 243 244 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ 245 246 /* Restart window underflow exception. 247 * We return to the instruction in user space that caused the window 248 * underflow exception. Therefore, we change window base to the value 249 * before we entered the window underflow exception and prepare the 250 * registers to return as if we were coming from a regular exception 251 * by changing depc (in a0). 252 * Note: We can trash the current window frame (a0...a3) and depc! 253 */ 254 255 wsr a2, depc # save stack pointer temporarily 256 rsr a0, ps 257 extui a0, a0, PS_OWB_SHIFT, 4 258 wsr a0, windowbase 259 rsync 260 261 /* We are now in the previous window frame. Save registers again. */ 262 263 xsr a2, depc # save a2 and get stack pointer 264 s32i a0, a2, PT_AREG0 265 266 wsr a3, excsave1 # save a3 267 l32r a3, .Lexc_table 268 269 rsr a0, exccause 270 s32i a0, a2, PT_DEPC # mark it as a regular exception 271 addx4 a0, a0, a3 272 l32i a0, a0, EXC_TABLE_FAST_USER 273 jx a0 274 275.Lfixup:/* Check for a fixup handler or if we were in a critical section. */ 276 277 /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */ 278 279 l32r a3, .Lexc_table 280 s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable 281 282 /* Enter critical section. */ 283 284 l32i a2, a3, EXC_TABLE_FIXUP 285 s32i a3, a3, EXC_TABLE_FIXUP 286 beq a2, a3, .Lunrecoverable_fixup # critical! 287 beqz a2, .Ldflt # no handler was registered 288 289 /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */ 290 291 jx a2 292 293.Ldflt: /* Get stack pointer. */ 294 295 l32i a3, a3, EXC_TABLE_DOUBLE_SAVE 296 addi a2, a3, -PT_USER_SIZE 297 298.Lovfl: /* Jump to default handlers. */ 299 300 /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ 301 302 xsr a3, depc 303 s32i a0, a2, PT_DEPC 304 s32i a3, a2, PT_AREG0 305 306 /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ 307 308 l32r a3, .Lexc_table 309 rsr a0, exccause 310 addx4 a0, a0, a3 311 l32i a0, a0, EXC_TABLE_FAST_USER 312 jx a0 313 314 /* 315 * We only allow the ITLB miss exception if we are in kernel space. 316 * All other exceptions are unexpected and thus unrecoverable! 317 */ 318 319#ifdef CONFIG_MMU 320 .extern fast_second_level_miss_double_kernel 321 322.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ 323 324 rsr a3, exccause 325 beqi a3, EXCCAUSE_ITLB_MISS, 1f 326 addi a3, a3, -EXCCAUSE_DTLB_MISS 327 bnez a3, .Lunrecoverable 3281: movi a3, fast_second_level_miss_double_kernel 329 jx a3 330#else 331.equ .Lksp, .Lunrecoverable 332#endif 333 334 /* Critical! We can't handle this situation. PANIC! */ 335 336 .extern unrecoverable_exception 337 338.Lunrecoverable_fixup: 339 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE 340 xsr a0, depc 341 342.Lunrecoverable: 343 rsr a3, excsave1 344 wsr a0, excsave1 345 movi a0, unrecoverable_exception 346 callx0 a0 347 348 .end literal_prefix 349 350ENDPROC(_DoubleExceptionVector) 351 352/* 353 * Debug interrupt vector 354 * 355 * There is not much space here, so simply jump to another handler. 356 * EXCSAVE[DEBUGLEVEL] has been set to that handler. 357 */ 358 359 .section .DebugInterruptVector.text, "ax" 360 361ENTRY(_DebugInterruptVector) 362 363 xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL 364 jx a0 365 366ENDPROC(_DebugInterruptVector) 367 368 369 370/* 371 * Medium priority level interrupt vectors 372 * 373 * Each takes less than 16 (0x10) bytes, no literals, by placing 374 * the extra 8 bytes that would otherwise be required in the window 375 * vectors area where there is space. With relocatable vectors, 376 * all vectors are within ~ 4 kB range of each other, so we can 377 * simply jump (J) to another vector without having to use JX. 378 * 379 * common_exception code gets current IRQ level in PS.INTLEVEL 380 * and preserves it for the IRQ handling time. 381 */ 382 383 .macro irq_entry_level level 384 385 .if XCHAL_EXCM_LEVEL >= \level 386 .section .Level\level\()InterruptVector.text, "ax" 387ENTRY(_Level\level\()InterruptVector) 388 wsr a0, epc1 389 rsr a0, epc\level 390 xsr a0, epc1 391 # branch to user or kernel vector 392 j _SimulateUserKernelVectorException 393 .endif 394 395 .endm 396 397 irq_entry_level 2 398 irq_entry_level 3 399 irq_entry_level 4 400 irq_entry_level 5 401 irq_entry_level 6 402 403 404/* Window overflow and underflow handlers. 405 * The handlers must be 64 bytes apart, first starting with the underflow 406 * handlers underflow-4 to underflow-12, then the overflow handlers 407 * overflow-4 to overflow-12. 408 * 409 * Note: We rerun the underflow handlers if we hit an exception, so 410 * we try to access any page that would cause a page fault early. 411 */ 412 413#define ENTRY_ALIGN64(name) \ 414 .globl name; \ 415 .align 64; \ 416 name: 417 418 .section .WindowVectors.text, "ax" 419 420 421/* 4-Register Window Overflow Vector (Handler) */ 422 423ENTRY_ALIGN64(_WindowOverflow4) 424 425 s32e a0, a5, -16 426 s32e a1, a5, -12 427 s32e a2, a5, -8 428 s32e a3, a5, -4 429 rfwo 430 431ENDPROC(_WindowOverflow4) 432 433 434#if XCHAL_EXCM_LEVEL >= 2 435 /* Not a window vector - but a convenient location 436 * (where we know there's space) for continuation of 437 * medium priority interrupt dispatch code. 438 * On entry here, a0 contains PS, and EPC2 contains saved a0: 439 */ 440 .align 4 441_SimulateUserKernelVectorException: 442 wsr a0, excsave2 443 movi a0, 4 # LEVEL1_INTERRUPT cause 444 wsr a0, exccause 445 rsr a0, ps 446 bbsi.l a0, PS_UM_BIT, 1f # branch if user mode 447 rsr a0, excsave2 # restore a0 448 j _KernelExceptionVector # simulate kernel vector exception 4491: rsr a0, excsave2 # restore a0 450 j _UserExceptionVector # simulate user vector exception 451#endif 452 453 454/* 4-Register Window Underflow Vector (Handler) */ 455 456ENTRY_ALIGN64(_WindowUnderflow4) 457 458 l32e a0, a5, -16 459 l32e a1, a5, -12 460 l32e a2, a5, -8 461 l32e a3, a5, -4 462 rfwu 463 464ENDPROC(_WindowUnderflow4) 465 466/* 8-Register Window Overflow Vector (Handler) */ 467 468ENTRY_ALIGN64(_WindowOverflow8) 469 470 s32e a0, a9, -16 471 l32e a0, a1, -12 472 s32e a2, a9, -8 473 s32e a1, a9, -12 474 s32e a3, a9, -4 475 s32e a4, a0, -32 476 s32e a5, a0, -28 477 s32e a6, a0, -24 478 s32e a7, a0, -20 479 rfwo 480 481ENDPROC(_WindowOverflow8) 482 483/* 8-Register Window Underflow Vector (Handler) */ 484 485ENTRY_ALIGN64(_WindowUnderflow8) 486 487 l32e a1, a9, -12 488 l32e a0, a9, -16 489 l32e a7, a1, -12 490 l32e a2, a9, -8 491 l32e a4, a7, -32 492 l32e a3, a9, -4 493 l32e a5, a7, -28 494 l32e a6, a7, -24 495 l32e a7, a7, -20 496 rfwu 497 498ENDPROC(_WindowUnderflow8) 499 500/* 12-Register Window Overflow Vector (Handler) */ 501 502ENTRY_ALIGN64(_WindowOverflow12) 503 504 s32e a0, a13, -16 505 l32e a0, a1, -12 506 s32e a1, a13, -12 507 s32e a2, a13, -8 508 s32e a3, a13, -4 509 s32e a4, a0, -48 510 s32e a5, a0, -44 511 s32e a6, a0, -40 512 s32e a7, a0, -36 513 s32e a8, a0, -32 514 s32e a9, a0, -28 515 s32e a10, a0, -24 516 s32e a11, a0, -20 517 rfwo 518 519ENDPROC(_WindowOverflow12) 520 521/* 12-Register Window Underflow Vector (Handler) */ 522 523ENTRY_ALIGN64(_WindowUnderflow12) 524 525 l32e a1, a13, -12 526 l32e a0, a13, -16 527 l32e a11, a1, -12 528 l32e a2, a13, -8 529 l32e a4, a11, -48 530 l32e a8, a11, -32 531 l32e a3, a13, -4 532 l32e a5, a11, -44 533 l32e a6, a11, -40 534 l32e a7, a11, -36 535 l32e a9, a11, -28 536 l32e a10, a11, -24 537 l32e a11, a11, -20 538 rfwu 539 540ENDPROC(_WindowUnderflow12) 541 542 .text 543