?? entry.s
字號:
l32i a0, a2, PT_DEPC bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable rsr a0, DEPC # get syscall-nr _beqz a0, fast_syscall_spill_registers addi a0, a0, -__NR_sysxtensa _beqz a0, fast_syscall_sysxtensa j kernel_exceptionENTRY(fast_syscall_user) /* Skip syscall. */ rsr a0, EPC_1 addi a0, a0, 3 wsr a0, EPC_1 l32i a0, a2, PT_DEPC bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable rsr a0, DEPC # get syscall-nr _beqz a0, fast_syscall_spill_registers addi a0, a0, -__NR_sysxtensa _beqz a0, fast_syscall_sysxtensa j user_exceptionENTRY(fast_syscall_unrecoverable) /* Restore all states. */ l32i a0, a2, PT_AREG0 # restore a0 xsr a2, DEPC # restore a2, depc rsr a3, EXCSAVE_1 wsr a0, EXCSAVE_1 movi a0, unrecoverable_exception callx0 a0/* * sysxtensa syscall handler * * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused); * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused); * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); * a2 a6 a3 a4 a5 * * Entry condition: * * a0: trashed, original value saved on stack (PT_AREG0) * a1: a1 * a2: new stack pointer, original in DEPC * a3: dispatch table * depc: a2, original value saved on stack (PT_DEPC) * excsave_1: a3 * * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception * * Note: we don't have to save a2; a2 holds the return value * * We use the two macros TRY and CATCH: * * TRY adds an entry to the __ex_table fixup table for the immediately * following instruction. * * CATCH catches any exception that occurred at one of the preceeding TRY * statements and continues from there * * Usage TRY l32i a0, a1, 0 * <other code> * done: rfe * CATCH <set return code> * j done */#define TRY \ .section __ex_table, "a"; \ .word 66f, 67f; \ .text; \66:#define CATCH \67:ENTRY(fast_syscall_sysxtensa) _beqz a6, 1f _blti a6, SYSXTENSA_COUNT, 2f1: j user_exception2: xsr a3, EXCSAVE_1 # restore a3, excsave1 s32i a7, a2, PT_AREG7 movi a7, 4 # sizeof(unsigned int) verify_area a3, a7, a0, a2, .Leac _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */.Lswp: /* Atomic compare and swap */TRY l32i a7, a3, 0 # read old value bne a7, a4, 1f # same as old value? jump s32i a5, a3, 0 # different, modify value movi a7, 1 # and return 1 j .Lret1: movi a7, 0 # same values: return 0 j .Lret.Ladd: /* Atomic add */.Lexg: /* Atomic (exchange) add */TRY l32i a7, a3, 0 add a4, a4, a7 s32i a4, a3, 0 j .Lret.Lset: /* Atomic set */TRY l32i a7, a3, 0 # read old value as return value s32i a4, a3, 0 # write new value.Lret: mov a0, a2 mov a2, a7 l32i a7, a0, PT_AREG7 l32i a3, a0, PT_AREG3 l32i a0, a0, PT_AREG0 rfeCATCH.Leac: movi a7, -EFAULT j .Lret/* fast_syscall_spill_registers. * * Entry condition: * * a0: trashed, original value saved on stack (PT_AREG0) * a1: a1 * a2: new stack pointer, original in DEPC * a3: dispatch table * depc: a2, original value saved on stack (PT_DEPC) * excsave_1: a3 * * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. * Note: We don't need to save a2 in depc (return value) */ENTRY(fast_syscall_spill_registers) /* Register a FIXUP handler (pass current wb as a parameter) */ movi a0, fast_syscall_spill_registers_fixup s32i a0, a3, EXC_TABLE_FIXUP rsr a0, WINDOWBASE s32i a0, a3, EXC_TABLE_PARAM /* Save a3 and SAR on stack. */ rsr a0, SAR xsr a3, EXCSAVE_1 # restore a3 and excsave_1 s32i a0, a2, PT_AREG4 # store SAR to PT_AREG4 s32i a3, a2, PT_AREG3 /* The spill routine might clobber a7, a11, and a15. */ s32i a7, a2, PT_AREG5 s32i a11, a2, PT_AREG6 s32i a15, a2, PT_AREG7 call0 _spill_registers # destroys a3, DEPC, and SAR /* Advance PC, restore registers and SAR, and return from exception. */ l32i a3, a2, PT_AREG4 l32i a0, a2, PT_AREG0 wsr a3, SAR l32i a3, a2, PT_AREG3 /* Restore clobbered registers. */ l32i a7, a2, PT_AREG5 l32i a11, a2, PT_AREG6 l32i a15, a2, PT_AREG7 movi a2, 0 rfe/* Fixup handler. * * We get here if the spill routine causes an exception, e.g. tlb miss. * We basically restore WINDOWBASE and WINDOWSTART to the condition when * we entered the spill routine and jump to the user exception handler. * * a0: value of depc, original value in depc * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE * a3: exctable, original value in excsave1 */fast_syscall_spill_registers_fixup: rsr a2, WINDOWBASE # get current windowbase (a2 is saved) xsr a0, DEPC # restore depc and a0 ssl a2 # set shift (32 - WB) /* We need to make sure the current registers (a0-a3) are preserved. * To do this, we simply set the bit for the current window frame * in WS, so that the exception handlers save them to the task stack. */ rsr a3, EXCSAVE_1 # get spill-mask slli a2, a3, 1 # shift left by one slli a3, a2, 32-WSBITS src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... wsr a2, WINDOWSTART # set corrected windowstart movi a3, exc_table l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task) /* Return to the original (user task) WINDOWBASE. * We leave the following frame behind: * a0, a1, a2 same * a3: trashed (saved in excsave_1) * depc: depc (we have to return to that address) * excsave_1: a3 */ wsr a3, WINDOWBASE rsync /* We are now in the original frame when we entered _spill_registers: * a0: return address * a1: used, stack pointer * a2: kernel stack pointer * a3: available, saved in EXCSAVE_1 * depc: exception address * excsave: a3 * Note: This frame might be the same as above. */#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION /* Restore registers we precautiously saved. * We have the value of the 'right' a3 */ l32i a7, a2, PT_AREG5 l32i a11, a2, PT_AREG6 l32i a15, a2, PT_AREG7#endif /* Setup stack pointer. */ addi a2, a2, -PT_USER_SIZE s32i a0, a2, PT_AREG0 /* Make sure we return to this fixup handler. */ movi a3, fast_syscall_spill_registers_fixup_return s32i a3, a2, PT_DEPC # setup depc /* Jump to the exception handler. */ movi a3, exc_table rsr a0, EXCCAUSE addx4 a0, a0, a3 # find entry in table l32i a0, a0, EXC_TABLE_FAST_USER # load handler jx a0fast_syscall_spill_registers_fixup_return: /* When we return here, all registers have been restored (a2: DEPC) */ wsr a2, DEPC # exception address /* Restore fixup handler. */ xsr a3, EXCSAVE_1 movi a2, fast_syscall_spill_registers_fixup s32i a2, a3, EXC_TABLE_FIXUP rsr a2, WINDOWBASE s32i a2, a3, EXC_TABLE_PARAM l32i a2, a3, EXC_TABLE_KSTK#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION /* Save registers again that might be clobbered. */ s32i a7, a2, PT_AREG5 s32i a11, a2, PT_AREG6 s32i a15, a2, PT_AREG7#endif /* Load WB at the time the exception occurred. */ rsr a3, SAR # WB is still in SAR neg a3, a3 wsr a3, WINDOWBASE rsync /* Restore a3 and return. */ movi a3, exc_table xsr a3, EXCSAVE_1 rfde/* * spill all registers. * * This is not a real function. The following conditions must be met: * * - must be called with call0. * - uses DEPC, a3 and SAR. * - the last 'valid' register of each frame are clobbered. * - the caller must have registered a fixup handler * (or be inside a critical section) * - PS_EXCM must be set (PS_WOE cleared?) */ENTRY(_spill_registers) /* * Rotate ws so that the current windowbase is at bit 0. * Assume ws = xxxwww1yy (www1 current window frame). * Rotate ws right so that a2 = yyxxxwww1. */ wsr a2, DEPC # preserve a2 rsr a2, WINDOWBASE rsr a3, WINDOWSTART ssr a2 # holds WB slli a2, a3, WSBITS or a3, a3, a2 # a2 = xxxwww1yyxxxwww1yy srl a3, a3 /* We are done if there are no more than the current register frame. */ extui a3, a3, 1, WSBITS-2 # a3 = 0yyxxxwww movi a2, (1 << (WSBITS-1)) _beqz a3, .Lnospill # only one active frame? jump /* We want 1 at the top, so that we return to the current windowbase */ or a3, a3, a2 # 1yyxxxwww /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */ wsr a3, WINDOWSTART # save shifted windowstart neg a2, a3 and a3, a2, a3 # first bit set from right: 000010000 ffs_ws a2, a3 # a2: shifts to skip empty frames movi a3, WSBITS sub a2, a3, a2 # WSBITS-a2:number of 0-bits from right ssr a2 # save in SAR for later. rsr a3, WINDOWBASE add a3, a3, a2 rsr a2, DEPC # restore a2 wsr a3, WINDOWBASE rsync rsr a3, WINDOWSTART srl a3, a3 # shift windowstart /* WB is now just one frame below the oldest frame in the register window. WS is shifted so the oldest frame is in bit 0, thus, WB and WS differ by one 4-register frame. */ /* Save frames. Depending what call was used (call4, call8, call12), * we have to save 4,8. or 12 registers. */ _bbsi.l a3, 1, .Lc4 _bbsi.l a3, 2, .Lc8 /* Special case: we have a call12-frame starting at a4. */ _bbci.l a3, 3, .Lc12 # bit 3 shouldn't be zero! (Jump to Lc12 first) s32e a4, a1, -16 # a1 is valid with an empty spill area l32e a4, a5, -12 s32e a8, a4, -48 mov a8, a4 l32e a4, a1, -16 j .Lc12c.Lloop: _bbsi.l a3, 1, .Lc4 _bbci.l a3, 2, .Lc12.Lc8: s32e a4, a13, -16 l32e a4, a5, -12 s32e a8, a4, -32 s32e a5, a13, -12 s32e a6, a13, -8 s32e a7, a13, -4 s32e a9, a4, -28 s32e a10, a4, -24 s32e a11, a4, -20 srli a11, a3, 2 # shift windowbase by 2 rotw 2 _bnei a3, 1, .Lloop.Lexit: /* Done. Do the final rotation, set WS, and return. */ rotw 1 rsr a3, WINDOWBASE ssl a3 movi a3, 1 sll a3, a3 wsr a3, WINDOWSTART.Lnospill: jx a0.Lc4: s32e a4, a9, -16 s32e a5, a9, -12 s32e a6, a9, -8 s32e a7, a9, -4 srli a7, a3, 1 rotw 1 _bnei a3, 1, .Lloop j .Lexit.Lc12: _bbci.l a3, 3, .Linvalid_mask # bit 2 shouldn't be zero! /* 12-register frame (call12) */ l32e a2, a5, -12 s32e a8, a2, -48 mov a8, a2.Lc12c: s32e a9, a8, -44 s32e a10, a8, -40 s32e a11, a8, -36 s32e a12, a8, -32 s32e a13, a8, -28 s32e a14, a8, -24 s32e a15, a8, -20 srli a15, a3, 3 /* The stack pointer for a4..a7 is out of reach, so we rotate the * window, grab the stackpointer, and rotate back. * Alternatively, we could also use the following approach, but that * makes the fixup routine much more complicated: * rotw 1 * s32e a0, a13, -16 * ... * rotw 2 */ rotw 1 mov a5, a13 rotw -1 s32e a4, a9, -16 s32e a5, a9, -12 s32e a6, a9, -8 s32e a7, a9, -4 rotw 3 _beqi a3, 1, .Lexit j .Lloop.Linvalid_mask: /* We get here because of an unrecoverable error in the window * registers. If we are in user space, we kill the application, * however, this condition is unrecoverable in kernel space. */ rsr a0, PS _bbci.l a0, PS_UM_SHIFT, 1f /* User space: Setup a dummy frame and kill application. * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer. */ movi a0, 1
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -