ARM处理器有7种工作模式 :
USR 模式
正常用户模式,程序正常执行模式
FIQ 模式(Fast Interrupt Request)
处理快速中断,支持高速数据传送或通道处理
IRQ 模式
处理普通中断
SVC 模式(Supervisor)
操作系统保护模式,处理软件中断swi reset
ABT 中止(Abort mode){数据、指令}
处理存储器故障、实现虚拟存储器和存储器保护
UND 未定义(Undefined)
处理未定义的指令陷阱,支持硬件协处理器的软件仿真
SYS 系统模式(基本上=USR)(System)
运行特权操作系统任务
这7种模式,除了用户模式之外的其他6种处理器模式称为特权模式
特权模式下,程序可以访问所有的系统资源,也可以任意地进行处理器模式的切换。
特权模式中,除系统模式外,其他5种模式又称为异常模式。
下面就来讨论一下发生异常时,linux的处理过程
首先引入中断异常向量表。
中断异常向量表就是一张函数表格,里面放置了一组函数,存放在一个固定位置,当发生异常时,处理器被强制从这个位置取出
函数执行。
中断异常向量表在启动之前存在于地址0x00000000,这是uboot的中断异常向量表,
u-boot\arch\arm\cpu\arm920t\start.S 40行
.globl _start
_start: b start_code // 0x00
ldr pc, _undefined_instruction // 0x04 未定义指令异常
ldr pc, _software_interrupt // 0x08 软件中断异常
ldr pc, _prefetch_abort // 0x0c 指令预取中止异常
ldr pc, _data_abort // 0x10 数据访问中止异常
ldr pc, _not_used // 0x14 保留
ldr pc, _irq // 0x18 外部中断请求异常
ldr pc, _fiq // 0x1c 快速中断请求异常
所以刚开始中断向量表的地址是0x00~0x1c
0x00地址放的跳转指令就是跳转到执行uboot的引导启动代码
在引导了kernel后,中断异常向量表会存在于地址0xffff0000,追踪代码如下:
start_kernel
setup_arch(&command_line);
early_trap_init();
#if defined(CONFIG_CPU_USE_DOMAINS)
unsigned long vectors = CONFIG_VECTORS_BASE;
#else
unsigned long vectors = (unsigned long)vectors_page;
#endif
...
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); //这三条指令就是搬移中断异常向量表指令
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
为什么会被拷到0xffff0000?
从上面的代码看CONFIG_CPU_USE_DOMAINS有没有被设置,我们去内核目录的.config文件查看,它被设置了,所以
vectors = CONFIG_VECTORS_BASE,而在.config文件中CONFIG_VECTORS_BASE=0xffff0000
中断异常向量表被拷贝到0xffff0000地址,中断异常处理函数也拷贝到0xffff0000 + 0x200的地址上去
考察汇编的时候到了,被虐的体无完肤啊,建议看之前恶补一下
在哪里拷贝呢?
从上面的代码看出,异常向量表从__vectors_start拷贝,中断异常处理函数从__stubs_start拷贝,这段代代码在
linux-3.3\arch\arm\kernel\entry-armv.S 1132行
__vectors_start:
ARM( swi SYS_ERROR0 )
THUMB( svc #0 ) // 0x00
THUMB( nop ) // 0x02
W(b) vector_und + stubs_offset // 0x04
W(ldr) pc, .LCvswi + stubs_offset // 0x08
W(b) vector_pabt + stubs_offset // 0x0c
W(b) vector_dabt + stubs_offset // 0x10
W(b) vector_addrexcptn + stubs_offset // 0x14
W(b) vector_irq + stubs_offset // 0x18
W(b) vector_fiq + stubs_offset // 0x1c
.globl __vectors_end
__vectors_end:
以上是介绍了异常向量表,当发生异常的时候,处理器会跳转到到这些地方来执行,不同的异常对应不同的入口地址。发生具体的异常会怎么处理,请见下面的博文
阅读(402) | 评论(0) | 转发(0) |