首页 / 操作系统 / Linux / ARM Linux异常处理之data abort
本文简要分析了ARM Linux的data abort异常处理过程,内核版本2.6.28,s3c6410平台。
异常向量与程序跳转
data abort是ARM体系定义的异常之一。异常发生时,ARM会自动跳转到异常向量表中,通过向量表中的跳转命令跳转到相应的异常处理中去。ARM的异常处理向量表在entry-armv.S文件中: .globl __vectors_start__vectors_start: swi SYS_ERROR0 b vector_und + stubs_offset ldr pc, .LCvswi + stubs_offset b vector_pabt + stubs_offset b vector_dabt + stubs_offset b vector_addrexcptn + stubs_offset b vector_irq + stubs_offset b vector_fiq + stubs_offset对于data abort,对应的跳转地址是vector_dabt + stubs_offset。这个地址的指令定义也在entry-armv.S: vector_stub dabt, ABT_MODE, 8 .long __dabt_usr @ 0 (USR_26 / USR_32) .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) .long __dabt_invalid @ 2 (IRQ_26 / IRQ_32) .long __dabt_svc @ 3 (SVC_26 / SVC_32) .long __dabt_invalid @ 4 .long __dabt_invalid @ 5 .long __dabt_invalid @ 6 .long __dabt_invalid @ 7 .long __dabt_invalid @ 8 .long __dabt_invalid @ 9 .long __dabt_invalid @ a .long __dabt_invalid @ b .long __dabt_invalid @ c .long __dabt_invalid @ d .long __dabt_invalid @ e .long __dabt_invalid @ fvector_stub是一个宏定义: .macro vector_stub, name, mode, correction=0 .align 5vector_
ame: .if correction sub lr, lr, #correction .endif @ @ Save r0, lr_<exception> (parent PC) and spsr_<exception> @ (parent CPSR) @ stmia sp, {r0, lr} @ save r0, lr mrs lr, spsr @ 保存跳转之前的CPSR到lr寄存器 str lr, [sp, #8] @ save spsr @ @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr eor r0, r0, #(mode ^ SVC_MODE) msr spsr_cxsf, r0 @ 准备进入svc模式 @ @ the branch table must immediately follow this code @ and lr, lr, #0x0f @ 得到跳转前所处的模式(usr、svr等) mov r0, sp ldr lr, [pc, lr, lsl #2] @ 根据模式跳转到相应的data abort指令,并进入svc模式 movs pc, lr @ branch to handler in SVC modeENDPROC(vector_
ame) .endm由代码中红色标注部分可看出,对于同一个异常,根据进入异常之前所处的模式,会跳转到不同的指令分支,www.linuxidc.com这些指令分支紧跟在vector_stub宏定义的后面。如果进入data abort之前处于usr模式,那么跳转到__dabt_usr;如果处于svc模式,那么跳转到__dabt_svc;否则跳转到__dabt_invalid。实际上,进入异常向量前Linux只能处于usr或者svc两种模式之一。这时因为irq等异常在跳转表中都要经过vector_stub宏,而不管之前是哪种状态,这个宏都会将CPU状态改为svc模式。usr模式即Linux中的用户态模式,svc即内核模式。下面看一下在不同模式下进入data abort时的处理过程。