1. 程式人生 > >Arm架構異常處理流程之中斷

Arm架構異常處理流程之中斷

arch/arm64/kernel/entry.s:   
el0_sync()/el0_irq() -> ret_to_user() -> work_pending() -> do_notify_resume()  
   
        // (1) 在arm64架構中,kernel執行在el1,使用者態執行在el0。
        // el0_sync是使用者態發生異常的入口,el0_irq是使用者態發生中斷的的入口。
        // 異常包括幾種:系統呼叫el0_svc、資料異常el0_da、指令異常el0_ia等等幾種。
        .align        11
ENTRY(vectors)
        ventry        el0_sync                        // Synchronous 64-bit EL0
        ventry        el0_irq                                // IRQ 64-bit EL0
        // (2) 使用者態異常el0_sync
        .align        6
el0_sync:
        kernel_entry 0
        mrs        x25, esr_el1                        // read the syndrome register
        lsr        x24, x25, #ESR_EL1_EC_SHIFT        // exception class
        cmp        x24, #ESR_EL1_EC_SVC64                // SVC in 64-bit state
        b.eq        el0_svc
        cmp        x24, #ESR_EL1_EC_DABT_EL0        // data abort in EL0
        b.eq        el0_da
        cmp        x24, #ESR_EL1_EC_IABT_EL0        // instruction abort in EL0
        b.eq        el0_ia
        cmp        x24, #ESR_EL1_EC_FP_ASIMD        // FP/ASIMD access
        b.eq        el0_fpsimd_acc
        cmp        x24, #ESR_EL1_EC_FP_EXC64        // FP/ASIMD exception
        b.eq        el0_fpsimd_exc
        cmp        x24, #ESR_EL1_EC_SYS64                // configurable trap
        b.eq        el0_undef
        cmp        x24, #ESR_EL1_EC_SP_ALIGN        // stack alignment exception
        b.eq        el0_sp_pc
        cmp        x24, #ESR_EL1_EC_PC_ALIGN        // pc alignment exception
        b.eq        el0_sp_pc
        cmp        x24, #ESR_EL1_EC_UNKNOWN        // unknown exception in EL0
        b.eq        el0_undef
        cmp        x24, #ESR_EL1_EC_BREAKPT_EL0        // debug exception in EL0
        b.ge        el0_dbg
        b        el0_inv
        // (2.1) 使用者態資料訪問el0_da
el0_da:
        /*
         * Data abort handling
         */
        mrs        x26, far_el1
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
        ct_user_exit
        bic        x0, x26, #(0xff << 56)
        mov        x1, x25
        mov        x2, sp
        bl        do_mem_abort
        b        ret_to_user
        // (3) 使用者態中斷el0_irq
        .align        6
el0_irq:
        kernel_entry 0
el0_irq_naked:
        enable_dbg
#ifdef CONFIG_TRACE_IRQFLAGS
        bl        trace_hardirqs_off
#endif
        ct_user_exit
        irq_handler
#ifdef CONFIG_TRACE_IRQFLAGS
        bl        trace_hardirqs_on
#endif
        b        ret_to_user
ENDPROC(el0_irq)
        // (4) 返回使用者態的處理函式ret_to_user
        // 判斷thread_info->flags與#_TIF_WORK_MASK,是否有置位,有則跳轉到work_pending執行。
        // _TIF_SIGPENDING置位即代表了程序有訊號需要處理
        // #define _TIF_WORK_MASK                (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
        //                         _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
ret_to_user:
        disable_irq                                // disable interrupts
        ldr        x1, [tsk, #TI_FLAGS]
        and        x2, x1, #_TIF_WORK_MASK
        cbnz        x2, work_pending
        enable_step_tsk x1, x2
no_work_pending:
#ifdef CONFIG_MTK_COMPAT
        kernel_exit_compat ret = 0
#else
        kernel_exit 0, ret = 0
#endif
ENDPROC(ret_to_user)
        // (5) work_pending
fast_work_pending:
        str        x0, [sp, #S_X0]                        // returned x0
work_pending:
        tbnz        x1, #TIF_NEED_RESCHED, work_resched
        /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */
        ldr        x2, [sp, #S_PSTATE]
        mov        x0, sp                                // 'regs'
Markdown
Toggle Zen Mode
Preview
        tst        x2, #PSR_MODE_MASK                // user mode regs?
        b.ne        no_work_pending                        // returning to kernel
        enable_irq                                // enable interrupts for do_notify_resume()
        bl        do_notify_resume
        b        ret_to_user
work_resched:
        bl        schedule