54.ARM 异常处理
一.什么异常?
异常我们可以笼统的理解为中断,它的范围更宽泛一点,复位啊,外部中断啊,都属于异常。都是向cpu请求打断正常的程序流程,进入特定程序的一种机制。
二. ARM中的7种异常种类
优先级 |
异常 |
异常模式 |
描述 |
用途 |
1(最高) |
复位异常(reset) |
SVC(特权模式) |
复位电平有效时,产生复位异常,程序跳转到复位处理程序处执行 |
进行操作系统高级处理 |
2 |
数据中止异常(data abort) |
Abort(数据访问中止模式) |
处理器数据访问指令的地址不存在,或该地址不允许当前指令访问时产生数据中止异常 |
虚存和存储器保护 |
3 |
快速中断异常(FIQ) |
FIQ(快速中断模式) |
快速中断请求引脚有效,且CPSR中的F位为0时,产生FIQ异常 |
快速中断请求处理 |
4 |
外部中断异常(IRQ) |
IRQ(外部中断模式) |
外部中断请求有效,且CPSR中的I位为0时,产生IRQ异常 |
外部中断请求处理 |
5 |
预取指令中止异常(prefetch abort) |
Abort(数据访问中止模式) |
处理器预取指令的地址不存在,或该地址不允许当前指令访问,产生指令预取中止异常 |
虚存和存储器保护 |
6 |
软中断异常 (swi) |
SVC(特权模式) |
执行SWI指令产生,用于用户模式下的程序调用特权操作指令 |
操作系统高级处理 |
7(最低) |
未定义指令异常 (undefined interrupt) |
Undefined(未定义指令终止模式) |
遇到不能处理的指令时,产生未定义指令异常 |
软件模拟硬件协处理器 |
注:每一种异常都会导致内核进入一种特定的模式,用户模式和系统模式下,不可以通过异常进入,只能通过编程改变CPSR来进入。(用户模式下不能读写cpsr,只能通过异常回到其他模式)
三. 异常和向量表地址,返回地址
存储器映射地址0x00000000是为向量表(32位字节)保留的(有的处理器向量表选择在存储空间的高地址0xffff0000开始)
有的支持通过设置CP15的C12寄存器将向量表首地址设置到任意地址。
向量表地址 |
异常 |
返回地址 |
说明 |
0x00000000 |
复位异常(reset) |
-- |
复位没有定义LR |
0x00000004 |
未定义指令异常 (undefined interrupt) |
LR |
LR指向未定义指令的下一条指令 |
0x00000008 |
软中断异常 (swi) |
LR |
LR指向SWI指令的下一条指令 |
0x0000000C |
预取指令中止异常(prefetch abort) |
LR-4 |
LR指向导致预取指令异常的那条指令 |
0x00000010 |
数据中止异常(data abort) |
LR-8 |
LR指向导致数据中止异常的指令 |
0x00000018 |
外部中断异常(IRQ) |
LR-4 |
LR指向发生异常时正在执行的指令 |
0x0000001C |
快速中断异常(FIQ) |
LR-4 |
LR指向发生异常时正在执行的指令 |
注:
- 异常是随机产生的,当异常发生时,处理器会把PC设置为一个特定的存储器地址,这一地址放在被称为向量表的特定地址范围内。(向量表的入口是一些跳转指令,跳转到专门处理某个异常或中断的子程序)
- 每一个异常发生时总是从异常向量表开始跳转,最简单快速的方法是向量表中的每一条指令直接跳到对应的异常处理函数,快速中断处理函数就可以直接从地址0x1C开始,省下一条跳转指令。
四.SWI 软中断
软中断是利用硬件中断的概念,用软件方式进行模拟,实现从用户模式切换到特权模式并执行特权程序的机制。
硬件中断是由电平的物理特性决定,在电平变化时引发中断操作,而软中断是通过一条具体指令SWI,引发中断操作,也就是说用户程序里可以通过写入SWI指令来切换到特权模式,当CPU执行到SWI指令时会从用户模式切换到管理模式下,执行软件中断处理。由于SWI指令由操作系统提供的API封装起来,并且软件中断处理程序也是操作系统编写者提前写好的,因此用户程序调用API时就是将操作权限交给了操作系统,所以用户程序还是不能随意访问硬件。
先来了解下SWI指令。
SWI指令编码中immed_24为24位任意有效立即数(范围0~2^24-1),当该指令被执行时系统产生软中断异常,切换到管理模式下。用户程序切换到管理模式下后,进入到软中断处理程序,通常软中断异常处理程序都是系统开发人员提前写好的,SWI切换到了特权模式,执行的是系统开发人员写好的异常处理程序
SWI指令后面的24立即数是干什么用的呢?用户程序通过SWI指令切换到特权模式,进入软中断处理程序,但是软中断处理程序不知道用户程序到底想要做什么?SWI指令后面的24位用来做用户程序和软中断处理程序之间的接头暗号。通过该软中断立即数来区分用户不同操作,执行不同内核函数。如果用户程序调用系统调用时传递参数,根据ATPCSC语言与汇编混合编程规则将参数放入R0~R4即可。
五.SWI 在系统调用中的应用
1.Unix系统通过向内核发出系统调用(system call)实现了用户态进程和硬件设备之间的大部分接口。系统调用是操作系统提供的服务,用户程序通过各种系统调用,来引用内核提供的各种服务,系统调用的执行让用户程序陷入内核,该陷入动作由swi软中断完成。
2. ARM Linux 系统利用SWI指令来从用户空间进入内核空间。SWI指令用于产生软件中断,从而实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR,执行转移到SWI向量。在其他模式下也可使用SWI指令,处理器同样地切换到管理模式。
六.SWI 异常处理过程
直接看下面的实例代码: