《Linux内核深度解析》-异常处理
一、异常级别
二、异常分类
异常分为同步异常和异步异常。如下图所示
三、异常处理
以出现用户模式(异常级别0)下访问数据时生成的页错误异常为例。
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 //调用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
对于用户模式(异常级别0)下生成的同步异常,入口是el0_sync。该入口函数在arch/arm64/kernel/entry.s中
通过上面代码,跳到对应的异常处理函数,
其中:访问数据时生成的页错误异常,通过( b.eq el0_da //调用el0_da )这行代码,进入 el0_da 函数。
下面为 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 //调用do_mem_abort函数
b ret_to_user
通过do_mem_abort( ) 函数将异常信息进行处理。