linux arm tst 命令,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 @ f

vector_stub是一个宏定义:

.macro vector_stub, name, mode,

correction=0

.align

5

vector_/name:

.if

/correction

sub lr, lr,

#/correction

.endif

@

@ Save r0, lr_ (parent PC) and

spsr_

@ (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 mode

ENDPROC(vector_/name)

.endm

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

svc模式进入data

abort

svc模式进入data

abort,也就是Linux的内核模式进入data

aboart时,会跳转到__dabt_svc。

__dabt_svc:

svc_entry

@ 保护寄存器现场

mrs

r9, cpsr

tst r3, #PSR_I_BIT @ 检查是否要开中断

biceq r9, r9,

#PSR_I_BIT

bl CPU_DABORT_HANDLER@ 处理异常之前的准备工作

msr

cpsr_c, r9

mov

r2, sp

bl do_DataAbort

@ 主要操作都在这里,本文暂不研究

disable_irq

ldr

r0, [sp, #S_PSR]

msr

spsr_cxsf, r0

ldmia

sp, {r0 - pc}^ @ load r0 - pc, cpsr

ENDPROC(__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

FSR

mrc p15, 0, r0, c6, c0, 0 @ get

FAR

这两句用于读取协处理器CP15的C5、C6寄存器。当data

abort异常发生时,C5寄存器中保存的值指明了是哪种原因导致的异常,具体原因可在介绍arm的资料中找到。C6寄存器中保存的是导致data

abort的存储地址。

usr模式进入data

abort

usr模式进入data

abort,也就是Linux的用户模式进入data

bort时,会跳转到__dabt_usr。

__dabt_usr:

usr_entry

@ 保护寄存器现场

kuser_cmpxchg_check

bl CPU_DABORT_HANDLER

@ 与svc模式时处理过程一样

enable_irq @ 开中断

mov r2,

sp

adr lr, ret_from_exception

@ 重设返回地址

b do_DataAbort @

与svc模式时处理过程一样

ENDPROC(__dabt_usr)

由代码可知,用户模式和内核模式的data

abort处理过程类似,区别在于:

l用户模式下data

abort处理一定是开中断的;内核模式下则由具体情况决定。

l用户模式下异常处理返回地址被设为ret_from_exception

(entry-armv.S文件);内核模式下则返回到出现异常的那条语句。

下面看一下ret_from_exception:

ENTRY(ret_from_exception)

get_thread_info

tsk

mov why,

#0

b

ret_to_user

ENDPROC(__pabt_usr)

ret_to_user会判断是否需要进行进程调度,并最终返回到用户空间。用户空间data

abort时可能产生进程调度的原因就在这里。

未定义状态的data

abort

除了usr和svc模式之外,其它模式下发生data

abort时,都会调用__dabt_invalid函数。这里所说的其它模式在linux正常运行过程中是不应该存在的,所以如果进入__dabt_invalid函数,那就代表Linux内核应该崩溃了。

__dabt_invalid:

inv_entry BAD_DATA

b

common_invalid

ENDPROC(__dabt_invalid)

inv_entry宏做的主要工作是保存寄存器现场(压栈)。

common_invalid做一些必要的设置,最终调用C函数bad_mode

(traps.c)。

asmlinkage void bad_mode(struct

pt_regs *regs, int reason)

{

console_verbose();

printk(KERN_CRIT "Bad mode in %s

handler detected/n",

handler[reason]);

die("Oops - bad mode", regs,

0);

local_irq_disable();

panic("bad

mode");

}

由代码可知,bad_mode主要是输出一些必要的信息,然后调用panic函数,进入死循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值