如上連接是《宋寶華: Kernel Oops和Panic是一回事嗎?》spa
大概介紹了在未開啓panic_on_oops,內核態非中斷上下文 發生 訪問0地址 時,kernel只會發oops,而不會panic。debug
看完以後會有個疑問:缺頁異常的上下文 是否是 中斷上下文?調試
答案是否。具體解析以下:code
1. 首先中斷上下文是指當前HARDIRQ/NMI/softIRQ的計數不爲0,code 以下:blog
1 #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \ 2 | NMI_MASK)) 3 #define in_interrupt() (irq_count())
HARDIRQ 計數 在irq_enter()/irq_exit()接口中 作增減, 題外話:在irq_exit接口中經過invoke_softirq()觸發軟中斷,一次執行時間限制在2ms或10次之內接口
NMI 計數 在nmi_enter()/nmi_exit()接口中 作增減,ARM64貌似沒有找到調用的地方?????ip
softIRQ 計數 在__local_bh_disable_ip/__local_bh_enable接口中 作增減ci
2. 對於ARM64, 異常向量表以下:get
1 // 文件:arch/arm64/kernel/entry.S 2 3 // 向量表------------------------------------------------------------------------------------------------ 4 .align 11 //對齊2^7=128 5 ENTRY(vectors) 6 ventry el1_sync_invalid // Synchronous EL1t 7 ventry el1_irq_invalid // IRQ EL1t 8 ventry el1_fiq_invalid // FIQ EL1t 9 ventry el1_error_invalid // Error EL1t 10 11 ventry el1_sync // Synchronous EL1h 同步異常入口,缺頁屬於這一類 12 ventry el1_irq // IRQ EL1h IRQ中斷入口, HARDIRQ/SOFTIRQ 計數均在此入口增減 13 ventry el1_fiq_invalid // FIQ EL1h FIQ入口,即NMI???? NMI計數應該在這個入口增減??? 14 ventry el1_error_invalid // Error EL1h 15 16 ventry el0_sync // Synchronous 64-bit EL0 17 ventry el0_irq // IRQ 64-bit EL0 18 ventry el0_fiq_invalid // FIQ 64-bit EL0 19 ventry el0_error_invalid // Error 64-bit EL0 20 21 #ifdef CONFIG_COMPAT 22 ventry el0_sync_compat // Synchronous 32-bit EL0 23 ventry el0_irq_compat // IRQ 32-bit EL0 24 ventry el0_fiq_invalid_compat // FIQ 32-bit EL0 25 ventry el0_error_invalid_compat // Error 32-bit EL0 26 #else 27 ventry el0_sync_invalid // Synchronous 32-bit EL0 28 ventry el0_irq_invalid // IRQ 32-bit EL0 29 ventry el0_fiq_invalid // FIQ 32-bit EL0 30 ventry el0_error_invalid // Error 32-bit EL0 31 #endif 32 END(vectors) 33 34 // 同步異常:系統調用/數據abort/指令abort/未對齊/未定義/調試異常--------------------------------------------- 35 .align 6 36 el1_sync: 37 kernel_entry 1 38 mrs x1, esr_el1 // read the syndrome register 39 lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class 40 cmp x24, #ESR_ELx_EC_DABT_CUR // data abort in EL1 41 b.eq el1_da 42 cmp x24, #ESR_ELx_EC_SYS64 // configurable trap 43 b.eq el1_undef 44 cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception 45 b.eq el1_sp_pc 46 cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception 47 b.eq el1_sp_pc 48 cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1 49 b.eq el1_undef 50 cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1 51 b.ge el1_dbg 52 b el1_inv 53 // 數據abort 54 el1_da: 55 /* 56 * Data abort handling 57 */ 58 mrs x0, far_el1 59 enable_dbg 60 // re-enable interrupts if they were enabled in the aborted context 61 tbnz x23, #7, 1f // PSR_I_BIT 62 enable_irq 63 1: 64 mov x2, sp // struct pt_regs 65 // 跳往do_mem_abort->do_transation_fault->do_page_fault->do_kernel_fault->die->... 66 bl do_mem_abort 67 68 // disable interrupts before pulling preserved data off the stack 69 disable_irq 70 kernel_exit 1 71 el1_sp_pc: 72 /* 73 * Stack or PC alignment exception handling 74 */ 75 mrs x0, far_el1 76 enable_dbg 77 mov x2, sp 78 b do_sp_pc_abort 79 el1_undef: 80 /* 81 * Undefined instruction 82 */ 83 enable_dbg 84 mov x0, sp 85 b do_undefinstr 86 el1_dbg: 87 /* 88 * Debug exception handling 89 */ 90 cmp x24, #ESR_ELx_EC_BRK64 // if BRK64 91 cinc x24, x24, eq // set bit '0' 92 tbz x24, #0, el1_inv // EL1 only 93 mrs x0, far_el1 94 mov x2, sp // struct pt_regs 95 bl do_debug_exception 96 kernel_exit 1 97 el1_inv: 98 // TODO: add support for undefined instructions in kernel mode 99 enable_dbg 100 mov x0, sp 101 mov x1, #BAD_SYNC 102 mrs x2, esr_el1 103 b bad_mode 104 ENDPROC(el1_sync) 105 106 // IRQ------------------------------------------------------------------------------------------------------- 107 .align 6 108 el1_irq: 109 kernel_entry 1 110 enable_dbg 111 #ifdef CONFIG_TRACE_IRQFLAGS 112 bl trace_hardirqs_off 113 #endif 114 // 中斷入口調用:handle_arch_irq->handle_irq 115 irq_handler 116 117 #ifdef CONFIG_PREEMPT 118 get_thread_info tsk 119 ldr w24, [tsk, #TI_PREEMPT] // get preempt count 120 cbnz w24, 1f // preempt count != 0 121 ldr x0, [tsk, #TI_FLAGS] // get flags 122 tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? 123 // 中斷返回前執行搶佔 124 bl el1_preempt 125 1: 126 #endif 127 #ifdef CONFIG_TRACE_IRQFLAGS 128 bl trace_hardirqs_on 129 #endif 130 kernel_exit 1 131 ENDPROC(el1_irq)
3. HARDIRQ softIRQ 計數增減 的 代碼流程,即缺頁異常的流程 以下圖:
綜上,在缺頁的流程中:HARDIRQ/SOFTIRQ/NMI計數都沒有增減,故in_interrupt()