-
2009-01-07
u-boot arm920t data_abort 异常处理分析
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://hunbalo.blogbus.com/logs/33513377.html
在porting u-boot到 microsot device emulator 的时候遇到了data abort问题,索性分析一下
u-boot中data abort异常处理的实现。
截取data abort 异常处理相关的代码片断,展开宏
.globl _start
_start: b start_code
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq...
data_abort:
;expand macro get_bad_stack
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE)
sub r13, r13, #(CFG_MALLOC_LEN)
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stackstr lr, [r13] @ save caller lr / spsr
mrs lr, spsr
str lr, [r13, #4]mov r13, #MODE_SVC @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc
movs pc, lr
;expand macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE)
sub r2, r2, #(CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
ldmia r2, {r2 - r3} @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE @ restore sp_SVCadd r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp
bl do_data_abort
下面的代码完成设置abt模式下的堆栈,并保存spsr和Lr(r14, 异常发生指令的pc+8)
进入abort模式时
spsr_abt = spsr
r14_abt = pc+8
将这两个寄存器8个字节的数据保存在abt模式的堆栈中
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE)
sub r13, r13, #(CFG_MALLOC_LEN)
sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stackstr lr, [r13] @ save caller lr / spsr
mrs lr, spsr
str lr, [r13, #4]
切换到svc模式,由于abt模式也是特权模式,因此可以模式切换
mov r13, #MODE_SVC @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc
movs pc, lr
在svc的堆栈中,保存r0-r12
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
把进入abt模式时保存的r14(发生异常时的pc+8的值), spsr分别放在r2,r3中
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE)
sub r2, r2, #(CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
ldmia r2, {r2 - r3} @ get pc, cpsr
保存发生异常时的sp到r0, lr到r1
sp=>r0
lr=>r1
pc=>r2
cpsr=>r3
add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
add r5, sp, #S_SP
mov r1, lr
保存sp, lr, pc, cpsr到sr_frame
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
sr_frame作为参数传给do_data_abort
mov r0, sp
bl do_data_abort
这样在调用do_data_abort函数时
sr_frame的结构如下
CPSR
PC
LR
SP
R12
R11
R10
R9
R8
R7
R6
R5
R4
R3
R2
R1
R0
传给do_data_abort()函数的值就是指向sp_frame的指针void do_data_abort (struct pt_regs *pt_regs)
{
printf ("data abort\n");
show_regs (pt_regs);
bad_mode ();
}
struct pt_regs {
long uregs[18];
};#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
#define ARM_sp uregs[13]
#define ARM_ip uregs[12]
#define ARM_fp uregs[11]
#define ARM_r10 uregs[10]
#define ARM_r9 uregs[9]
#define ARM_r8 uregs[8]
#define ARM_r7 uregs[7]
#define ARM_r6 uregs[6]
#define ARM_r5 uregs[5]
#define ARM_r4 uregs[4]
#define ARM_r3 uregs[3]
#define ARM_r2 uregs[2]
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
pt_regs就是sp_framedo_data_abort()就不分析了,把这些寄存器都显示出来。
通过这些分析,可以知道这就是发生异常时的所有寄存器现场,但是pc要减去8才是异常指令的地址
随机文章:
各种手机模拟调试器与 Bluetooth 串口适配器的连接 2009-05-05Device Emulator 中CS8900A MAC 地址的端倪 2009-01-08教哥哥用电脑 2007-08-27观察能力的培养 2006-01-09motor control 2005-09-02
收藏到:Del.icio.us







