entry.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 2,106 行 · 第 1/4 页
S
2,106 行
* Post-handlers for interrupts (ret_from_irq), exceptions * (ret_from_exception) and common reentrance doors (restore_all * to get back to the original context, ret_from_syscall loop to * check kernel exiting). * * ret_with_reschedule and check_signals are an inner lables of * the ret_from_syscall loop. * * In common to all stack-frame sensitive handlers. * * Inputs: * (SP) struct pt_regs *, original register's frame pointer (basic) * */ret_from_irq: ld.q SP, FRAME_S(FSSR), r6 shlri r6, 30, r6 andi r6, 1, r6 _ptar restore_all, t0 bne r6, ZERO, t0 /* no further checks */ STI() _ptar ret_with_reschedule, t0 blink t0, ZERO /* Do not check softirqs */ ret_from_exception: ld.q SP, FRAME_S(FSSR), r6 shlri r6, 30, r6 andi r6, 1, r6 _ptar restore_all, t0 bne r6, ZERO, t0 /* no further checks */ /* Check softirqs */ /* * Fall-through: * _ptar ret_from_syscall, t0 * blink t0, ZERO */ret_from_syscall: ret_with_reschedule: getcon KCR0, r6 ld.l r6, need_resched, r7 _ptar check_signals, t0 beq r7, ZERO, t0 _ptar ret_from_syscall, t0 gettr t0, LINK _loada schedule, r6 ptabs r6, t0 blink t0, ZERO /* Call schedule(), return on top */check_signals: getcon KCR0, r6 ld.l r6, sigpending, r7 _ptar restore_all, t0 beq r7, ZERO, t0 _loada do_signal, r6 ptabs r6, t0 or SP, ZERO, r2 or ZERO, ZERO, r3 blink t0, LINK /* Call do_signal(regs, 0), return here */ #ifdef CONFIG_SH64_PAGE_TABLE_AUDIT /* Check page tables before returning (with obvious performance penalty). */ _loada audit_mm, r6 ptabs r6, t0 getcon expevt, r2 getcon intevt, r3 getcon tra, r4 getcon dcr, r5 blink t0, LINK#endifrestore_all: /* Do prefetches */ ld.q SP, FRAME_T(0), r6 ld.q SP, FRAME_T(1), r7 ld.q SP, FRAME_T(2), r8 ld.q SP, FRAME_T(3), r9 ptabs r6, t0 ptabs r7, t1 ptabs r8, t2 ptabs r9, t3 ld.q SP, FRAME_T(4), r6 ld.q SP, FRAME_T(5), r7 ld.q SP, FRAME_T(6), r8 ld.q SP, FRAME_T(7), r9 ptabs r6, t4 ptabs r7, t5 ptabs r8, t6 ptabs r9, t7 ld.q SP, FRAME_R(0), r0 ld.q SP, FRAME_R(1), r1 ld.q SP, FRAME_R(2), r2 ld.q SP, FRAME_R(3), r3 ld.q SP, FRAME_R(4), r4 ld.q SP, FRAME_R(5), r5 ld.q SP, FRAME_R(6), r6 ld.q SP, FRAME_R(7), r7 ld.q SP, FRAME_R(8), r8 ld.q SP, FRAME_R(9), r9 ld.q SP, FRAME_R(10), r10 ld.q SP, FRAME_R(11), r11 ld.q SP, FRAME_R(12), r12 ld.q SP, FRAME_R(13), r13 ld.q SP, FRAME_R(14), r14 ld.q SP, FRAME_R(16), r16 ld.q SP, FRAME_R(17), r17 ld.q SP, FRAME_R(18), r18 ld.q SP, FRAME_R(19), r19 ld.q SP, FRAME_R(20), r20 ld.q SP, FRAME_R(21), r21 ld.q SP, FRAME_R(22), r22 ld.q SP, FRAME_R(23), r23 ld.q SP, FRAME_R(24), r24 ld.q SP, FRAME_R(25), r25 ld.q SP, FRAME_R(26), r26 ld.q SP, FRAME_R(27), r27 ld.q SP, FRAME_R(28), r28 ld.q SP, FRAME_R(29), r29 ld.q SP, FRAME_R(30), r30 ld.q SP, FRAME_R(31), r31 ld.q SP, FRAME_R(32), r32 ld.q SP, FRAME_R(33), r33 ld.q SP, FRAME_R(34), r34 ld.q SP, FRAME_R(35), r35 ld.q SP, FRAME_R(36), r36 ld.q SP, FRAME_R(37), r37 ld.q SP, FRAME_R(38), r38 ld.q SP, FRAME_R(39), r39 ld.q SP, FRAME_R(40), r40 ld.q SP, FRAME_R(41), r41 ld.q SP, FRAME_R(42), r42 ld.q SP, FRAME_R(43), r43 ld.q SP, FRAME_R(44), r44 ld.q SP, FRAME_R(45), r45 ld.q SP, FRAME_R(46), r46 ld.q SP, FRAME_R(47), r47 ld.q SP, FRAME_R(48), r48 ld.q SP, FRAME_R(49), r49 ld.q SP, FRAME_R(50), r50 ld.q SP, FRAME_R(51), r51 ld.q SP, FRAME_R(52), r52 ld.q SP, FRAME_R(53), r53 ld.q SP, FRAME_R(54), r54 ld.q SP, FRAME_R(55), r55 ld.q SP, FRAME_R(56), r56 ld.q SP, FRAME_R(57), r57 ld.q SP, FRAME_R(58), r58 getcon SR, r59 movi SR_BLOCK_EXC, r60 or r59, r60, r59 putcon r59, SR /* SR.BL = 1, keep nesting out */ ld.q SP, FRAME_S(FSSR), r61 ld.q SP, FRAME_S(FSPC), r62 movi SR_ASID_MASK, r60 and r59, r60, r59 andc r61, r60, r61 /* Clear out older ASID */ or r59, r61, r61 /* Retain current ASID */ putcon r61, SSR putcon r62, SPC /* Ignore FSYSCALL_ID */ ld.q SP, FRAME_R(59), r59 ld.q SP, FRAME_R(60), r60 ld.q SP, FRAME_R(61), r61 ld.q SP, FRAME_R(62), r62 /* Last touch */ ld.q SP, FRAME_R(15), SP rte nop/* * Third level handlers for VBR-based exceptions. Adapting args to * and/or deflecting to fourth level handlers. * * Fourth level handlers interface. * Most are C-coded handlers directly pointed by the trap_jtable. * (Third = Fourth level) * Inputs: * (r2) fault/interrupt code, entry number (e.g. NMI = 14, * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) * (r3) struct pt_regs *, original register's frame pointer * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) * (r5) TRA control register (for syscall/debug benefit only) * (LINK) return address * (SP) = r3 * * Kernel TLB fault handlers will get a slightly different interface. * (r2) struct pt_regs *, original register's frame pointer * (r3) writeaccess, whether it's a store fault as opposed to load fault * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault * (r5) Effective Address of fault * (LINK) return address * (SP) = r2 * * fpu_error_or_IRQ? is a helper to deflect to the right cause. * */tlb_miss_load: or SP, ZERO, r2 or ZERO, ZERO, r3 /* Read */ or ZERO, ZERO, r4 /* Data */ getcon TEA, r5 _ptar call_do_page_fault, t0 beq ZERO, ZERO, tr0tlb_miss_store: or SP, ZERO, r2 movi 1, r3 /* Write */ or ZERO, ZERO, r4 /* Data */ getcon TEA, r5 _ptar call_do_page_fault, t0 beq ZERO, ZERO, tr0itlb_miss_or_IRQ: _ptar its_IRQ, t0 beqi/u r4, EVENT_INTERRUPT, t0 or SP, ZERO, r2 or ZERO, ZERO, r3 /* Read */ movi 1, r4 /* Text */ getcon TEA, r5 /* Fall through */call_do_page_fault: _loada do_page_fault, r6 ptabs r6, t0 blink t0, ZERO fpu_error_or_IRQA: _ptar its_IRQ, t0 beqi/l r4, EVENT_INTERRUPT, t0#ifndef CONFIG_NOFPU_SUPPORT _loada do_fpu_state_restore, r6#else _loada do_exception_error, r6#endif ptabs r6, t0 blink t0, ZEROfpu_error_or_IRQB: _ptar its_IRQ, t0 beqi/l r4, EVENT_INTERRUPT, t0#ifndef CONFIG_NOFPU_SUPPORT _loada do_fpu_state_restore, r6#else _loada do_exception_error, r6#endif ptabs r6, t0 blink t0, ZEROits_IRQ: _loada do_IRQ, r6 ptabs r6, t0 blink t0, ZERO/* * system_call/unknown_trap third level handler: * * Inputs: * (r2) fault/interrupt code, entry number (TRAP = 11) * (r3) struct pt_regs *, original register's frame pointer * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) * (SP) = r3 * (LINK) return address: ret_from_exception * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) * * Outputs: * (*r3) Syscall reply (Saved r2) * (LINK) In case of syscall only it can be scrapped. * Common second level post handler will be ret_from_syscall. * Common (non-trace) exit point to that is syscall_ret (saving * result to r2). Common bad exit point is syscall_bad (returning * ENOSYS then saved to r2). * */unknown_trap: /* Unknown Trap or User Trace */ _loada do_unknown_trapa, r6 ptabs r6, t0 ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */ andi r2, 0x1ff, r2 /* r2 = syscall # */ blink t0, LINK _ptar syscall_ret, t0 blink t0, ZERO /* New syscall implementation*/system_call: _ptar unknown_trap, t0 or r5, ZERO, r4 /* TRA (=r5) -> r4 */ shlri r4, 20, r4 bnei r4, 1, t0 /* unknown_trap if not 0x1yzzzz */ /* It's a system call */ st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */ andi r5, 0x1ff, r5 /* syscall # -> r5 */ STI() _ptar syscall_allowed, t0 movi NR_syscalls - 1, r4 /* Last valid */ bgeu/l r4, r5, t0syscall_bad: /* Return ENOSYS ! */ movi -(ENOSYS), r2 /* Fall-through */syscall_ret: st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */#ifdef POOR_MANS_STRACE /* nothing useful in registers at this point */ _loada evt_debug2, r5 ori r5, 1, r5 ptabs r5, t0 ld.q SP, FRAME_R(9), r2 or SP, ZERO, r3 blink t0, LINK#endif ld.q SP, FRAME_S(FSPC), r2 addi r2, 4, r2 /* Move PC, being pre-execution event */ st.q SP, FRAME_S(FSPC), r2 _ptar ret_from_syscall, t0 blink t0, ZERO/* A different return path for ret_from_fork, because we now need * to call schedule_tail with the later kernels. Because prev is * loaded into r2 by switch_to() means we can just call it straight away */ .global ret_from_forkret_from_fork: _loada schedule_tail,r5 ori r5, 1, r5 ptabs r5, t0 blink t0, LINK #ifdef POOR_MANS_STRACE /* nothing useful in registers at this point */ _loada evt_debug2, r5 ori r5, 1, r5 ptabs r5, t0 ld.q SP, FRAME_R(9), r2 or SP, ZERO, r3 blink t0, LINK#endif ld.q SP, FRAME_S(FSPC), r2 addi r2, 4, r2 /* Move PC, being pre-execution event */ st.q SP, FRAME_S(FSPC), r2 _ptar ret_from_syscall, t0 blink t0, ZERO syscall_allowed: /* Use LINK to deflect the exit point, default is syscall_ret */ _ptar syscall_ret, t0 gettr t0, LINK _ptar syscall_notrace, t0 getcon KCR0, r2 ld.l r2, ptrace, r4 andi r4, PT_TRACESYS, r4 beq/l r4, ZERO, t0 /* Trace it by calling syscall_trace before and after */ _loada syscall_trace, r4 ptabs r4, t0 blink t0, LINK /* Reload syscall number as r5 is trashed by syscall_trace */ ld.q SP, FRAME_S(FSYSCALL_ID), r5 andi r5, 0x1ff, r5 _ptar syscall_ret_trace, t0 gettr t0, LINKsyscall_notrace: /* Now point to the appropriate 4th level syscall handler */ _loada sys_call_table, r4 shlli r5, 2, r5 ldx.l r4, r5, r5 ptabs r5, t0 /* Prepare original args */ ld.q SP, FRAME_R(2), r2 ld.q SP, FRAME_R(3), r3 ld.q SP, FRAME_R(4), r4 ld.q SP, FRAME_R(5), r5 ld.q SP, FRAME_R(6), r6 ld.q SP, FRAME_R(7), r7 /* And now the trick for those syscalls requiring regs * ! */ or SP, ZERO, r8 /* Call it */ blink t0, ZERO /* LINK is already properly set */syscall_ret_trace: /* We get back here only if under trace */ st.q SP, FRAME_R(9), r2 /* Save return value */ /* ... usage of a pt relative (_ptar _syscall_trace) fails on CDC */ _loada syscall_trace, LINK ptabs LINK, t0 blink t0, LINK /* This needs to be done after any syscall tracing */ ld.q SP, FRAME_S(FSPC), r2 addi r2, 4, r2 /* Move PC, being pre-execution event */ st.q SP, FRAME_S(FSPC), r2 _ptar ret_from_syscall, t0 blink t0, ZERO /* Resume normal return sequence *//* * --- Switch to running under a particular ASID and return the previous ASID value * --- The caller is assumed to have done a cli before calling this. * * Input r2 : new ASID * Output r2 : old ASID */ .global switch_and_save_asidswitch_and_save_asid: getcon sr, r0 movi 255, r4 shlli r4, 16, r4 /* r4 = mask to select ASID */ and r0, r4, r3 /* r3 = shifted old ASID */ andi r2, 255, r2 /* mask down new ASID */ shlli r2, 16, r2 /* align new ASID against SR.ASID */ andc r0, r4, r0 /* efface old ASID from SR */ or r0, r2, r0 /* insert the new ASID */ putcon r0, ssr _loada 1f, r0 putcon r0, spc rte nop1: ptabs r18, tr0 shlri r3, 16, r2 /* r2 = old ASID */ blink tr0, r63 .global route_to_panic_handlerroute_to_panic_handler: /* Switch to real mode, goto panic_handler, don't return. Useful for last-chance debugging, e.g. if no output wants to go to the console. */ _loada panic_handler - CONFIG_CACHED_MEMORY_OFFSET, r1 ptabs r1, tr0 pta 1f, tr1 gettr tr1, r0 putcon r0, spc getcon sr, r0 movi 1, r1 shlli r1, 31, r1 andc r0, r1, r0 putcon r0, ssr rte nop1: /* Now in real mode */ blink tr0, r63 nop .global peek_real_address_qpeek_real_address_q: /* Two args: r2 : real mode address to peek r2(out) : result quadword This is provided as a cheapskate way of manipulating device registers for debugging (to avoid the need to onchip_remap the debug module, and to avoid the need to onchip_remap the watchpoint controller in a way that identity maps sufficient bits to avoid the SH5-101 cut2 silicon defect). This code is not performance critical */ add.l r2, r63, r2 /* sign extend address */ getcon sr, r0 /* r0 = saved original SR */ movi 1, r1 shlli r1, 28, r1 or r0, r1, r1 /* r0 with block bit set */ putcon r1, sr /* now in critical section */ movi 1, r36 shlli r36, 31, r36 andc r1, r36, r1 /* turn sr.mmu off in real mode section */ putcon r1, ssr _loada .peek0 - CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */ _loada 1f, r37 /* virtual mode return addr */ putcon r36, spc synco rte nop.peek0: /* come here in real mode, don't touch caches!! still in critical section (sr.bl==1) */ putcon r0, ssr putcon r37, spc /* Here's the actual peek. If the address is bad, all bets are now off * what will happen (handlers invoked in real-mode = bad news) */ ld.q r2, 0, r2 synco rte /* Back to virtual mode */ nop1:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?