Linux 学习笔记 (二) —— Cortex -A 架构 、寄存器组与运行模式
Linux学习笔记
version : v1.0 「2022.7.28」 最后补充
author: Y.Z.T.
简介: Linux学习笔记 , 写的比较乱 , 属于随记
3️⃣ Cortex -A 架构
3.1
ARM指令集分两种, Thumb指令集,ARM指令集
ARM
指令长度为32位,Thumb
指令长度为16位。- 这种特点使得ARM既能执行16位指令,又能执行32位指令,从而增强了ARM内核的功能
3.1.0 ARM三级流水线技术
ARM7处理器核使用了典型三级流水线的冯诺伊曼结构
三级流水线技术
流水线使用三个阶段,因此指令分为三个阶段执行:
- 取指(从存储器装载一条指令)
- 译码(识别将要被执行的指令)
- 执行(处理指令并将结果写回寄存器)
为什么发送中断时 , 保存的pc
地址是 ( PC - 4 )
R15(PC)
寄存器 总是指向 “正在取指” 的指令,而不是指向 “正在执行” 的指令或正在“译码”的指令。- 一般来说,人们习惯性约定将 “ 正在执行 的指令作为参考点” ,称之为当前第一条指令,因此 PC总是指向第三条指令 。
- 当ARM状态时,每条指令为 4字节 长,所以
PC
始终指向该指令地址 加8字节 的地址,即: PC值=当前程序执行位置 + 8 - PC指向的是正在取指的地址(下一条指令) ,那么cpu正在 译指的指令地址是
PC-4
, 即PC
所 指向的地址 和现在所 执行的指令地址 相差8 - 所以 当突然发生中断的时候,保存的是PC的地址
PC-8+4 = PC-4
(下一条指令的地址)
3.1.1 九种运行模式
除了 User(USR)用户模式以外,其它 8 种运行模式都是 特权模式 。
特权模式具有以下权利:
- MRS(把状态寄存器的内容放到通用寄存器);
- MSR(把通用寄存器的内容放到状态寄存器中)。
由于状态寄存器中的内容不能够改变,因此,要先把内容复制到通用寄存器中,然后修改通用寄存
器中的内容,再把通用寄存器中的内容复制给状态寄存器中,即可完成“修改状态寄存器”的任务。
这几个运行模式可以通过软件进行任意切换,也可以通过中断或者异常来进行切换。(这几个模式除去 系统模式(SYS) 外 , 统称异常模式)
大多数的程序都运行在 用户模式 ,用户模式下是不能访问系统所有资源的,用户模式下需要借助 异常 来完成模式切换
3.1.1.1用户模式(USER)
- 用户模式是用户程序的工作模式,它运行在操作系统的用户态,它没有权限去操作其它硬件资源,
- 用户模式只能执行处理自己的数据,也不能切换到其它模式下,要想访问硬件资源或切换到其它模式只能通过软中断或产生异常。
3.1.1.2 系统模式(SYS)
- 系统模式是特权模式,不受用户模式的限制。
- 用户模式和系统模式共用一套寄存器,操作系统在该模式下可以方便的访问用户模式的寄存器,
- 而且操作系统的一些特权任务可以使用这个模式访问一些受控的资源。
说明:用户模式与系统模式两者使用相同的寄存器,都没有
SPSR
(Saved ProgramStatement Register,已保存程序状态寄存器),但系统模式比用户模式有更高的权限,可
以访问所有系统资源。
3.1.1.3 一般中断模式(IRQ)
一般中断模式也叫 普通中断模式,用于处理一般的中断请求,通常在硬件产生中断信号之后自动进入该模式,该模式为特权模式,可以自由访问系统硬件资源。
3.1.1.4 快速中断模式(FIQ)
- 快速中断模式是相对一般中断模式而言的,它是用来处理对时间要求比较紧急的中断请求,主要用于高速数据传输及通道处中。
- 快中断有许多 (R8~R14)自己的专用寄存器 ,发生中断时,使用自己的寄存器就避免了保存和恢复某些寄存器。
- 如果异常中断处理程序中使用它自己的物理寄存器之外的其他寄存器,异常中断处理程序必须 保存和恢复 这些寄存器
3.1.1.5 管理模式(SVS)
管理模式是 CPU上电后默认模式 ,因此,在该模式下主要用来做 系统的初始化 ,
软中断处理也在该模式下。当用户模式下的用户程序请求使用硬件资源时,通过软件中断进入该模式。
说明: 系统复位或开机、软中断时进入到SVC模式下。
3.1.1.6 终止模式(ABT)
终止模式用于支持虚拟内存或存储器保护,当用户程序访问非法地址,没有权限读取的内存地址时,会进入该模式,linux下编程时经常出现的segment fault
通常都是在该模式下抛出返回的。
3.1.1.7 未定义模式(UND)
未定义模式用于支持硬件协处理器的软件仿真,CPU在指令的译码阶段不能识别该指令操作时,会进入未定义模式。
3.1.2 ARM寄存器组
ARM处理器共有37个寄存器。它包含31个通用寄存器和6个状态寄存器。
- 34 个通用寄存器,包括
R15
程序计数器(PC),这些寄存器都是 32 位 的。- 8 个 状态寄存器,包括
CPSR
和SPSR
。Hyp
模式下独有一个ELR_Hyp
寄存器。
Contex -A 寄存器组
低等寄存器 (R0-R7)
在所有运行模式下,未分组寄存器都指向同一个物理寄存器,他们未被系统用作特殊的用途。
因此在中断或异常处理进行异常模式转换时,由于不同的处理器运行模式均使用相同的物理寄存器,所
以可能造成寄存器中数据的破坏。
高等寄存器 (R8 -R14)
高等寄存器 , 每次所访问的物理寄存器都与当前的处理器运行模式相关。
R13
常用作存放 堆栈指针 ,用户也可以使用其他寄存器存放堆栈指针,但在Thumb
指令集下,某些指令强制要求使用R13
存放堆栈指针。
R14
称为链接寄存器(LR,Link Register)
,当执行子程序时,R14
可得到R15(PC)
的备份,执行完子程序后,又将
R14
的值复制回PC
,即使用R14
保存返回地址。例 : 将
R14(LR)
中的值赋给R15(PC)
即可完成子函数返回
1 MOV PC, LR ;寄存器 LR 中的值赋值给 PC,实现跳转或者以在子函数的入口出将 LR 入栈
1
2
3
4 PUSH {LR} ;将 LR 寄存器压栈
;在子函数最后出栈即可
POP {PC} ;@将上面压栈的 LR 寄存器数据出栈给 PC 寄存器,严格意义上来讲应该是将@LR-4 赋给 PC(因为是3级流水线)
寄存器
R15
用作程序计数器(PC),在ARM
状态下,位[1:0]为0,位[31:2]用于保存PC;在Thumb
状态下,位[0]为0,位[31:1]用于保存PC。
各个模式的寄存器
浅色字体的是与 User 模式所 共有 的寄存器,蓝绿色背景的是各个模式所 独有 的寄存器。
在所有的模式中,低寄存器组 (R0~R7) 是共享同一组物理寄存器的 , 一些高寄存器组在不同的模式有自己独有的寄存器,比如
FIQ
模式下R8~R14
是独立的物理寄存器。
- 假如某个程序在
FIQ
模式下访问R13
寄存器,那它实际访问的是寄存器R13_fiq
,- 如果程序处于
SVC
模式下访问R13
寄存器,那它实际访问的是寄存器R13_svc
。
程序状态寄存器 ( CPSR)
- 除了
User
和Sys
这两个模式 , 其他7个模式都配备 一个备份程序状态寄存器 (SPSR
)- 当特定异常中断发生时,
SPSR
寄存器用来保存当前程序状态寄存器(CPSR
)的值,当异常退出以后可以用 SPSR 中保存的值来恢复CPSR
CPSR 寄存器结构如图所示:
N(bit31):当两个补码表示的 有符号整数运算的时候,
N=1
表示运算对的结果为 负数 ,N=0
表示结果为 正数Z(bit30) :
Z=1
表示运算结果为 零 ,Z=0
表示运算结果 不为零 ,对于CMP
指令,Z=1
表示进行比较的两个数 大小相等C(bit29):
- 在加法指令中,当结果产生了 进位 ,则
C=1
,表示无符号数运算发生上溢,其它情况下C=0
。- 在减法指令中,当运算中发生 借位 ,则
C=0
,表示无符号数运算发生下溢,其它情况下 C=1。- 对于包含 移位操作 的非加/减法运算指令,C 中包含最后一次溢出的位的数值,对于其它非加/减运算指令,C 位的值通常不受影响。
V(bit28) : 对于加/减法运算指令,当操作数和运算结果表示为二进制的补码表示的带符号数时,
V=1
表示 符号位溢出 ,通常其他位不影响 V 位。Q(bit27) : 仅
ARM v5TE_J
架构支持,表示饱和状态,Q=1
表示累积饱和,Q=0
表示累积不饱和IT[1:0] (bit26:25) : 和
IT[7:2](bit15:bit10)
一起组成IT[7:0]
,作为IF-THEN
指令执行状态。J(bit24) : 仅
ARM_v5TE-J
架构支持,J=1
表示处于Jazelle
状态,此位通常和T(bit5)
位一起表示当前所使用的指令集如下所示 :
GE[3:0] (bit19:16):
SIMD
指令有效,大于或等于。IT[7:2] (bit15:10) : 参考
IT[1:0]
E(bit9) : 大小端控制位,
E=1
表示 大端模式 ,E=0
表示 小端模式A(bit8) : 禁止异步中断位,
A=1
表示禁止异步中断。I(bit7) :
I=1
禁止 IRQ,I=0
使能 IRQF(bit6) :
F=1
禁止 FIQ,F=0
使能 FIQT(bit5) : 控制指令执行状态,表明本指令是
ARM
指令还是Thumb
指令,通常和J(bit24)
一起表明指令类型,参考J(bit24)
位。M[4:0] : 处理器模式控制位
具体模式如下所示 :
3.1.3 中断系统
中断向量表
Cortex-A
内核CPU
的所有外部中断 属于IRQ
中断 , 当任意一个外部中断发生的时候都会触发 IRQ 中断
中断类型介绍:
- 复位中断
(Rest)
,CPU
复位以后就会进入复位中断,我们可以在复位中断服务函数里面做一些初始化工作,比如初始化SP
指针DDR
等等。 - 未定义指令中断
(Undefined Instruction)
,如果指令不能识别的话就会产生此中断 - 软中断
(Software Interrupt,SWI)
,由SWI
指令引起的中断,Linux
的系统调用会用SWI
指令来引起软中断,通过软中断来陷入到内核空间。 - 指令预取中止中断
(Prefetch Abort)
,预取指令的出错的时候会产生此中断 - 数据访问中止中断
(Data Abort)
,访问数据出错的时候会产生此中断。 - IRQ 中断
(IRQ Interrupt)
,外部中断,芯片内部的 外设中断 都会引起此中断的发生 - FIQ 中断
(FIQ Interrupt)
,快速中断,如果需要快速处理中断的话就可以使用此中断。主要用于高速数据传输及通道处理中 , FIQ有 自己的专用寄存器( R8 ~R14 )
GIC中断控制器 :
- GIC中断控制器 用于接收到外部中断信号后 , 进行处理最终 通过
VFIQ
、VIRQ
、FIQ
、IRQ
四个信号报给ARM
内核- GIC 将众多的 中断源 分为分为三类:
SPI(Shared Peripheral Interrupt)
共享中断 , 这是所有核共享的中断 , 这些中断所有的Core
都可以处理 , 不限定特定core
PPI(Private Peripheral Interrupt)
,私有中断,每个核有自己独有的中断。这些独有的中断需要指定的核心进行处理SGI(Software-generated Interrupt)
,软件中断,由软件触发引起的中断,通过向寄存器GICD_SGIR
写入数据来触发,系统会使用SGI
中断来完成 多核 之间的通信。