1、用户模式(Usr):用于正常执行程序;
2、快速中断模式(FIQ):用于高速数据传输;
3、外部中断模式(IRQ):用于通常的中断处理;
4、管理模式(svc):操作系统使用的保护模式;
5、数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储以及存储保护;
6、系统模式(sys):运行具有特权的操作系统任务;
7、未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件;
Arm的工作模式切换有两种方法:
被动切换:在arm运行的时候产生一些异常或者中断来自动进行模式切换
主动切换:通过软件改变,即软件设置寄存器来经行arm的模式切换,应为arm的工作模式都是可以通过相应寄存器的赋值来切换的。
tips:当处理器运行在用户模式下,某些被保护的系统资源是不能被访问的。
除用户模式外,其余6种工作模式都属于特权模式;
特权模式中除了系统模式以外的其余5种模式称为异常模式;
大多数程序运行于用户模式;
进入特权模式是为了处理中断、异常、或者访问被保护的系统资源;
四、寄存器
ARM有31个通用的32位寄存器,6个程序状态寄存器,共分为7组,有些寄存器是所有工作模式共用的,还有一些寄存器专属于每一种工作模式;
R13——栈指针寄存器,用于保存堆栈指针;
R14——程序连接寄存器,当执行BL子程序调用指令时,R14中得到R15的备份,而当发生中断或异常时,R14保存R15的返回值;
R15——程序计数器;
快速中断模式有7个备份寄存器R8—R14,这使得进入快速中断模式执行很大部分程序时,甚至不需要保存任何寄存器;
其它特权模式都含有两个独立的寄存器副本R13、R14,这样可以令每个模式都拥有自己的堆栈指针和连接寄存器;
五、当前程序状态寄存器(CPSR)
CPSR中各位意义如下:
T位:1——CPU处于Thumb状态, 0——CPU处于ARM状态;
I、F(中断禁止位): 1——禁止中断, 0——中断使能;
工作模式位:可以改变这些位,进行模式切换;
六、程序状态保存寄存器(SPSR)
当切换进入某一个特权模式时,SPSR保存前一个工作模式的CPSR值,这样,当返回前一个工作模式时,可以将SPSR的值恢复到CPSR中;
Linux用户态程序运行在FIQ,Linux内核运行在Supervisor模式
七、模式切换
当异常发生,CPU进入相应的异常模式时,以下工作是由CPU自动完成的:
1、在异常模式的R14中保存前一工作模式的下一条即将执行的指令地址;
2、将CPSR的值复制到异常模式的SPSR中;
3、将CPSR的工作模式设为该异常模式对应的工作模式;
4、令PC值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令;
从异常工作模式退回到之前的工作模式时,需要由软件来完成以下工作:
1、将异常模式的R14减去一个适当的值(4或8)后赋给PC寄存器;
2、将异常模式SPSR的值赋给CPSR;
早期的ARM核有状态(ARM或Thumb)切换(通过BX等指令修改CPSR寄存器(当前程序状态寄存器,存放条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息)中T的控制位完成程序状态的切换),现在ARM都只使用Thumb状态了。所以,我们不在讨论状态切换相关。
一、ARM七种工作模式及其应用场合(Linux操作系统使用了其中USR和SVC模式、出现异常时还可能通过进入其他模式转为Linux内核态)
在CPSR寄存器中设置M[4:0]位,分别对应如下七种模式(注意:用户模式和系统模式只有对CPSR的读权限,因此、这两种模式下不可以通过直接设置CPSR进入其他模式(SWI汇编指令除外)):
1.用户模式(USR):用于正常执行程序。在Linux操作系统中,用户空间进程就是在这种模式下运行。CPSR寄存器M[4:0]设置10000。
2.系统模式(SYS):运行有特权的操作系统任务。CPSR寄存器M[4:0]设置11011。
这个模式和用户模式共用R15-pc(程序计数器,存放下一条指令所在单元的地址)的值,因此不用ARM强制赋值。
ARM进入以下几种模式后,都需要给R15-PC寄存器重新赋值、也就是开始执行新的指令。
3.管理模式(SVC):操作系统使用的保护模式(高权限)。在Linux操作系统中,内核空间在这种模式下运行。CPSR寄存器M[4:0]设置10011。
当ARM刚上电或复位时、进入该模式,并强制PC从0x0000 0000处取指令;当系统软中断(如系统调用,调用ARM的SWI汇编指令)时、进入该模式,并强制PC从0x0000 0008处取指令——这也是ARM从用户模式主动切入管理模式(Linux从用户态主动进入内核态)的唯一方法。
当出现异常状况时,Linux还有可能在如下几种ARM模式下运行;如硬件中断、程序问题导致的异常等。
4.快速中断模式(FIQ):用于高速数据传输。CPSR寄存器M[4:0]设置10001。
进入该模式后、ARM强制PC从0x0000 001C处取指令。
5.外部中断模式(IRQ):用于通常的中断处理。CPSR寄存器M[4:0]设置10010。
进入该模式后、ARM强制PC从0x0000 0018处取指令。
6.数据访问终止模式(ABT):当数据或指令预取终止时进入该模式,可用于虚拟内存及存储保护。CPSR寄存器M[4:0]设置10111。
当指令取终止时、进入该模式,并强制PC从0x0000 000C处取指令;当数据取终止时、进入该模式;并强制PC从0x0000 0010处取指令。
7.未定义指令终止模式(UND):当未定义的指令执行时进入该模式,可用于支持硬件。CPSR寄存器M[4:0]设置11111。
当程序中出现未定义的指令时、进入该模式,并强制PC从0x0000 0004处取指令。
在非user模式下的其他6中模式,有SVC,FIQ,IRQ,ABT,UND,SYS 都可以修改CPSR寄存器、从而控制ARM工作模式的切换。
在Linux操作系统中;当CPU处于特权模式(Linux处于内核态)时,可以随意进入用户态。而当CPU处于用户模式(Linux处于用户态)时,Linux从用户态切换到内核态(ARM从用户模式切换到其他特权模式)只有在系统调用和中断(中断进入IRQ模式,也可以操作内核)两种情况下发生,一般程序一开始都是运行于用户态,当程序需要使用系统资源时,就必须通过调用软中断进入内核态。
每一种工作模式的R13-SP(堆栈指针寄存器,在堆栈操作中使用)都是独立的。因此,对程序中需要用到的每一种模式都要给SP定义一个堆栈地址。方法是改变状态寄存器(CPSR)内的状态位,使处理器切换到不同的状态,然后给SP赋值。注意:不要切换到User模式进行User模式的堆栈设置,因为进入User模式后就不能再操作CPSR回到别的模式了,可能会对接下去的程序执行造成影响。
ARM在刚上电或复位后、进入SVC管理模式,并从0x0000 0000开始取指令;bootloader和Linux Kernel都是工作在此模式。
八、ARM工作模式切换的两种方法
1.被动切换:是指ARM在当前工作模式下,没有要求模式切换、而被动地进入另外一种模式。在ARM运行的时候产生一些异常(包括软中断)或者中断(硬中断)来进行模式切换。如上边提到的Linux操作系统从用户态到内核态,如硬件中断或程序异常。内核态不会被动切换到用户态。
2.主动切换:是指ARM在当前工作模式下,通过一些自主操作、主动的要求切换工作模式。ARM通过软件改变,即软件设置寄存器来进行ARM的模式切换,因为ARM的工作模式都是可以通过相应寄存器的赋值来切换的。如上边提到的Linux操作系统从内核态到用户态;这里边有一个比较特殊的情况:Linux用户态可以通过系统调用主要要求切换到内核态。
九、linux操作系统与ARM工作模式
首先,arm开发板在刚上电或者复位后,都会首先进入SVC即管理模式,此时、程序计数器R15-PC会被自动赋值为0x0000 0000,bootloader就是在该模式下,位于0x0000 0000 的NOR FLASH或SRAM中装载的,因此,开机或重启后bootloader会被首先执行。
接着,bootloader引导linux内核,此时,linux内核仍然运行在SVC即管理模式下,当内核启动完毕后,进入用户态init进程时,内核将ARM的当前程序状态CPSR寄存器M[4:0]设置为10000,进而用户态程序只能运行在ARM的用户模式。
由于ARM用户模式下对资源的访问时受限制的,因此,用户态可以实现对linux操作系统内核保护的目的。
需要强调的是:Linux内核态是从ARM的SVC即管理模式下启动的,但在某些情况下、如:硬件中断、程序异常(被动)等情况下进入ARM的其他特权模式,这时仍然可以进入内核态(因为就是可以操作内核了);同样,Linux用户态是从ARM用户模式启动的,但当进入ARM系统模式时、仍然可以操作Linux用户态程序(进入用户态,如init进程的启动过程)。
即:Linux内核从ARM的SVC模式下启动,但内核态不仅仅指ARM的SVC模式(还包括可以访问内核空间的所有ARM模式);Linux用户程序从ARM的用户模式启动,但用户态不仅仅指ARM的用户模式。