微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux异常处理之data abort

ARM Linux异常处理之data abort

时间:11-09 来源:互联网 点击:

1 异常向量与程序跳转

data abortARM体系定义的异常之一。异常发生时,ARM会自动跳转到异常向量表中,通过向量表中的跳转命令跳转到相应的异常处理中去。
ARM的异常处理向量表在entry-armv.S文件中:
.globl      __vectors_start__vectors_start:swi   SYS_ERROR0b     vector_und + stubs_offsetldr   pc, .LCvswi + stubs_offsetb     vector_pabt + stubs_offsetb     vector_dabt + stubs_offsetb     vector_addrexcptn + stubs_offsetb     vector_irq + stubs_offsetb     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      5vector_\name:.if \correctionsub  lr, lr, #\correction.endif@@ Save r0, lr_ (parent PC) and spsr_@ (parent CPSR)@stmia       sp, {r0, lr}             @ save r0, lrmrs  lr, spsr                          @ 保存跳转之前的CPSR到lr寄存器str    lr, [sp, #8]                    @ save spsr@@ Prepare for SVC32 mode.  IRQs remain disabled.@mrs  r0, cpsreor   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, spldr   lr, [pc, lr, lsl #2]            @ 根据模式跳转到相应的data abort指令,并进入svc模式movs       pc, lr                     @ branch to handler in SVC modeENDPROC(vector_\name).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时的处理过程。

2 svc模式进入data abort

svc模式进入data abort,也就是Linux的内核模式进入data aboart时,会跳转到__dabt_svc。
__dabt_svc:svc_entry               @ 保护寄存器现场mrs  r9, cpsrtst    r3, #PSR_I_BIT            @ 检查是否要开中断biceq       r9, r9, #PSR_I_BITbl    CPU_DABORT_HANDLER  @ 处理异常之前的准备工作msr  cpsr_c, r9mov r2, spbl    do_DataAbort        @ 主要操作都在这里,本文暂不研究disable_irqldr   r0, [sp, #S_PSR]msr  spsr_cxsf, r0ldmia      sp, {r0 - pc}^                @ load r0 - pc, cpsrENDPROC(__dabt_svc)
CPU_DABORT_HANDLER的定义在glue.h:
#define CPU_DABORT_HANDLER v6_early_abort
对于s3c6410,v6_early_abort的定义在abort-ev6.S中,里面涉及到很多ARM的细节操作,但对我们来说,只需要了解下面这两句即可:
mrc  p15, 0, r1, c5, c0, 0              @ get FSRmrc  p15, 0, r0, c6, c0, 0              @ get FAR
这两句用于读取协处理器CP15的C5、C6寄存器。当data abort异常发生时,C5寄存器中保存的值指明了是哪种原因导致的异常,具体原因可在介绍arm的资料中找到。C6寄存器中保存的是导致data abort的存储地址。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top