entry.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 2,106 行 · 第 1/4 页
S
2,106 行
getcon KCR1, SP _ptar handle_exception, t0 blink t0, ZERO /* * Instead of the natural .balign 1024 place RESVEC here * respecting the final 1KB alignment. */ .balign TEXT_SIZE /* * Instead of '.space 1024-TEXT_SIZE' place the RESVEC * block making sure the final alignment is correct. */LRESVEC_block: /* Panic handler. Called with MMU off. Possible causes/actions: * - Reset: Jump to program start. * - Single Step: Turn off Single Step & return. * - Others: Call panic handler, passing PC as arg. * (this may need to be extended...) */reset_or_panic: putcon SP, DCR /* First save r0-1 and tr0, as we need to use these */ _loada resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP st.q SP, 0, r0 st.q SP, 8, r1 gettr t0, r0 st.q SP, 32, r0 /* Check cause */ getcon EXPEVT, r0 movi RESET_CAUSE, r1 sub r1, r0, r1 /* r1=0 if reset */ _loada _stext-CONFIG_CACHED_MEMORY_OFFSET, r0 ori r0, 1, r0 ptabs r0, t0 beqi r1, 0, t0 /* Jump to start address if reset */ getcon EXPEVT, r0 movi DEBUGSS_CAUSE, r1 sub r1, r0, r1 /* r1=0 if single step */ _ptar single_step_panic, t0 beqi r1, 0, t0 /* jump if single step */ /* If we get here, we have an unknown panic. Just call the panic * handler, passing saved PC. We never expect to return, so we can * use any regs now. */ getcon SPC,r2 getcon SSR,r3 getcon EXPEVT,r4 /* Prepare to jump to C - physical address */ _loada panic_handler-CONFIG_CACHED_MEMORY_OFFSET, r1 ori r1, 1, r1 ptabs r1, t0 getcon DCR, SP blink t0, ZEROsingle_step_panic: /* We are in a handler with Single Step set. We need to resume the * handler, by turning on MMU & turning off Single Step. */ getcon SSR, r0 movi SR_MMU, r1 or r0, r1, r0 movi ~SR_SS, r1 and r0, r1, r0 putcon r0, SSR /* Restore EXPEVT, as the rte won't do this */ getcon PEXPEVT, r0 putcon r0, EXPEVT /* Restore regs */ ld.q SP, 32, r0 ptabs r0, tr0 ld.q SP, 0, r0 ld.q SP, 8, r1 getcon DCR, SP synco rte .balign TEXT_SIZEdebug_exception: /* * Single step/software_break_point first level handler. * Called with MMU off, so the first thing we do is enable it * by doing an rte with appropriate SSR. */ putcon SP, DCR /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */ _loada resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP /* With the MMU off, we are bypassing the cache, so purge any * data that will be made stale by the following stores. */ ocbp SP, 0 synco st.q SP, 0, r0 st.q SP, 8, r1 getcon SPC, r0 st.q SP, 16, r0 getcon SSR, r0 st.q SP, 24, r0 /* Enable MMU, block exceptions, set priv mode, disable single step */ movi SR_MMU | SR_BL | SR_MD, r1 or r0, r1, r0 movi ~SR_SS, r1 and r0, r1, r0 putcon r0, SSR /* Force control to debug_exception_2 when rte is executed */ _loada debug_exeception_2, r0 ori r0, 1, r0 /* force SHmedia, just in case */ putcon r0, SPC getcon DCR, SP synco rtedebug_exeception_2: /* Restore saved regs */ putcon SP, KCR1 _loada resvec_save_area, SP ld.q SP, 24, r0 putcon r0, SSR ld.q SP, 16, r0 putcon r0, SPC ld.q SP, 0, r0 ld.q SP, 8, r1 /* Save other original registers into reg_save_area */ _loada reg_save_area, SP st.q SP, SAVED_R2, r2 st.q SP, SAVED_R3, r3 st.q SP, SAVED_R4, r4 st.q SP, SAVED_R5, r5 st.q SP, SAVED_R6, r6 st.q SP, SAVED_R18, r18 gettr t0, r3 st.q SP, SAVED_T0, r3 /* Set args for debug class handler */ getcon EXPEVT, r2 _loada ret_from_exception, r3 ori r3, 1, r3 movi EVENT_DEBUG, r4 or SP, ZERO, r5 getcon KCR1, SP _ptar handle_exception, t0 blink t0, ZERO .balign TEXT_SIZEdebug_interrupt: /* * Not supported. If we ever get here loop forever * We may be MMUOFF or MMUON. Just use pic code. */ _ptar debug_interrupt, t0 blink t0, ZERO .balign TEXT_SIZELRESVEC_block_end: /* Marker. Unused. */tlb_miss: putcon SP, KCR1 _loada reg_save_area, SP /* SP is guaranteed 32-byte aligned. */ st.q SP, TLB_SAVED_R0 , r0 st.q SP, TLB_SAVED_R1 , r1 st.q SP, SAVED_R2 , r2 st.q SP, SAVED_R3 , r3 st.q SP, SAVED_R4 , r4 st.q SP, SAVED_R5 , r5 st.q SP, SAVED_R6 , r6 st.q SP, SAVED_R18, r18 /* Save R25 for safety; as/ld may want to use it to achieve the call to * the code in mm/tlbmiss.c */ st.q SP, TLB_SAVED_R25, r25 gettr tr0, r2 gettr tr1, r3 gettr tr2, r4 gettr tr3, r5 gettr tr4, r18 st.q SP, SAVED_T0 , r2 st.q SP, TLB_SAVED_T1 , r3 st.q SP, TLB_SAVED_T2 , r4 st.q SP, TLB_SAVED_T3 , r5 st.q SP, TLB_SAVED_T4 , r18 pt do_fast_page_fault, tr0 getcon SSR, r2 getcon EXPEVT, r3 getcon TEA, r4 shlri r2, 30, r2 andi r2, 1, r2 /* r2 = SSR.MD */ blink tr0, r18 pt fixup_to_invoke_general_handler, tr1 /* If the fast path handler fixed the fault, just drop through quickly to the restore code right away to return to the excepting context. */ beqi/u r2, 0, tr1fast_tlb_miss_restore: ld.q SP, SAVED_T0, r2 ld.q SP, TLB_SAVED_T1, r3 ld.q SP, TLB_SAVED_T2, r4 ld.q SP, TLB_SAVED_T3, r5 ld.q SP, TLB_SAVED_T4, r18 ptabs r2, tr0 ptabs r3, tr1 ptabs r4, tr2 ptabs r5, tr3 ptabs r18, tr4 ld.q SP, TLB_SAVED_R0, r0 ld.q SP, TLB_SAVED_R1, r1 ld.q SP, SAVED_R2, r2 ld.q SP, SAVED_R3, r3 ld.q SP, SAVED_R4, r4 ld.q SP, SAVED_R5, r5 ld.q SP, SAVED_R6, r6 ld.q SP, SAVED_R18, r18 ld.q SP, TLB_SAVED_R25, r25 getcon KCR1, SP rte nop /* for safety, in case the code is run on sh5-101 cut1.x */fixup_to_invoke_general_handler: /* OK, new method. Restore stuff that's not expected to get saved into the 'first-level' reg save area, then just fall through to setting up the registers and calling the second-level handler. */ /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore r25,tr1-4 and save r6 to get into the right state. */ ld.q SP, TLB_SAVED_T1, r3 ld.q SP, TLB_SAVED_T2, r4 ld.q SP, TLB_SAVED_T3, r5 ld.q SP, TLB_SAVED_T4, r18 ld.q SP, TLB_SAVED_R25, r25 ld.q SP, TLB_SAVED_R0, r0 ld.q SP, TLB_SAVED_R1, r1 ptabs/u r3, tr1 ptabs/u r4, tr2 ptabs/u r5, tr3 ptabs/u r18, tr4#ifdef CONFIG_SH64_PAGE_TABLE_AUDIT /* This use of DCR is not really legal, but there's nowhere else convenient to store this and it's only for last-resort debug anyway. */ movi 0x400, r3 putcon r3, dcr#endif /* Set args for Non-debug, TLB miss class handler */ getcon EXPEVT, r2 _loada ret_from_exception, r3 ori r3, 1, r3 movi EVENT_FAULT_TLB, r4 or SP, ZERO, r5 getcon KCR1, SP _ptar handle_exception, t0 blink t0, ZERO/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE DOES END UP AT VBR+0x600 */ nop nop nop nop nop nop#if 0 .balign 256 nop#endif .balign 256 /* VBR + 0x600 */interrupt: /* Save original stack pointer into KCR1 */ putcon SP, KCR1 /* Save other original registers into reg_save_area */ _loada reg_save_area, SP st.q SP, SAVED_R2, r2 st.q SP, SAVED_R3, r3 st.q SP, SAVED_R4, r4 st.q SP, SAVED_R5, r5 st.q SP, SAVED_R6, r6 st.q SP, SAVED_R18, r18 gettr t0, r3 st.q SP, SAVED_T0, r3#ifdef CONFIG_SH64_PAGE_TABLE_AUDIT /* This use of DCR is not really legal, but there's nowhere else convenient to store this and it's only for last-resort debug anyway. */ movi 0x600, r3 putcon r3, dcr#endif /* Set args for interrupt class handler */ getcon INTEVT, r2 _loada ret_from_irq, r3 ori r3, 1, r3 movi EVENT_INTERRUPT, r4 or SP, ZERO, r5 getcon KCR1, SP _ptar handle_exception, t0 blink t0, ZERO .balign TEXT_SIZE /* let's waste the bare minimum */LVBR_block_end: /* Marker. Used for total checking */ /* * Second level handler for VBR-based exceptions. Pre-handler. * In common to all stack-frame sensitive handlers. * * Inputs: * (KCR0) Current [current task union] * (KCR1) Original SP * (r2) INTEVT/EXPEVT * (r3) appropriate return address * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug) * (r5) Pointer to reg_save_area * (SP) Original SP * * Available registers: * (r6) * (r18) * (t0) * */handle_exception: /* Common 2nd level handler. */ /* First thing we need an appropriate stack pointer */ getcon SSR, r6 shlri r6, 30, r6 andi r6, 1, r6 _ptar stack_ok, t0 bne r6, ZERO, t0 /* Original stack pointer is fine */ /* Set stack pointer for user fault */ getcon KCR0, SP movi THREAD_SIZE, r6 /* Point to the end */ add SP, r6, SPstack_ok: /* Make some room for the BASIC frame. */ movi -(FRAME_SIZE), r6 add SP, r6, SP/* Could do this with no stalling if we had another spare register, but the code below will be OK. */ ld.q r5, SAVED_R2, r6 ld.q r5, SAVED_R3, r18 st.q SP, FRAME_R(2), r6 ld.q r5, SAVED_R4, r6 st.q SP, FRAME_R(3), r18 ld.q r5, SAVED_R5, r18 st.q SP, FRAME_R(4), r6 ld.q r5, SAVED_R6, r6 st.q SP, FRAME_R(5), r18 ld.q r5, SAVED_R18, r18 st.q SP, FRAME_R(6), r6 ld.q r5, SAVED_T0, r6 st.q SP, FRAME_R(18), r18 st.q SP, FRAME_T(0), r6 /* Keep old SP around */ getcon KCR1, r6 /* Save the rest of the general purpose registers */ st.q SP, FRAME_R(0), r0 st.q SP, FRAME_R(1), r1 st.q SP, FRAME_R(7), r7 st.q SP, FRAME_R(8), r8 st.q SP, FRAME_R(9), r9 st.q SP, FRAME_R(10), r10 st.q SP, FRAME_R(11), r11 st.q SP, FRAME_R(12), r12 st.q SP, FRAME_R(13), r13 st.q SP, FRAME_R(14), r14 /* SP is somewhere else */ st.q SP, FRAME_R(15), r6 st.q SP, FRAME_R(16), r16 st.q SP, FRAME_R(17), r17 /* r18 is saved earlier. */ st.q SP, FRAME_R(19), r19 st.q SP, FRAME_R(20), r20 st.q SP, FRAME_R(21), r21 st.q SP, FRAME_R(22), r22 st.q SP, FRAME_R(23), r23 st.q SP, FRAME_R(24), r24 st.q SP, FRAME_R(25), r25 st.q SP, FRAME_R(26), r26 st.q SP, FRAME_R(27), r27 st.q SP, FRAME_R(28), r28 st.q SP, FRAME_R(29), r29 st.q SP, FRAME_R(30), r30 st.q SP, FRAME_R(31), r31 st.q SP, FRAME_R(32), r32 st.q SP, FRAME_R(33), r33 st.q SP, FRAME_R(34), r34 st.q SP, FRAME_R(35), r35 st.q SP, FRAME_R(36), r36 st.q SP, FRAME_R(37), r37 st.q SP, FRAME_R(38), r38 st.q SP, FRAME_R(39), r39 st.q SP, FRAME_R(40), r40 st.q SP, FRAME_R(41), r41 st.q SP, FRAME_R(42), r42 st.q SP, FRAME_R(43), r43 st.q SP, FRAME_R(44), r44 st.q SP, FRAME_R(45), r45 st.q SP, FRAME_R(46), r46 st.q SP, FRAME_R(47), r47 st.q SP, FRAME_R(48), r48 st.q SP, FRAME_R(49), r49 st.q SP, FRAME_R(50), r50 st.q SP, FRAME_R(51), r51 st.q SP, FRAME_R(52), r52 st.q SP, FRAME_R(53), r53 st.q SP, FRAME_R(54), r54 st.q SP, FRAME_R(55), r55 st.q SP, FRAME_R(56), r56 st.q SP, FRAME_R(57), r57 st.q SP, FRAME_R(58), r58 st.q SP, FRAME_R(59), r59 st.q SP, FRAME_R(60), r60 st.q SP, FRAME_R(61), r61 st.q SP, FRAME_R(62), r62 /* * Save the S* registers. */ getcon SSR, r61 st.q SP, FRAME_S(FSSR), r61 getcon SPC, r62 st.q SP, FRAME_S(FSPC), r62 movi -1, r62 /* Reset syscall_nr */ st.q SP, FRAME_S(FSYSCALL_ID), r62 /* Save the rest of the target registers */ gettr t1, r6 st.q SP, FRAME_T(1), r6 gettr t2, r6 st.q SP, FRAME_T(2), r6 gettr t3, r6 st.q SP, FRAME_T(3), r6 gettr t4, r6 st.q SP, FRAME_T(4), r6 gettr t5, r6 st.q SP, FRAME_T(5), r6 gettr t6, r6 st.q SP, FRAME_T(6), r6 gettr t7, r6 st.q SP, FRAME_T(7), r6/*#define POOR_MANS_STRACE 1*/ #ifdef POOR_MANS_STRACE /* We've pushed all the registers now, so only r2-r4 hold anything * useful. Move them into callee save registers */ or r2, ZERO, r28 or r3, ZERO, r29 or r4, ZERO, r30 /* Preserve r2 as the event code */ _loada evt_debug, r3 ori r3, 1, r3 ptabs r3, t0 /* or SP, ZERO, r5 */ getcon TRA, r5 blink t0, LINK or r28, ZERO, r2 or r29, ZERO, r3 or r30, ZERO, r4#endif /* For syscall and debug race condition, get TRA now */ getcon TRA, r5 /* We are in a safe position to turn SR.BL off, but set IMASK=0xf * Also set FD, to catch FPU usage in the kernel. * * benedict.gaster@superh.com 29/07/2002 * * On all SH5-101 revisions it is unsafe to raise the IMASK and at the * same time change BL from 1->0, as any pending interrupt of a level * higher than he previous value of IMASK will leak through and be * taken unexpectedly. * * To avoid this we raise the IMASK and then issue another PUTCON to * enable interrupts. */ getcon SR, r6 movi SR_IMASK | SR_FD, r7 or r6, r7, r6 putcon r6, SR movi SR_UNBLOCK_EXC, r7 and r6, r7, r6 putcon r6, SR /* Now call the appropriate 3rd level handler */ or r3, ZERO, LINK _loada trap_jtable, r3 shlri r2, 3, r2 ldx.l r2, r3, r3 shlri r2, 2, r2 ptabs r3, t0 or SP, ZERO, r3 blink t0, ZERO/* * Second level handler for VBR-based exceptions. Post-handlers. *
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?