2  * arch/xtensa/kernel/entry.S
 
   4  * Low-level exception handling
 
   6  * This file is subject to the terms and conditions of the GNU General Public
 
   7  * License.  See the file "COPYING" in the main directory of this archive
 
  10  * Copyright (C) 2004-2007 by Tensilica Inc.
 
  12  * Chris Zankel <chris@zankel.net>
 
  16 #include <linux/linkage.h>
 
  17 #include <asm/asm-offsets.h>
 
  18 #include <asm/processor.h>
 
  19 #include <asm/thread_info.h>
 
  20 #include <asm/uaccess.h>
 
  21 #include <asm/unistd.h>
 
  22 #include <asm/ptrace.h>
 
  23 #include <asm/current.h>
 
  24 #include <asm/pgtable.h>
 
  26 #include <asm/signal.h>
 
  27 #include <asm/tlbflush.h>
 
  28 #include <asm/variant/tie-asm.h>
 
  30 /* Unimplemented features. */
 
  32 #undef KERNEL_STACK_OVERFLOW_CHECK
 
  33 #undef PREEMPTIBLE_KERNEL
 
  34 #undef ALLOCA_EXCEPTION_IN_IRAM
 
  42  * Macro to find first bit set in WINDOWBASE from the left + 1
 
  49         .macro ffs_ws bit mask
 
  52         nsau    \bit, \mask                     # 32-WSBITS ... 31 (32 iff 0)
 
  53         addi    \bit, \bit, WSBITS - 32 + 1     # uppest bit set -> return 1
 
  57         _bltui  \mask, 0x10000, 99f
 
  59         extui   \mask, \mask, 16, 16
 
  62 99:     _bltui  \mask, 0x100, 99f
 
  66 99:     _bltui  \mask, 0x10, 99f
 
  69 99:     _bltui  \mask, 0x4, 99f
 
  72 99:     _bltui  \mask, 0x2, 99f
 
  79 /* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
 
  82  * First-level exception handler for user exceptions.
 
  83  * Save some special registers, extra states and all registers in the AR
 
  84  * register file that were in use in the user task, and jump to the common
 
  86  * We save SAR (used to calculate WMASK), and WB and WS (we don't have to
 
  87  * save them for kernel exceptions).
 
  89  * Entry condition for user_exception:
 
  91  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
  93  *   a2:        new stack pointer, original value in depc
 
  95  *   depc:      a2, original value saved on stack (PT_DEPC)
 
  98  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
  99  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
 101  * Entry condition for _user_exception:
 
 103  *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
 
 104  *   excsave has been restored, and
 
 105  *   stack pointer (a1) has been set.
 
 107  * Note: _user_exception might be at an odd adress. Don't use call0..call12
 
 110 ENTRY(user_exception)
 
 112         /* Save a2, a3, and depc, restore excsave_1 and set SP. */
 
 116         s32i    a1, a2, PT_AREG1
 
 117         s32i    a0, a2, PT_AREG2
 
 118         s32i    a3, a2, PT_AREG3
 
 121         .globl _user_exception
 
 124         /* Save SAR and turn off single stepping */
 
 130         s32i    a2, a1, PT_ICOUNTLEVEL
 
 132         /* Rotate ws so that the current windowbase is at bit0. */
 
 133         /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
 138         s32i    a2, a1, PT_WINDOWBASE
 
 139         s32i    a3, a1, PT_WINDOWSTART
 
 140         slli    a2, a3, 32-WSBITS
 
 142         srli    a2, a2, 32-WSBITS
 
 143         s32i    a2, a1, PT_WMASK        # needed for restoring registers
 
 145         /* Save only live registers. */
 
 148         s32i    a4, a1, PT_AREG4
 
 149         s32i    a5, a1, PT_AREG5
 
 150         s32i    a6, a1, PT_AREG6
 
 151         s32i    a7, a1, PT_AREG7
 
 153         s32i    a8, a1, PT_AREG8
 
 154         s32i    a9, a1, PT_AREG9
 
 155         s32i    a10, a1, PT_AREG10
 
 156         s32i    a11, a1, PT_AREG11
 
 158         s32i    a12, a1, PT_AREG12
 
 159         s32i    a13, a1, PT_AREG13
 
 160         s32i    a14, a1, PT_AREG14
 
 161         s32i    a15, a1, PT_AREG15
 
 162         _bnei   a2, 1, 1f               # only one valid frame?
 
 164         /* Only one valid frame, skip saving regs. */
 
 168         /* Save the remaining registers.
 
 169          * We have to save all registers up to the first '1' from
 
 170          * the right, except the current frame (bit 0).
 
 171          * Assume a2 is:  001001000110001
 
 172          * All register frames starting from the top field to the marked '1'
 
 176 1:      addi    a3, a2, -1              # eliminate '1' in bit 0: yyyyxxww0
 
 177         neg     a3, a3                  # yyyyxxww0 -> YYYYXXWW1+1
 
 178         and     a3, a3, a2              # max. only one bit is set
 
 180         /* Find number of frames to save */
 
 182         ffs_ws  a0, a3                  # number of frames to the '1' from left
 
 184         /* Store information into WMASK:
 
 185          * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,
 
 186          * bits 4...: number of valid 4-register frames
 
 189         slli    a3, a0, 4               # number of frames to save in bits 8..4
 
 190         extui   a2, a2, 0, 4            # mask for the first 16 registers
 
 192         s32i    a2, a1, PT_WMASK        # needed when we restore the reg-file
 
 194         /* Save 4 registers at a time */
 
 197         s32i    a0, a5, PT_AREG_END - 16
 
 198         s32i    a1, a5, PT_AREG_END - 12
 
 199         s32i    a2, a5, PT_AREG_END - 8
 
 200         s32i    a3, a5, PT_AREG_END - 4
 
 205         /* WINDOWBASE still in SAR! */
 
 207         rsr     a2, SAR                 # original WINDOWBASE
 
 211         wsr     a3, WINDOWSTART         # set corresponding WINDOWSTART bit
 
 212         wsr     a2, WINDOWBASE          # and WINDOWSTART
 
 215         /* We are back to the original stack pointer (a1) */
 
 217 2:      /* Now, jump to the common exception handler. */
 
 223  * First-level exit handler for kernel exceptions
 
 224  * Save special registers and the live window frame.
 
 225  * Note: Even though we changes the stack pointer, we don't have to do a
 
 226  *       MOVSP here, as we do that when we return from the exception.
 
 227  *       (See comment in the kernel exception exit code)
 
 229  * Entry condition for kernel_exception:
 
 231  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
 233  *   a2:        new stack pointer, original in DEPC
 
 235  *   depc:      a2, original value saved on stack (PT_DEPC)
 
 238  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
 239  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
 241  * Entry condition for _kernel_exception:
 
 243  *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
 
 244  *   excsave has been restored, and
 
 245  *   stack pointer (a1) has been set.
 
 247  * Note: _kernel_exception might be at an odd adress. Don't use call0..call12
 
 250 ENTRY(kernel_exception)
 
 252         /* Save a0, a2, a3, DEPC and set SP. */
 
 254         xsr     a3, EXCSAVE_1           # restore a3, excsave_1
 
 255         rsr     a0, DEPC                # get a2
 
 256         s32i    a1, a2, PT_AREG1
 
 257         s32i    a0, a2, PT_AREG2
 
 258         s32i    a3, a2, PT_AREG3
 
 261         .globl _kernel_exception
 
 264         /* Save SAR and turn off single stepping */
 
 270         s32i    a2, a1, PT_ICOUNTLEVEL
 
 272         /* Rotate ws so that the current windowbase is at bit0. */
 
 273         /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
 275         rsr     a2, WINDOWBASE          # don't need to save these, we only
 
 276         rsr     a3, WINDOWSTART         # need shifted windowstart: windowmask
 
 278         slli    a2, a3, 32-WSBITS
 
 280         srli    a2, a2, 32-WSBITS
 
 281         s32i    a2, a1, PT_WMASK        # needed for kernel_exception_exit
 
 283         /* Save only the live window-frame */
 
 286         s32i    a4, a1, PT_AREG4
 
 287         s32i    a5, a1, PT_AREG5
 
 288         s32i    a6, a1, PT_AREG6
 
 289         s32i    a7, a1, PT_AREG7
 
 291         s32i    a8, a1, PT_AREG8
 
 292         s32i    a9, a1, PT_AREG9
 
 293         s32i    a10, a1, PT_AREG10
 
 294         s32i    a11, a1, PT_AREG11
 
 296         s32i    a12, a1, PT_AREG12
 
 297         s32i    a13, a1, PT_AREG13
 
 298         s32i    a14, a1, PT_AREG14
 
 299         s32i    a15, a1, PT_AREG15
 
 303 #ifdef KERNEL_STACK_OVERFLOW_CHECK
 
 305         /*  Stack overflow check, for debugging  */
 
 306         extui   a2, a1, TASK_SIZE_BITS,XX
 
 308         _bge    a2, a3, out_of_stack_panic
 
 313  * This is the common exception handler.
 
 314  * We get here from the user exception handler or simply by falling through
 
 315  * from the kernel exception handler.
 
 316  * Save the remaining special registers, switch to kernel mode, and jump
 
 317  * to the second-level exception handler.
 
 323         /* Save some registers, disable loops and clear the syscall flag. */
 
 327         s32i    a2, a1, PT_DEBUGCAUSE
 
 332         s32i    a2, a1, PT_SYSCALL
 
 334         s32i    a3, a1, PT_EXCVADDR
 
 336         s32i    a2, a1, PT_LCOUNT
 
 338         /* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
 343         s32i    a0, a1, PT_EXCCAUSE
 
 344         s32i    a3, a2, EXC_TABLE_FIXUP
 
 346         /* All unrecoverable states are saved on stack, now, and a1 is valid,
 
 347          * so we can allow exceptions and interrupts (*) again.
 
 348          * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
 
 350          * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before
 
 351          *     (interrupts disabled) and if this exception is not an interrupt.
 
 357         extui   a3, a3, 0, 1            # a3 = PS.INTLEVEL[0]
 
 358         moveqz  a3, a2, a0              # a3 = 1 iff interrupt exception
 
 359         movi    a2, 1 << PS_WOE_BIT
 
 364         s32i    a3, a1, PT_PS           # save ps
 
 366         /* Save LBEG, LEND */
 
 373         /* Save optional registers. */
 
 375         save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
 
 377         /* Go to second-level dispatcher. Set up parameters to pass to the
 
 378          * exception handler and call the exception handler.
 
 382         mov     a6, a1                  # pass stack frame
 
 383         mov     a7, a0                  # pass EXCCAUSE
 
 385         l32i    a4, a4, EXC_TABLE_DEFAULT               # load handler
 
 387         /* Call the second-level handler */
 
 391         /* Jump here for exception exit */
 
 393 common_exception_return:
 
 395         /* Jump if we are returning from kernel exceptions. */
 
 397 1:      l32i    a3, a1, PT_PS
 
 398         _bbci.l a3, PS_UM_BIT, 4f
 
 400         /* Specific to a user exception exit:
 
 401          * We need to check some flags for signal handling and rescheduling,
 
 402          * and have to restore WB and WS, extra states, and all registers
 
 403          * in the register file that were in use in the user task.
 
 404          * Note that we don't disable interrupts here. 
 
 407         GET_THREAD_INFO(a2,a1)
 
 408         l32i    a4, a2, TI_FLAGS
 
 410         _bbsi.l a4, TIF_NEED_RESCHED, 3f
 
 411         _bbci.l a4, TIF_SIGPENDING, 4f
 
 414         bgeui   a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
 
 416         /* Call do_signal() */
 
 418         movi    a4, do_signal   # int do_signal(struct pt_regs*, sigset_t*)
 
 426         movi    a4, schedule    # void schedule (void)
 
 430 4:      /* Restore optional registers. */
 
 432         load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
 
 434         wsr     a3, PS          /* disable interrupts */
 
 436         _bbci.l a3, PS_UM_BIT, kernel_exception_exit
 
 440         /* Restore the state of the task and return from the exception. */
 
 442         /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
 
 444         l32i    a2, a1, PT_WINDOWBASE
 
 445         l32i    a3, a1, PT_WINDOWSTART
 
 446         wsr     a1, DEPC                # use DEPC as temp storage
 
 447         wsr     a3, WINDOWSTART         # restore WINDOWSTART
 
 448         ssr     a2                      # preserve user's WB in the SAR
 
 449         wsr     a2, WINDOWBASE          # switch to user's saved WB
 
 451         rsr     a1, DEPC                # restore stack pointer
 
 452         l32i    a2, a1, PT_WMASK        # register frames saved (in bits 4...9)
 
 453         rotw    -1                      # we restore a4..a7
 
 454         _bltui  a6, 16, 1f              # only have to restore current window?
 
 456         /* The working registers are a0 and a3.  We are restoring to
 
 457          * a4..a7.  Be careful not to destroy what we have just restored.
 
 458          * Note: wmask has the format YYYYM:
 
 459          *       Y: number of registers saved in groups of 4
 
 460          *       M: 4 bit mask of first 16 registers
 
 466 2:      rotw    -1                      # a0..a3 become a4..a7
 
 467         addi    a3, a7, -4*4            # next iteration
 
 468         addi    a2, a6, -16             # decrementing Y in WMASK
 
 469         l32i    a4, a3, PT_AREG_END + 0
 
 470         l32i    a5, a3, PT_AREG_END + 4
 
 471         l32i    a6, a3, PT_AREG_END + 8
 
 472         l32i    a7, a3, PT_AREG_END + 12
 
 475         /* Clear unrestored registers (don't leak anything to user-land */
 
 477 1:      rsr     a0, WINDOWBASE
 
 481         extui   a3, a3, 0, WBBITS
 
 491         /* We are back were we were when we started.
 
 492          * Note: a2 still contains WMASK (if we've returned to the original
 
 493          *       frame where we had loaded a2), or at least the lower 4 bits
 
 494          *       (if we have restored WSBITS-1 frames).
 
 497 2:      j       common_exception_exit
 
 499         /* This is the kernel exception exit.
 
 500          * We avoided to do a MOVSP when we entered the exception, but we
 
 501          * have to do it here.
 
 504 kernel_exception_exit:
 
 506 #ifdef PREEMPTIBLE_KERNEL
 
 508 #ifdef CONFIG_PREEMPT
 
 511          * Note: We've just returned from a call4, so we have
 
 512          * at least 4 addt'l regs.
 
 515         /* Check current_thread_info->preempt_count */
 
 518         l32i    a3, a2, TI_PREEMPT
 
 521         l32i    a2, a2, TI_FLAGS
 
 529         /* Check if we have to do a movsp.
 
 531          * We only have to do a movsp if the previous window-frame has
 
 532          * been spilled to the *temporary* exception stack instead of the
 
 533          * task's stack. This is the case if the corresponding bit in
 
 534          * WINDOWSTART for the previous window-frame was set before
 
 535          * (not spilled) but is zero now (spilled).
 
 536          * If this bit is zero, all other bits except the one for the
 
 537          * current window frame are also zero. So, we can use a simple test:
 
 538          * 'and' WINDOWSTART and WINDOWSTART-1:
 
 540          *  (XXXXXX1[0]* - 1) AND XXXXXX1[0]* = XXXXXX0[0]*
 
 542          * The result is zero only if one bit was set.
 
 544          * (Note: We might have gone through several task switches before
 
 545          *        we come back to the current task, so WINDOWBASE might be
 
 546          *        different from the time the exception occurred.)
 
 549         /* Test WINDOWSTART before and after the exception.
 
 550          * We actually have WMASK, so we only have to test if it is 1 or not.
 
 553         l32i    a2, a1, PT_WMASK
 
 554         _beqi   a2, 1, common_exception_exit    # Spilled before exception,jump
 
 556         /* Test WINDOWSTART now. If spilled, do the movsp */
 
 561         _bnez   a3, common_exception_exit
 
 563         /* Do a movsp (we returned from a call4, so we have at least a0..a7) */
 
 568         s32i    a3, a1, PT_SIZE+0
 
 569         s32i    a4, a1, PT_SIZE+4
 
 572         s32i    a3, a1, PT_SIZE+8
 
 573         s32i    a4, a1, PT_SIZE+12
 
 575         /* Common exception exit.
 
 576          * We restore the special register and the current window frame, and
 
 577          * return from the exception.
 
 579          * Note: We expect a2 to hold PT_WMASK
 
 582 common_exception_exit:
 
 584         /* Restore address registers. */
 
 587         l32i    a4,  a1, PT_AREG4
 
 588         l32i    a5,  a1, PT_AREG5
 
 589         l32i    a6,  a1, PT_AREG6
 
 590         l32i    a7,  a1, PT_AREG7
 
 592         l32i    a8,  a1, PT_AREG8
 
 593         l32i    a9,  a1, PT_AREG9
 
 594         l32i    a10, a1, PT_AREG10
 
 595         l32i    a11, a1, PT_AREG11
 
 597         l32i    a12, a1, PT_AREG12
 
 598         l32i    a13, a1, PT_AREG13
 
 599         l32i    a14, a1, PT_AREG14
 
 600         l32i    a15, a1, PT_AREG15
 
 602         /* Restore PC, SAR */
 
 604 1:      l32i    a2, a1, PT_PC
 
 609         /* Restore LBEG, LEND, LCOUNT */
 
 614         l32i    a2, a1, PT_LCOUNT
 
 618         /* We control single stepping through the ICOUNTLEVEL register. */
 
 620         l32i    a2, a1, PT_ICOUNTLEVEL
 
 625         /* Check if it was double exception. */
 
 628         l32i    a3, a1, PT_AREG3
 
 629         l32i    a2, a1, PT_AREG2
 
 630         _bgeui  a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
 632         /* Restore a0...a3 and return */
 
 634         l32i    a0, a1, PT_AREG0
 
 635         l32i    a1, a1, PT_AREG1
 
 639         l32i    a0, a1, PT_AREG0
 
 640         l32i    a1, a1, PT_AREG1
 
 644  * Debug exception handler.
 
 646  * Currently, we don't support KGDB, so only user application can be debugged.
 
 648  * When we get here,  a0 is trashed and saved to excsave[debuglevel]
 
 651 ENTRY(debug_exception)
 
 653         rsr     a0, EPS + XCHAL_DEBUGLEVEL
 
 654         bbsi.l  a0, PS_EXCM_BIT, 1f     # exception mode
 
 656         /* Set EPC_1 and EXCCAUSE */
 
 658         wsr     a2, DEPC                # save a2 temporarily
 
 659         rsr     a2, EPC + XCHAL_DEBUGLEVEL
 
 662         movi    a2, EXCCAUSE_MAPPED_DEBUG
 
 665         /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
 
 667         movi    a2, 1 << PS_EXCM_BIT
 
 669         movi    a0, debug_exception     # restore a3, debug jump vector
 
 671         xsr     a0, EXCSAVE + XCHAL_DEBUGLEVEL
 
 673         /* Switch to kernel/user stack, restore jump vector, and save a0 */
 
 675         bbsi.l  a2, PS_UM_BIT, 2f       # jump if user mode
 
 677         addi    a2, a1, -16-PT_SIZE     # assume kernel stack
 
 678         s32i    a0, a2, PT_AREG0
 
 680         s32i    a1, a2, PT_AREG1
 
 681         s32i    a0, a2, PT_DEPC         # mark it as a regular exception
 
 683         s32i    a3, a2, PT_AREG3
 
 684         s32i    a0, a2, PT_AREG2
 
 689         l32i    a2, a2, EXC_TABLE_KSTK  # load kernel stack pointer
 
 690         s32i    a0, a2, PT_AREG0
 
 692         s32i    a1, a2, PT_AREG1
 
 695         s32i    a3, a2, PT_AREG3
 
 696         s32i    a0, a2, PT_AREG2
 
 700         /* Debug exception while in exception mode. */
 
 705  * We get here in case of an unrecoverable exception.
 
 706  * The only thing we can do is to be nice and print a panic message.
 
 707  * We only produce a single stack frame for panic, so ???
 
 712  *   - a0 contains the caller address; original value saved in excsave1.
 
 713  *   - the original a0 contains a valid return address (backtrace) or 0.
 
 714  *   - a2 contains a valid stackpointer
 
 718  *   - If the stack pointer could be invalid, the caller has to setup a
 
 719  *     dummy stack pointer (e.g. the stack of the init_task)
 
 721  *   - If the return address could be invalid, the caller has to set it
 
 722  *     to 0, so the backtrace would stop.
 
 727         .ascii "Unrecoverable error in exception handler\0"
 
 729 ENTRY(unrecoverable_exception)
 
 738         movi    a1, (1 << PS_WOE_BIT) | 1
 
 744         addi    a1, a1, PT_REGS_OFFSET
 
 747         movi    a6, unrecoverable_text
 
 754 /* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
 
 757  * Fast-handler for alloca exceptions
 
 759  *  The ALLOCA handler is entered when user code executes the MOVSP
 
 760  *  instruction and the caller's frame is not in the register file.
 
 761  *  In this case, the caller frame's a0..a3 are on the stack just
 
 762  *  below sp (a1), and this handler moves them.
 
 764  *  For "MOVSP <ar>,<as>" without destination register a1, this routine
 
 765  *  simply moves the value from <as> to <ar> without moving the save area.
 
 769  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
 771  *   a2:        new stack pointer, original in DEPC
 
 773  *   depc:      a2, original value saved on stack (PT_DEPC)
 
 776  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
 777  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
 781 #define _EXTUI_MOVSP_SRC(ar)    extui ar, ar, 4, 4
 
 782 #define _EXTUI_MOVSP_DST(ar)    extui ar, ar, 0, 4
 
 784 #define _EXTUI_MOVSP_SRC(ar)    extui ar, ar, 0, 4
 
 785 #define _EXTUI_MOVSP_DST(ar)    extui ar, ar, 4, 4
 
 790         /* We shouldn't be in a double exception. */
 
 793         _bgeui  a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
 
 795         rsr     a0, DEPC                # get a2
 
 796         s32i    a4, a2, PT_AREG4        # save a4 and
 
 797         s32i    a0, a2, PT_AREG2        # a2 to stack
 
 799         /* Exit critical section. */
 
 802         s32i    a0, a3, EXC_TABLE_FIXUP
 
 804         /* Restore a3, excsave_1 */
 
 806         xsr     a3, EXCSAVE_1           # make sure excsave_1 is valid for dbl.
 
 807         rsr     a4, EPC_1               # get exception address
 
 808         s32i    a3, a2, PT_AREG3        # save a3 to stack
 
 810 #ifdef ALLOCA_EXCEPTION_IN_IRAM
 
 811 #error  iram not supported
 
 813         /* Note: l8ui not allowed in IRAM/IROM!! */
 
 814         l8ui    a0, a4, 1               # read as(src) from MOVSP instruction
 
 817         _EXTUI_MOVSP_SRC(a0)            # extract source register number
 
 823         movi    a0, unrecoverable_exception
 
 828         l32i    a3, a2, PT_AREG0;       _j 1f;  .align 8
 
 829         mov     a3, a1;                 _j 1f;  .align 8
 
 830         l32i    a3, a2, PT_AREG2;       _j 1f;  .align 8
 
 831         l32i    a3, a2, PT_AREG3;       _j 1f;  .align 8
 
 832         l32i    a3, a2, PT_AREG4;       _j 1f;  .align 8
 
 833         mov     a3, a5;                 _j 1f;  .align 8
 
 834         mov     a3, a6;                 _j 1f;  .align 8
 
 835         mov     a3, a7;                 _j 1f;  .align 8
 
 836         mov     a3, a8;                 _j 1f;  .align 8
 
 837         mov     a3, a9;                 _j 1f;  .align 8
 
 838         mov     a3, a10;                _j 1f;  .align 8
 
 839         mov     a3, a11;                _j 1f;  .align 8
 
 840         mov     a3, a12;                _j 1f;  .align 8
 
 841         mov     a3, a13;                _j 1f;  .align 8
 
 842         mov     a3, a14;                _j 1f;  .align 8
 
 843         mov     a3, a15;                _j 1f;  .align 8
 
 847 #ifdef ALLOCA_EXCEPTION_IN_IRAM
 
 848 #error  iram not supported
 
 850         l8ui    a0, a4, 0               # read ar(dst) from MOVSP instruction
 
 852         addi    a4, a4, 3               # step over movsp
 
 853         _EXTUI_MOVSP_DST(a0)            # extract destination register
 
 854         wsr     a4, EPC_1               # save new epc_1
 
 856         _bnei   a0, 1, 1f               # no 'movsp a1, ax': jump
 
 858         /* Move the save area. This implies the use of the L32E
 
 859          * and S32E instructions, because this move must be done with
 
 860          * the user's PS.RING privilege levels, not with ring 0
 
 861          * (kernel's) privileges currently active with PS.EXCM
 
 862          * set. Note that we have stil registered a fixup routine with the
 
 863          * double exception vector in case a double exception occurs.
 
 866         /* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
 
 877         /* Restore stack-pointer and all the other saved registers. */
 
 881         l32i    a4, a2, PT_AREG4
 
 882         l32i    a3, a2, PT_AREG3
 
 883         l32i    a0, a2, PT_AREG0
 
 884         l32i    a2, a2, PT_AREG2
 
 887         /*  MOVSP <at>,<as>  was invoked with <at> != a1.
 
 888          *  Because the stack pointer is not being modified,
 
 889          *  we should be able to just modify the pointer
 
 890          *  without moving any save area.
 
 891          *  The processor only traps these occurrences if the
 
 892          *  caller window isn't live, so unfortunately we can't
 
 893          *  use this as an alternate trap mechanism.
 
 894          *  So we just do the move.  This requires that we
 
 895          *  resolve the destination register, not just the source,
 
 896          *  so there's some extra work.
 
 897          *  (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
 
 900         /* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
 
 902 1:      movi    a4, .Lmovsp_dst
 
 908         s32i    a3, a2, PT_AREG0;       _j 1f;  .align 8
 
 909         mov     a1, a3;                 _j 1f;  .align 8
 
 910         s32i    a3, a2, PT_AREG2;       _j 1f;  .align 8
 
 911         s32i    a3, a2, PT_AREG3;       _j 1f;  .align 8
 
 912         s32i    a3, a2, PT_AREG4;       _j 1f;  .align 8
 
 913         mov     a5, a3;                 _j 1f;  .align 8
 
 914         mov     a6, a3;                 _j 1f;  .align 8
 
 915         mov     a7, a3;                 _j 1f;  .align 8
 
 916         mov     a8, a3;                 _j 1f;  .align 8
 
 917         mov     a9, a3;                 _j 1f;  .align 8
 
 918         mov     a10, a3;                _j 1f;  .align 8
 
 919         mov     a11, a3;                _j 1f;  .align 8
 
 920         mov     a12, a3;                _j 1f;  .align 8
 
 921         mov     a13, a3;                _j 1f;  .align 8
 
 922         mov     a14, a3;                _j 1f;  .align 8
 
 923         mov     a15, a3;                _j 1f;  .align 8
 
 925 1:      l32i    a4, a2, PT_AREG4
 
 926         l32i    a3, a2, PT_AREG3
 
 927         l32i    a0, a2, PT_AREG0
 
 928         l32i    a2, a2, PT_AREG2
 
 935  * WARNING:  The kernel doesn't save the entire user context before
 
 936  * handling a fast system call.  These functions are small and short,
 
 937  * usually offering some functionality not available to user tasks.
 
 939  * BE CAREFUL TO PRESERVE THE USER'S CONTEXT.
 
 943  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
 945  *   a2:        new stack pointer, original in DEPC
 
 947  *   depc:      a2, original value saved on stack (PT_DEPC)
 
 951 ENTRY(fast_syscall_kernel)
 
 960         bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
 962         rsr     a0, DEPC                        # get syscall-nr
 
 963         _beqz   a0, fast_syscall_spill_registers
 
 964         _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
 968 ENTRY(fast_syscall_user)
 
 977         bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
 979         rsr     a0, DEPC                        # get syscall-nr
 
 980         _beqz   a0, fast_syscall_spill_registers
 
 981         _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
 985 ENTRY(fast_syscall_unrecoverable)
 
 987         /* Restore all states. */
 
 989         l32i    a0, a2, PT_AREG0        # restore a0
 
 990         xsr     a2, DEPC                # restore a2, depc
 
 994         movi    a0, unrecoverable_exception
 
1000  * sysxtensa syscall handler
 
1002  * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
 
1003  * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
 
1004  * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
 
1005  * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
 
1010  *   a0:        a2 (syscall-nr), original value saved on stack (PT_AREG0)
 
1012  *   a2:        new stack pointer, original in a0 and DEPC
 
1013  *   a3:        dispatch table, original in excsave_1
 
1014  *   a4..a15:   unchanged
 
1015  *   depc:      a2, original value saved on stack (PT_DEPC)
 
1018  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
1019  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
1021  * Note: we don't have to save a2; a2 holds the return value
 
1023  * We use the two macros TRY and CATCH:
 
1025  * TRY   adds an entry to the __ex_table fixup table for the immediately
 
1026  *       following instruction.
 
1028  * CATCH catches any exception that occurred at one of the preceeding TRY
 
1029  *       statements and continues from there
 
1031  * Usage TRY    l32i    a0, a1, 0
 
1034  *       CATCH  <set return code>
 
1039         .section __ex_table, "a";                                       \
 
1047 ENTRY(fast_syscall_xtensa)
 
1049         xsr     a3, EXCSAVE_1           # restore a3, excsave1
 
1051         s32i    a7, a2, PT_AREG7        # we need an additional register
 
1052         movi    a7, 4                   # sizeof(unsigned int)
 
1053         access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
 
1055         addi    a6, a6, -1              # assuming SYS_XTENSA_ATOMIC_SET = 1
 
1056         _bgeui  a6, SYS_XTENSA_COUNT - 1, .Lill
 
1057         _bnei   a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
 
1059         /* Fall through for ATOMIC_CMP_SWP. */
 
1061 .Lswp:  /* Atomic compare and swap */
 
1063 TRY     l32i    a0, a3, 0               # read old value
 
1064         bne     a0, a4, 1f              # same as old value? jump
 
1065 TRY     s32i    a5, a3, 0               # different, modify value
 
1066         l32i    a7, a2, PT_AREG7        # restore a7
 
1067         l32i    a0, a2, PT_AREG0        # restore a0
 
1068         movi    a2, 1                   # and return 1
 
1069         addi    a6, a6, 1               # restore a6 (really necessary?)
 
1072 1:      l32i    a7, a2, PT_AREG7        # restore a7
 
1073         l32i    a0, a2, PT_AREG0        # restore a0
 
1074         movi    a2, 0                   # return 0 (note that we cannot set
 
1075         addi    a6, a6, 1               # restore a6 (really necessary?)
 
1078 .Lnswp: /* Atomic set, add, and exg_add. */
 
1080 TRY     l32i    a7, a3, 0               # orig
 
1081         add     a0, a4, a7              # + arg
 
1082         moveqz  a0, a4, a6              # set
 
1083 TRY     s32i    a0, a3, 0               # write new value
 
1087         l32i    a7, a0, PT_AREG7        # restore a7
 
1088         l32i    a0, a0, PT_AREG0        # restore a0
 
1089         addi    a6, a6, 1               # restore a6 (really necessary?)
 
1093 .Leac:  l32i    a7, a2, PT_AREG7        # restore a7
 
1094         l32i    a0, a2, PT_AREG0        # restore a0
 
1098 .Lill:  l32i    a7, a2, PT_AREG0        # restore a7
 
1099         l32i    a0, a2, PT_AREG0        # restore a0
 
1106 /* fast_syscall_spill_registers.
 
1110  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
1112  *   a2:        new stack pointer, original in DEPC
 
1113  *   a3:        dispatch table
 
1114  *   depc:      a2, original value saved on stack (PT_DEPC)
 
1117  * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
 
1120 ENTRY(fast_syscall_spill_registers)
 
1122         /* Register a FIXUP handler (pass current wb as a parameter) */
 
1124         movi    a0, fast_syscall_spill_registers_fixup
 
1125         s32i    a0, a3, EXC_TABLE_FIXUP
 
1127         s32i    a0, a3, EXC_TABLE_PARAM
 
1129         /* Save a3 and SAR on stack. */
 
1132         xsr     a3, EXCSAVE_1           # restore a3 and excsave_1
 
1133         s32i    a3, a2, PT_AREG3
 
1134         s32i    a4, a2, PT_AREG4
 
1135         s32i    a0, a2, PT_AREG5        # store SAR to PT_AREG5
 
1137         /* The spill routine might clobber a7, a11, and a15. */
 
1139         s32i    a7, a2, PT_AREG7
 
1140         s32i    a11, a2, PT_AREG11
 
1141         s32i    a15, a2, PT_AREG15
 
1143         call0   _spill_registers        # destroys a3, a4, and SAR
 
1145         /* Advance PC, restore registers and SAR, and return from exception. */
 
1147         l32i    a3, a2, PT_AREG5
 
1148         l32i    a4, a2, PT_AREG4
 
1149         l32i    a0, a2, PT_AREG0
 
1151         l32i    a3, a2, PT_AREG3
 
1153         /* Restore clobbered registers. */
 
1155         l32i    a7, a2, PT_AREG7
 
1156         l32i    a11, a2, PT_AREG11
 
1157         l32i    a15, a2, PT_AREG15
 
1164  * We get here if the spill routine causes an exception, e.g. tlb miss.
 
1165  * We basically restore WINDOWBASE and WINDOWSTART to the condition when
 
1166  * we entered the spill routine and jump to the user exception handler.
 
1168  * a0: value of depc, original value in depc
 
1169  * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
 
1170  * a3: exctable, original value in excsave1
 
1173 fast_syscall_spill_registers_fixup:
 
1175         rsr     a2, WINDOWBASE  # get current windowbase (a2 is saved)
 
1176         xsr     a0, DEPC        # restore depc and a0
 
1177         ssl     a2              # set shift (32 - WB)
 
1179         /* We need to make sure the current registers (a0-a3) are preserved.
 
1180          * To do this, we simply set the bit for the current window frame
 
1181          * in WS, so that the exception handlers save them to the task stack.
 
1184         rsr     a3, EXCSAVE_1   # get spill-mask
 
1185         slli    a2, a3, 1       # shift left by one
 
1187         slli    a3, a2, 32-WSBITS
 
1188         src     a2, a2, a3      # a1 = xxwww1yyxxxwww1yy......
 
1189         wsr     a2, WINDOWSTART # set corrected windowstart
 
1192         l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE   # restore a2
 
1193         l32i    a3, a3, EXC_TABLE_PARAM # original WB (in user task)
 
1195         /* Return to the original (user task) WINDOWBASE.
 
1196          * We leave the following frame behind:
 
1198          * a3:          trashed (saved in excsave_1)
 
1199          * depc:        depc (we have to return to that address)
 
1206         /* We are now in the original frame when we entered _spill_registers:
 
1207          *  a0: return address
 
1208          *  a1: used, stack pointer
 
1209          *  a2: kernel stack pointer
 
1210          *  a3: available, saved in EXCSAVE_1
 
1211          *  depc: exception address
 
1213          * Note: This frame might be the same as above.
 
1216         /* Setup stack pointer. */
 
1218         addi    a2, a2, -PT_USER_SIZE
 
1219         s32i    a0, a2, PT_AREG0
 
1221         /* Make sure we return to this fixup handler. */
 
1223         movi    a3, fast_syscall_spill_registers_fixup_return
 
1224         s32i    a3, a2, PT_DEPC         # setup depc
 
1226         /* Jump to the exception handler. */
 
1230         addx4   a0, a0, a3                      # find entry in table
 
1231         l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
 
1234 fast_syscall_spill_registers_fixup_return:
 
1236         /* When we return here, all registers have been restored (a2: DEPC) */
 
1238         wsr     a2, DEPC                # exception address
 
1240         /* Restore fixup handler. */
 
1243         movi    a2, fast_syscall_spill_registers_fixup
 
1244         s32i    a2, a3, EXC_TABLE_FIXUP
 
1246         s32i    a2, a3, EXC_TABLE_PARAM
 
1247         l32i    a2, a3, EXC_TABLE_KSTK
 
1249         /* Load WB at the time the exception occurred. */
 
1251         rsr     a3, SAR                 # WB is still in SAR
 
1256         /* Restore a3 and return. */
 
1265  * spill all registers.
 
1267  * This is not a real function. The following conditions must be met:
 
1269  *  - must be called with call0.
 
1270  *  - uses a3, a4 and SAR.
 
1271  *  - the last 'valid' register of each frame are clobbered.
 
1272  *  - the caller must have registered a fixup handler
 
1273  *    (or be inside a critical section)
 
1274  *  - PS_EXCM must be set (PS_WOE cleared?)
 
1277 ENTRY(_spill_registers)
 
1280          * Rotate ws so that the current windowbase is at bit 0.
 
1281          * Assume ws = xxxwww1yy (www1 current window frame).
 
1282          * Rotate ws right so that a4 = yyxxxwww1.
 
1286         rsr     a3, WINDOWSTART         # a3 = xxxwww1yy
 
1289         or      a3, a3, a4              # a3 = xxxwww1yyxxxwww1yy
 
1290         srl     a3, a3                  # a3 = 00xxxwww1yyxxxwww1
 
1292         /* We are done if there are no more than the current register frame. */
 
1294         extui   a3, a3, 1, WSBITS-1     # a3 = 0yyxxxwww
 
1295         movi    a4, (1 << (WSBITS-1))
 
1296         _beqz   a3, .Lnospill           # only one active frame? jump
 
1298         /* We want 1 at the top, so that we return to the current windowbase */
 
1300         or      a3, a3, a4              # 1yyxxxwww
 
1302         /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
 
1304         wsr     a3, WINDOWSTART         # save shifted windowstart
 
1306         and     a3, a4, a3              # first bit set from right: 000010000
 
1308         ffs_ws  a4, a3                  # a4: shifts to skip empty frames
 
1310         sub     a4, a3, a4              # WSBITS-a4:number of 0-bits from right
 
1311         ssr     a4                      # save in SAR for later.
 
1319         srl     a3, a3                  # shift windowstart
 
1321         /* WB is now just one frame below the oldest frame in the register
 
1322            window. WS is shifted so the oldest frame is in bit 0, thus, WB
 
1323            and WS differ by one 4-register frame. */
 
1325         /* Save frames. Depending what call was used (call4, call8, call12),
 
1326          * we have to save 4,8. or 12 registers.
 
1332         /* Special case: we have a call12-frame starting at a4. */
 
1334         _bbci.l a3, 3, .Lc12    # bit 3 shouldn't be zero! (Jump to Lc12 first)
 
1336         s32e    a4, a1, -16     # a1 is valid with an empty spill area
 
1346 .Lloop: _bbsi.l a3, 1, .Lc4
 
1347         _bbci.l a3, 2, .Lc12
 
1349 .Lc8:   s32e    a4, a13, -16
 
1359         srli    a11, a3, 2              # shift windowbase by 2
 
1363 .Lexit: /* Done. Do the final rotation, set WS, and return. */
 
1373 .Lc4:   s32e    a4, a9, -16
 
1383 .Lc12:  _bbci.l a3, 3, .Linvalid_mask   # bit 2 shouldn't be zero!
 
1385         /* 12-register frame (call12) */
 
1391 .Lc12c: s32e    a9, a8, -44
 
1400         /* The stack pointer for a4..a7 is out of reach, so we rotate the
 
1401          * window, grab the stackpointer, and rotate back.
 
1402          * Alternatively, we could also use the following approach, but that
 
1403          * makes the fixup routine much more complicated:
 
1426         /* We get here because of an unrecoverable error in the window
 
1427          * registers. If we are in user space, we kill the application,
 
1428          * however, this condition is unrecoverable in kernel space.
 
1432         _bbci.l a0, PS_UM_BIT, 1f
 
1434         /* User space: Setup a dummy frame and kill application.
 
1435          * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
 
1448         l32i    a1, a3, EXC_TABLE_KSTK
 
1451         movi    a4, (1 << PS_WOE_BIT) | 1
 
1459 1:      /* Kernel space: PANIC! */
 
1462         movi    a0, unrecoverable_exception
 
1463         callx0  a0              # should not return
 
1467  * We should never get here. Bail out!
 
1470 ENTRY(fast_second_level_miss_double_kernel)
 
1472 1:      movi    a0, unrecoverable_exception
 
1473         callx0  a0              # should not return
 
1476 /* First-level entry handler for user, kernel, and double 2nd-level
 
1477  * TLB miss exceptions.  Note that for now, user and kernel miss
 
1478  * exceptions share the same entry point and are handled identically.
 
1480  * An old, less-efficient C version of this function used to exist.
 
1481  * We include it below, interleaved as comments, for reference.
 
1485  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
1487  *   a2:        new stack pointer, original in DEPC
 
1488  *   a3:        dispatch table
 
1489  *   depc:      a2, original value saved on stack (PT_DEPC)
 
1492  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
1493  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
1496 ENTRY(fast_second_level_miss)
 
1498         /* Save a1. Note: we don't expect a double exception. */
 
1500         s32i    a1, a2, PT_AREG1
 
1502         /* We need to map the page of PTEs for the user task.  Find
 
1503          * the pointer to that page.  Also, it's possible for tsk->mm
 
1504          * to be NULL while tsk->active_mm is nonzero if we faulted on
 
1505          * a vmalloc address.  In that rare case, we must use
 
1506          * active_mm instead to avoid a fault in this handler.  See
 
1508          * http://mail.nl.linux.org/linux-mm/2002-08/msg00258.html
 
1509          *   (or search Internet on "mm vs. active_mm")
 
1512          *              mm = tsk->active_mm;
 
1513          *      pgd = pgd_offset (mm, regs->excvaddr);
 
1514          *      pmd = pmd_offset (pgd, regs->excvaddr);
 
1519         l32i    a0, a1, TASK_MM         # tsk->mm
 
1523         /* We deliberately destroy a3 that holds the exception table. */
 
1525 8:      rsr     a3, EXCVADDR            # fault address
 
1526         _PGD_OFFSET(a0, a3, a1)
 
1527         l32i    a0, a0, 0               # read pmdval
 
1530         /* Read ptevaddr and convert to top of page-table page.
 
1532          *      vpnval = read_ptevaddr_register() & PAGE_MASK;
 
1533          *      vpnval += DTLB_WAY_PGTABLE;
 
1534          *      pteval = mk_pte (virt_to_page(pmd_val(pmdval)), PAGE_KERNEL);
 
1535          *      write_dtlb_entry (pteval, vpnval);
 
1537          * The messy computation for 'pteval' above really simplifies
 
1538          * into the following:
 
1540          * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
 
1543         movi    a1, -PAGE_OFFSET
 
1544         add     a0, a0, a1              # pmdval - PAGE_OFFSET
 
1545         extui   a1, a0, 0, PAGE_SHIFT   # ... & PAGE_MASK
 
1548         movi    a1, _PAGE_DIRECTORY
 
1549         or      a0, a0, a1              # ... | PAGE_DIRECTORY
 
1552          * We utilize all three wired-ways (7-9) to hold pmd translations.
 
1553          * Memory regions are mapped to the DTLBs according to bits 28 and 29.
 
1554          * This allows to map the three most common regions to three different
 
1556          *  0,1 -> way 7        program (0040.0000) and virtual (c000.0000)
 
1557          *  2   -> way 8        shared libaries (2000.0000)
 
1558          *  3   -> way 0        stack (3000.0000)
 
1561         extui   a3, a3, 28, 2           # addr. bit 28 and 29   0,1,2,3
 
1563         addx2   a3, a3, a3              # ->                    0,3,6,9
 
1564         srli    a1, a1, PAGE_SHIFT
 
1565         extui   a3, a3, 2, 2            # ->                    0,0,1,2
 
1566         slli    a1, a1, PAGE_SHIFT      # ptevaddr & PAGE_MASK
 
1567         addi    a3, a3, DTLB_WAY_PGD
 
1568         add     a1, a1, a3              # ... + way_number
 
1573         /* Exit critical section. */
 
1575 4:      movi    a3, exc_table           # restore a3
 
1577         s32i    a0, a3, EXC_TABLE_FIXUP
 
1579         /* Restore the working registers, and return. */
 
1581         l32i    a0, a2, PT_AREG0
 
1582         l32i    a1, a2, PT_AREG1
 
1583         l32i    a2, a2, PT_DEPC
 
1586         bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
1588         /* Restore excsave1 and return. */
 
1593         /* Return from double exception. */
 
1599 9:      l32i    a0, a1, TASK_ACTIVE_MM  # unlikely case mm == 0
 
1602 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
 
1604 2:      /* Special case for cache aliasing.
 
1605          * We (should) only get here if a clear_user_page, copy_user_page
 
1606          * or the aliased cache flush functions got preemptively interrupted 
 
1607          * by another task. Re-establish temporary mapping to the 
 
1608          * TLBTEMP_BASE areas.
 
1611         /* We shouldn't be in a double exception */
 
1613         l32i    a0, a2, PT_DEPC
 
1614         bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f
 
1616         /* Make sure the exception originated in the special functions */
 
1618         movi    a0, __tlbtemp_mapping_start
 
1621         movi    a0, __tlbtemp_mapping_end
 
1624         /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
 
1626         movi    a3, TLBTEMP_BASE_1
 
1630         addi    a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
 
1633         /* Check if we have to restore an ITLB mapping. */
 
1635         movi    a1, __tlbtemp_mapping_itlb
 
1644         /* Jump for ITLB entry */
 
1648         /* We can use up to two TLBTEMP areas, one for src and one for dst. */
 
1650         extui   a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1
 
1653         /* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
 
1659         /* ITLB entry. We only use dst in a6. */
 
1666 #endif  // DCACHE_WAY_SIZE > PAGE_SIZE
 
1669 2:      /* Invalid PGD, default exception handling */
 
1674         s32i    a1, a2, PT_AREG2
 
1675         s32i    a3, a2, PT_AREG3
 
1679         bbsi.l  a2, PS_UM_BIT, 1f
 
1681 1:      j       _user_exception
 
1685  * StoreProhibitedException
 
1687  * Update the pte and invalidate the itlb mapping for this pte.
 
1691  *   a0:        trashed, original value saved on stack (PT_AREG0)
 
1693  *   a2:        new stack pointer, original in DEPC
 
1694  *   a3:        dispatch table
 
1695  *   depc:      a2, original value saved on stack (PT_DEPC)
 
1698  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
 
1699  *           <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
 
1702 ENTRY(fast_store_prohibited)
 
1704         /* Save a1 and a4. */
 
1706         s32i    a1, a2, PT_AREG1
 
1707         s32i    a4, a2, PT_AREG4
 
1710         l32i    a0, a1, TASK_MM         # tsk->mm
 
1713 8:      rsr     a1, EXCVADDR            # fault address
 
1714         _PGD_OFFSET(a0, a1, a4)
 
1718         /* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/
 
1720         _PTE_OFFSET(a0, a1, a4)
 
1721         l32i    a4, a0, 0               # read pteval
 
1722         bbci.l  a4, _PAGE_WRITABLE_BIT, 2f
 
1724         movi    a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
 
1729         /* We need to flush the cache if we have page coloring. */
 
1730 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
1736         /* Exit critical section. */
 
1739         s32i    a0, a3, EXC_TABLE_FIXUP
 
1741         /* Restore the working registers, and return. */
 
1743         l32i    a4, a2, PT_AREG4
 
1744         l32i    a1, a2, PT_AREG1
 
1745         l32i    a0, a2, PT_AREG0
 
1746         l32i    a2, a2, PT_DEPC
 
1748         /* Restore excsave1 and a3. */
 
1751         bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
1756         /* Double exception. Restore FIXUP handler and return. */
 
1762 9:      l32i    a0, a1, TASK_ACTIVE_MM  # unlikely case mm == 0
 
1765 2:      /* If there was a problem, handle fault in C */
 
1767         rsr     a4, DEPC        # still holds a2
 
1769         s32i    a4, a2, PT_AREG2
 
1770         s32i    a3, a2, PT_AREG3
 
1771         l32i    a4, a2, PT_AREG4
 
1775         bbsi.l  a2, PS_UM_BIT, 1f
 
1777 1:      j       _user_exception
 
1783  * void system_call (struct pt_regs* regs, int exccause)
 
1790         /* regs->syscall = regs->areg[2] */
 
1792         l32i    a3, a2, PT_AREG2
 
1794         movi    a4, do_syscall_trace_enter
 
1795         s32i    a3, a2, PT_SYSCALL
 
1798         /* syscall = sys_call_table[syscall_nr] */
 
1800         movi    a4, sys_call_table;
 
1801         movi    a5, __NR_syscall_count
 
1807         movi    a5, sys_ni_syscall;
 
1810         /* Load args: arg0 - arg5 are passed via regs. */
 
1812         l32i    a6, a2, PT_AREG6
 
1813         l32i    a7, a2, PT_AREG3
 
1814         l32i    a8, a2, PT_AREG4
 
1815         l32i    a9, a2, PT_AREG5
 
1816         l32i    a10, a2, PT_AREG8
 
1817         l32i    a11, a2, PT_AREG9
 
1819         /* Pass one additional argument to the syscall: pt_regs (on stack) */
 
1824 1:      /* regs->areg[2] = return_value */
 
1826         s32i    a6, a2, PT_AREG2
 
1827         movi    a4, do_syscall_trace_leave
 
1834  * Create a kernel thread
 
1836  * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 
1840 ENTRY(kernel_thread)
 
1843         mov     a5, a2                  # preserve fn over syscall
 
1844         mov     a7, a3                  # preserve args over syscall
 
1846         movi    a3, _CLONE_VM | _CLONE_UNTRACED
 
1848         or      a6, a4, a3              # arg0: flags
 
1849         mov     a3, a1                  # arg1: sp
 
1852         beq     a3, a1, 1f              # branch if parent
 
1854         callx4  a5                      # fn(args)
 
1857         syscall                         # return value of fn(args) still in a6
 
1862  * Do a system call from kernel instead of calling sys_execve, so we end up
 
1863  * with proper pt_regs.
 
1865  * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
 
1869 ENTRY(kernel_execve)
 
1871         mov     a6, a2                  # arg0 is in a6
 
1872         movi    a2, __NR_execve
 
1880  * struct task*  _switch_to (struct task* prev, struct task* next)
 
1888         mov     a12, a2                 # preserve 'prev' (a2)
 
1889         mov     a13, a3                 # and 'next' (a3)
 
1891         l32i    a4, a2, TASK_THREAD_INFO
 
1892         l32i    a5, a3, TASK_THREAD_INFO
 
1894         save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
 
1896         s32i    a0, a12, THREAD_RA      # save return address
 
1897         s32i    a1, a12, THREAD_SP      # save stack pointer
 
1899         /* Disable ints while we manipulate the stack pointer. */
 
1901         movi    a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
 
1905         s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
 
1907         /* Switch CPENABLE */
 
1909 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
 
1910         l32i    a3, a5, THREAD_CPENABLE
 
1912         s32i    a3, a4, THREAD_CPENABLE
 
1915         /* Flush register file. */
 
1917         call0   _spill_registers        # destroys a3, a4, and SAR
 
1919         /* Set kernel stack (and leave critical section)
 
1920          * Note: It's save to set it here. The stack will not be overwritten
 
1921          *       because the kernel stack will only be loaded again after
 
1922          *       we return from kernel space.
 
1925         rsr     a3, EXCSAVE_1           # exc_table
 
1927         addi    a7, a5, PT_REGS_OFFSET
 
1928         s32i    a6, a3, EXC_TABLE_FIXUP
 
1929         s32i    a7, a3, EXC_TABLE_KSTK
 
1931         /* restore context of the task that 'next' addresses */
 
1933         l32i    a0, a13, THREAD_RA      # restore return address
 
1934         l32i    a1, a13, THREAD_SP      # restore stack pointer
 
1936         load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
 
1939         mov     a2, a12                 # return 'prev'
 
1945 ENTRY(ret_from_fork)
 
1947         /* void schedule_tail (struct task_struct *prev)
 
1948          * Note: prev is still in a6 (return value from fake call4 frame)
 
1950         movi    a4, schedule_tail
 
1953         movi    a4, do_syscall_trace_leave
 
1957         j       common_exception_return