FROM:https://blog.csdn.net/xichangbao/article/details/51484629
1. arm异常模式。
#define FUNCTION(x) .global x; x:
FUNCTION(arm_undefined) // 未定义指令异常
stmfd sp!, { r0-r12, r14 } // 批量数据存储指令,用于将r0-r12及r14压入堆栈,stmfd指令的寻址方式为事前递减方式(DB),后缀“!”表示更新sp的值,即sp = sp - 14*4
sub sp, sp, #12 // sp = sp - 12
mov r0, sp
mrs r1, spsr // spsr保存的用户模式的cpsr
stmia r0, { r1, r13-r14 }^ // 将spsr,sp,lr入栈,后缀“^”表示sp,lr是用户模式的寄存器
b arm_undefined_handler
b .
FUNCTION(arm_syscall) // 系统调用模式
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_syscall_handler
b .
FUNCTION(arm_prefetch_abort) // 预取指令异常模式
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_prefetch_abort_handler
b .
FUNCTION(arm_data_abort) // 数据访问终止模式
stmfd sp!, { r0-r12, r14 }
sub sp, sp, #12
mov r0, sp
mrs r1, spsr
stmia r0, { r1, r13-r14 }^
b arm_data_abort_handler
b .
FUNCTION(arm_reserved)
b .
FUNCTION(arm_irq) // 普通中断模式
/* XXX only deals with interrupting supervisor mode */
/* save r4-r6 and use as a temporary place to save while we switch into supervisor mode */
stmia r13, { r4-r6 } // r4-r6入栈,使用用户模式的堆栈
mov r4, r13
sub r5, lr, #4
mrs r6, spsr
/* move into supervisor mode. irq/fiq disabled */
msr cpsr_c, #(3<<6 | 0x13) // 切换到超级用户模式,同时关闭中断
/* save the return address */
stmfd sp!, { r5 } // // platform_irq的参数frame中的pc,入栈返回地址:lr - 4
/* save C trashed regs, supervisor lr */
stmfd sp!, { r0-r3, r12, lr } // platform_irq的参数frame中的r0, r1, r2, r3, r12, lr
/* save spsr */
stmfd sp!, { r6 } // platform_irq的参数frame中的spsr
/* restore r4-r6 */
ldmia r4, { r4-r6 } // r4-r6出栈,使用用户模式的堆栈
/* increment the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
add r0, r0, #1
str r0, [r1] // 以上四句指令critical_section_count = critical_section_count + 1
/* call into higher level code */
mov r0, sp /* iframe */ // platform_irq的参数struct arm_iframe *frame
bl platform_irq
/* reschedule if the handler returns nonzero */
cmp r0, #0 // 比较platform_irq返回值是否为0
blne thread_preempt 不为0跳转到thread_preempt,进行线程抢占
/* decrement the global critical section count */
ldr r1, =critical_section_count
ldr r0, [r1]
sub r0, r0, #1
str r0, [r1] // 以上四句指令critical_section_count = critical_section_count - 1
/* restore spsr */
ldmfd sp!, { r0 }
msr spsr_cxsf, r0 // 恢复spsr
/* restore back to where we came from */
ldmfd sp!, { r0-r3, r12, lr, pc }^ // 出栈,返回到pc处进执行
.bss
.align 2
.global irq_save_spot
irq_save_spot:
.word 0 /* r4 */
.word 0 /* r5 */
.word 0 /* r6 */
.text
FUNCTION(arm_fiq) // 快速中断模式
sub lr, lr, #4 // 修正快速中断的返回地址
stmfd sp!, { r0-r3, r12, lr } // 入栈
bl platform_fiq
ldmfd sp!, { r0-r3, r12, pc }^ // 出栈,后缀“^”,同时将spsr复制到cpsr
.ltorg
未定义指令模式。
void arm_undefined_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "undefined abort, halting\n");
}
系统调用模式。
void arm_syscall_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "unhandled syscall, halting\n");
}
预取指令异常模式。
void arm_prefetch_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -4, "prefetch abort, halting\n");
}
数据访问终止模式。
void arm_data_abort_handler(struct arm_fault_frame *frame)
{
exception_die(frame, -8, "data abort, halting\n");
}
普通中断模式。
struct arm_iframe {
uint32_t spsr;
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr;
uint32_t pc;
};
enum handler_return platform_irq(struct arm_iframe *frame)
{
#if TARGET_USES_GIC_VIC
if(target_supports_qgic())
return gic_platform_irq(frame);
else
return vic_platform_irq(frame);
#else
return gic_platform_irq(frame);
#endif
}
/* IRQ handler */
enum handler_return gic_platform_irq(struct arm_iframe *frame)
{
uint32_t num;
enum handler_return ret;
/* Read the interrupt number to be served*/
num = qgic_read_iar(); // 获取中断号
if (num >= NR_IRQS)
return 0;
ret = handler[num].func(handler[num].arg); // 根据中断号,执行相应中断处理函数
/* End of interrupt */
qgic_write_eoi(num); // 通知cpu中断已处理
return ret;
}
快速中断模式。
void platform_fiq(struct arm_iframe *frame)
{
#if TARGET_USES_GIC_VIC
if(target_supports_qgic())
gic_platform_fiq(frame);
else
vic_platform_fiq(frame);
#else
gic_platform_fiq(frame);
#endif
}
/* FIQ handler */
void gic_platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
#define PANIC_UNIMPLEMENTED panic("%s unimplemented\n", __PRETTY_FUNCTION__) // lk中不支持快速中断模式
exception_die()。
static void exception_die(struct arm_fault_frame *frame, int pc_off, const char *msg) // 注意第二个参数,不同的异常模式的返回地址不同
{
inc_critical_section(); // 禁掉中断
frame->pc += pc_off; // 计算正确的返回地址,frame->pc对应入栈的lr
dprintf(CRITICAL, msg);
dump_fault_frame(frame); // 打印帧信息
halt(); // 挂起
for(;;); // 死循环
}
dump_fault_frame()。
struct arm_fault_frame {
uint32_t spsr;
uint32_t usp;
uint32_t ulr;
uint32_t r[13];
uint32_t pc;
};
struct arm_mode_regs {
uint32_t fiq_r13, fiq_r14;
uint32_t irq_r13, irq_r14;
uint32_t svc_r13, svc_r14;
uint32_t abt_r13, abt_r14;
uint32_t und_r13, und_r14;
uint32_t sys_r13, sys_r14;
};
void dump_fault_frame(struct arm_fault_frame *frame)
{
// 打印堆栈中的寄存器信息,其中pc值已修正
dprintf(CRITICAL, "r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n", frame->r[0], frame->r[1], frame->r[2], frame->r[3]);
dprintf(CRITICAL, "r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", frame->r[4], frame->r[5], frame->r[6], frame->r[7]);
dprintf(CRITICAL, "r8 0x%08x r9 0x%08x r10 0x%08x r11 0x%08x\n", frame->r[8], frame->r[9], frame->r[10], frame->r[11]);
dprintf(CRITICAL, "r12 0x%08x usp 0x%08x ulr 0x%08x pc 0x%08x\n", frame->r[12], frame->usp, frame->ulr, frame->pc);
dprintf(CRITICAL, "spsr 0x%08x\n", frame->spsr);
struct arm_mode_regs regs;
arm_save_mode_regs(®s);
// 打印异常模式的寄存器值
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_FIQ) ? '*' : ' ', "fiq", regs.fiq_r13, regs.fiq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_IRQ) ? '*' : ' ', "irq", regs.irq_r13, regs.irq_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SVC) ? '*' : ' ', "svc", regs.svc_r13, regs.svc_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_UND) ? '*' : ' ', "und", regs.und_r13, regs.und_r14);
dprintf(CRITICAL, "%c%s r13 0x%08x r14 0x%08x\n", ((frame->spsr & MODE_MASK) == MODE_SYS) ? '*' : ' ', "sys", regs.sys_r13, regs.sys_r14);
// dump the bottom of the current stack
addr_t stack;
switch (frame->spsr & MODE_MASK) {
case MODE_FIQ: stack = regs.fiq_r13; break;
case MODE_IRQ: stack = regs.irq_r13; break;
case MODE_SVC: stack = regs.svc_r13; break;
case MODE_UND: stack = regs.und_r13; break;
case MODE_SYS: stack = regs.sys_r13; break;
default:
stack = 0;
}
if (stack != 0) {
dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
hexdump((void *)stack, 128); // 打印异常模式的堆栈内容
}
}
---------------------
作者:xichangbao
来源:CSDN
原文:https://blog.csdn.net/xichangbao/article/details/51484629
版权声明:本文为博主原创文章,转载请附上博文链接!