二、Cortex-A系列处理器模式和内核寄存器

本篇的笔记主要是对《ARM Cortex-A(armV7)编程手册V4.0》文档第二、三章的学习记录,重点是对第三章—ARM Processor Modes and Registers的学习。

一、ARM架构处理器模式
ARM架构的处理器有如下图所示的7种经典处理器模式:
7种经典的处理器模式
这7种模式是在ARMv6之前就已经存在的,所以叫做经典模式。随着处理器架构的发展和一些CPU扩展的增加,在这7种经典模式的基础上又引入了Monitor (MON) 模式和Hyp (HYP)模式,它们分别用于实现安全扩展和虚拟化扩展。所以,对于ARMv7架构的处理器,目前共有如下图所示的9种处理器模式:
ARMv7架构CPU处理器模式
这9种处理器模式按照对CPU资源的访问权限又被划分为3种不同的特权等级PL0~PL2。PL0为用户级模式,只有User模式为用户级的处理器模式;PL2为超级管理员模式,只有Hyp模式为超级管理员级别的处理器模式(因为Hyp模式用于实现虚拟化扩展,可以让操作系统实现多用户登录,故其相当于一个超级管理员,用于管理操作系统用户);PL1为系统级模式,其权限介于PL0和PL2之间,除User和Hyp外的其余处理器模式均为PL1级。

当架构引入了安全扩展(TurstZone)后,又引入了安全状态的概念。在具有安全扩展的实现上,CPU具有安全(Secure World)和非安全(Normal World)两种安全状态。要注意的是,处理器模式和安全状态是两个独立的概念,在任一个时刻,某个CPU都处于某种处理器模式和某种安全状态。Monitor (MON)模式作为安全态和非安全态之间的过渡模式,用于在两种状态之间进行切换,如下2图所示:
Mon模式切换安全状态
带有虚拟化扩展的安全状态
下图是CPU可能出现的处理器模式和安全状态的组合表:
处理器模式和安全状态组合表
可以看到,Hyp模式只能出现在非安全态中,也就是说,处理器想进入Hyp模式,必须先到Monitor模式中将处理器切换到非安全状态后,才能切换到Hyp模式。

当前CPU处于何种处理器模式,何种安全状态,可以通过CPSR寄存器获知。我们可以在特权模式下(PL1和PL2)下通过软件的方式切换处理器模式,另外,异常发生时也会自动进入相应的处理器模式

二、内核寄存器
ARM架构里面定义了16个32位的通用CPU寄存器R0~R15。在不同的模式下,这16个寄存器可能进行了BANK(影子或分身)处理,如下图所示,阴影部分表示寄存器在对应的模式下是BANK访问的:
寄存器表
下面详细讲一下R13,R14,R15这三个特殊的寄存器。

  • R13(SP),栈指针寄存器
    这个寄存器用来保存栈顶位置。将一个内存地址放到这个寄存器里面,以后就可以通过栈操作指令来操作这个寄存器,就可以将这片内存用作栈。注意,SP只能设置栈顶位置,不能设置栈的大小,所以要预留足够的栈内存空间,避免栈溢出。SP一般都被用在C代码里面来管理栈,所以在进入C语言执行环境之前,必须设置SP寄存器。如果不使用栈,也可将SP当作通用寄存器来使用。

  • R14(LR),链接寄存器
    这个寄存器保存的是通过BL指令跳转到的函数的返回地址。同理,其特权模式下的BANK版本则用于保存对应的异常返回地址,也用于保存在异常里面通过BL跳转到其它函数后的返回地址。

  • R15(PC),程序计数器
    有的文献也叫作PC指针,个人觉得还是程序计数器更贴近其实际用途。在以前程序结构都还比较简单(顺序执行,没有跳转),没有现在这么复杂的时候,PC值反映了代码执行到哪里了,或者已经执行了多少条代码,类似于一个计数器,所以其名称也一直被沿用下来。
    关于PC,在文档中有下面这样一段描述:
    R15 is the program counter and holds the current program address (actually, it always points eight bytes ahead of the current instruction in ARM state and four bytes ahead of the current instruction in Thumb state, a legacy of the three stage pipeline of the original ARM1 processor)
    要理解这段话的意思,需要知道计算机组成原理与体系结构里面的流水线概念。这段话的意思是说在ARM架构里面,PC的值总是当前正在被执行的指令的地址 + 8(ARM指令),或+4(THUMB指令),也就是经典的3段流水线(取指令 + 译指令 + 执行指令)的情况。我们知道一条ARM指令固定4字节长度,一条THUMB指令通常为2字节长度,故在3段流水线的情况下,当执行0x0000_0000地址处的指令时,0x0000_0004(ARM指令)/ 0x0000_0002(THUMB指令)地址处的指令正在被译码,0x0000_0008(ARM指令)/ 0x0000_0004(THUMB指令)地址处的指令正在被取指,而PC的值是当前取指的地址,所以此时PC也就等于0x0000_0008(ARM指令)/ 0x0000_0004(THUMB指令),也就说描述中说的当前正在执行的指令地址+4或+8的值。当然,这里说的并不包含ARM指令和THUMB指令需要切换的情况,或者出现分支跳转时的情况。
    但是,Cortex-A处理器的流水线真的是3段的吗,毕竟3段流水线已经是很老的设计了。下图是从《ARM Cortex-A(armV7)编程手册V4.0》中截取的Cortex-A系列处理器的部分参数列表:
    Cortex-A系列处理器参数
    篮色方框部分的内容是处理器的流水线参数,可以看到2011年4月发布的A7是基于超标量的3条流水线,每条流水线有15段,其吞吐率可以达到3条指令/cycle。而同年10月发布的A7,由于其只是部分双发射,所以其吞吐率介于1~2之间(高于单流水单发射的1,低于双流水线双发射的2),并且流水线只有8段,可以猜想由于A15的流水线段数过多引起了分支预测错误导致的惩罚问题比较严重,所以A7减少了流水的段数。而2013年6月发布的A12,其流水线条数为2(低于A15的3),流水线的段数为11(高于A7的8),所以可以看出A12的流水线设计是在A7和A15之间的折衷,用于平衡流水线的吞吐率和分支预测错误问题。

由此可以看出,Cortex-A系列的处理器流水线段数已经达到10+,远超3段,不仅如此,流水线也达到了2条,3条。但是为什么PC值还是按照3段流水线来计算呢?我们只能说3段流水线设计太经典了,哪怕芯片架构实际使用的流水线已经远超3段,但是指令集还是按照3段流水线来设计的,以便我们在使用指令集的时候还是可以按照经典的3段式流水线来考虑和计算PC的值,这就是设计在改进,接口却保持不变的一种理念
接下来,我们设计一段简单的代码来验证一下这段关于PC的描述,这里不涉及混用ARM指令和THUMB指令。

.data 

name_target:
.asciz "TARGET"
name_r15:
.asciz "PC"

.text

main:
	bl int_init
	bl imx6u_clkinit
	bl delay_init
	bl clk_enable
	bl led_init
	bl uart_init

	#打印target_address处指令的地址
	ldr r0, =name_target
	ldr r1, =target_address
	bl print_register

	ldr r0, =name_r15

	#这条指令将PC的值放进R1,按照3段流水线计算,此时R1中的值就应该是target_address的值
	#执行这条指令的时候,正在取target_address地址处的指令
	mov r1, r15

	#打印保存在R1中的PC值
	bl print_register

target_address:
	bl loop_task

编译后固化到SD卡,连接串口并打开串口调试助手后,开机从SD卡启动,可以看到串口打印了target_address的值和PC的值,确实是一样的。这就证明执行[ mov r1, r15 ]这条指令的时候,PC值确实是target_address,并且编译出的指令是ARM指令,处理器处于ARM状态。
串口打印PC值和目标指令的地址
当代码镜像里面既有32位的ARM指令,又有16位的THUMB指令时,需要通过CPSR或CP15的SCTRL的T位来进行处理器状态的切换。切换处理器状态的时候,应该将流水线排空,以防一种状态的指令在另一种状态中去执行。BX和BLX指令可以切换处理器状态,并排空流水线。LDR PC和POP/LDM PC也具有这样的功能。参考《ARM Cortex-A(armV7)编程手册V4.0》 - 4.5 Interworking

  • PSRs,程序状态寄存器
    PSRs,指CPSR,APSR和SPSR。

CPSR,表示当前程序状态寄存器,这个寄存器没有分身,用于记录如下一些CPU运行时的信息:
1.APSR标志
2.处理器当前所处的模式
3.中断使能标志
4.当前处理器状态为ARM, Thumb, ThumbEE, 还是Jazelle
5.大小端
6.IT块的执行状态位

APSR,用户程序状态寄存器,其实就是CPSR寄存器,只不过在User模式下,只能访问CPSR的某些位,文档就用APSR表示是在用户模式下访问PSR,所以就有了CPSR和APSR。其实都是同一个寄存器,只是用APSR表示当前是在用户模式下,对CPSR寄存器只有有限的访问权限,只能访问CPSR的APSR标志部分。

SPSR,备份程序状态寄存器。这个寄存器是BANK的,每个异常模式都有自己的Saved Program Status Register (SPSR),用于保存进入异常前的模式的CPSR值,方便切换模式的时候用于恢复CPSR。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值