其次设置栈帧大小S_FRAM_SIZE,S_FRAM_SIZE根据pt_regs结构体大小而设定。 ![]() pt_regs结构体: ![]() 另外就是读取elr_el1和spsr_el1等寄存器值。总之,kernel_entry主要将CPU寄存器按照pt_regs结构体的定义将异常第一现场保存到栈上。 (2)判断异常类型 kernel_entry保存完第一现场之后,接下来读取esr_el1寄存器的值,并判断异常的具体类型。如2.3.5章节所描述的ESR寄存器定义,ESR包含的异常信息主要用于异常处理程序确定异常原因,其中ESR_ELn的BIT[31:26] EC域指示处理程序执行的对应异常类型。 发生DataAbort时,EC = 0b100101,即ESR_ELx_EC_DABT_CUR=0x25,el1_syn将跳转至el1_da。 ![]() ESR_ELx_EC_DABT_CUR定义在/kernel/msm-4.19/arch/arm64/include/asm/esr.h。 除此之外,还有其他的同步异常类型,比如: ![]() (3)跳转至异常类型标签 通过esr_el1寄存器值确定同步异常的具体类型后,跳转至对应的异常处理标签el1_da。el1_da第一条指令,mrs x3,far_el1,将far_el1保存到x3。在2.4异常入口章节介绍过如果发生数据中止异常(DataAbort exception),故障的虚拟地址将保存在FAR_ELx中。这里就是首先将data abort异常发生的虚拟地址第一时间取出,保持在x3中。 ![]() el1_da 跳转到异常处理程序do_mem_abort之前,为其设置好了三个入参:
|