ARM Linux异常处理之data abort


本文简要分析了ARM Linuxdata abort异常处理过程,内核版本2.6.28s3c6410平台。

异常向量与程序跳转

data abortARM体系定义的异常之一。异常发生时,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                     @  f

vector_stub是一个宏定义:

       .macro     vector_stub, name, mode, correction=0

       .align      5

vector_\name:

       .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                          @ 保存跳转之前的CPSRlr寄存器

       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                    @ 得到跳转前所处的模式(usrsvr等)

       mov r0, sp

       ldr   lr, [pc, lr, lsl #2]            @ 根据模式跳转到相应的data abort指令,并进入svc模式

       movs       pc, lr                     @ branch to handler in SVC mode

ENDPROC(vector_\name)

       .endm

由代码中红色标注部分可看出,对于同一个异常,根据进入异常之前所处的模式,会跳转到不同的指令分支,www.bkjia.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时的处理过程。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 下一页

相关内容