ARM处理器是当前嵌入式领域使用最多的处理器,我们在使用中一定注意处理器的工作模式,下面对ARM处理的工作模式进行描述 一、ARM体系的CPU有以下7种工作模式: 1、用户模式(Usr):用于正常执行程序; 2、快速中断模式(FIQ):用于高速数据传输; 3、外部中断模式(IRQ):用于通常的中断处理; 4、管理模式(svc):操作系统使用的保护模式; 5、数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储以及存储保护; 6、系统模式(sys):运行具有特权的操作系统任务; 7、未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件; 二、Arm的工作模式切换有两种方法: 被动切换:在arm运行的时候产生一些异常或者中断来自动进行模式切换 主动切换:通过软件改变,即软件设置寄存器来经行arm的模式切换,应为arm的工作模式都是可以通过相应寄存器的赋值来切换的。 Tips:当处理器运行在用户模式下,某些被保护的系统资源是不能被访问的。 除用户模式外,其余6种工作模式都属于特权模式; 特权模式中除了系统模式以外的其余5种模式称为异常模式; 大多数程序运行于用户模式; 进入特权模式是为了处理中断、异常、或者访问被保护的系统资源; 三、模式切换 当异常发生,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都是工作在此模式。 四、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的用户模式。
|