购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

5.2 Cortex-A9处理器的结构

Cortex-A9处理器的内核结构如图5.3所示。每个Cortex-A9的CPU都能在一个周期内给出两个指令,并且以无序的方式执行。CPU动态地实现分支预测和可变长度的流水线,性能达到2.5DMIPS/MHz。Cortex-A9处理器实现Armv7-A架构,支持虚拟存储器,能执行32位的Arm指令、16位及32位的Thumb指令和在Jazelle状态下的8位Java字节码。

图5.3 Cortex-A9处理器的内核结构

注:(1)Jazelle-DBX(Direct Bytecode eXecution)在Armv5-TEJ中引入,用于加速Java的性能,同时兼顾功耗。在应用处理器中,由于提升存储器利用率和改善即时(JIT)编译器的组合降低了它的价值,因此,很多Armv7-A处理器不实现这种硬件加速。Jazelle-DBX能在有限的存储器空间(如手机和低成本的嵌入式应用)内很好地实现高性能的Java。

(2)Armv7架构包含两套指令集,即Arm和Thumb指令集。在这两套指令集中,绝大部分可用的功能是一样的。Thumb指令集是最通用的32位Arm指令集的子集。Thumb指令为16位长度,它对应的每条32位Arm指令与之有相同的效果。使用Thumb指令的优势在于可以降低代码密度。由于改善了代码密度,因此缓存Thumb指令比缓存Arm指令要好很多,显著减小了所要求的存储器空间。但是,程序员仍可使用Arm指令集用于特殊的且对性能要求很高的代码段。

(3)在Armv6-T2中引入了Thumb-2技术,在Armv7中也要求使用它。该技术将最初的16位Thumb指令扩展到包含32位指令。在Armv6-T2中引入的32位Thumb指令允许Thumb代码达到与Arm代码相近的性能。此外,与单纯使用16位Thumb指令相比,这样做有更低的代码密度。

5.2.1 处理器模式

Arm结构为莫代尔结构。在引入TrustZone安全性扩展之前,处理器有7种模式,如表5.1所示。其中有6种特权模式和1种非特权(用户)模式。在特权模式下,可以执行在非特权模式下不能执行的某些任务。在非特权模式下,操作时有一些限制,对系统的整体配置有影响,如MMU配置和缓存操作。

表5.1 Armv6前的Arm处理器模式

引入TrustZone安全性扩展后,为处理器创建了两种安全状态,它与特权/非特权模式相独立,带有一个新的监控模式,作为安全和非安全状态之间的门槛,独立于每种安全状态,如图5.4所示。

对实现TrustZone安全性扩展的处理器来说,通过将用于器件的硬件和软件资源分配到用于安全子系统的安全世界或非安全世界(普通世界)实现系统的安全性。当处理器处于非安全状态时,它不能访问分配给安全状态的存储器。

在这种情况下,安全监控程序就相当于在两个世界直接来回移动的门槛。如果实现了TrustZone安全性扩展,则在监控模式下运行的软件控制处理器在安全和非安全状态之间切换。

Armv7-A架构的虚拟化扩展增加了系统管理程序(Hypervisor)模式,该技术使得在相同的系统内可共存多个操作系统,Arm的虚拟化扩展使得其可以在相同的平台上运行多个操作系统,如图5.5所示。

图5.4 非安全世界和安全世界

图5.5 系统管理程序

注:Guest OS指运行在虚拟机上的操作系统。

如果实现了虚拟化扩展,则此处的特权模式不同于前面的结构。在非安全世界中,有3个特权级,即PL0、PL1和PL2。

(1)PL0:应用程序软件的特权级,在用户模式下执行。在用户模式下,执行软件被描述为非特权软件。此时,软件不能访问处理器结构的一些特征;特别地,不能改变任何配置。

(2)PL1:在所有模式下执行的软件,不同于用户模式和系统监控模式。通常,操作系统软件运行在PL1上。

(3)PL2:系统管理程序模式。它能控制并切换在PL1上执行的Guest OS。

如果实现了虚拟化扩展,那么系统管理程序将运行在PL2上。虚拟化扩展使得PL2可以在相同的平台上运行多个操作系统。这些特权级从TrustZone安全和普通设置中独立出来。

注:特权级定义了在当前安全状态下访问资源的能力。

特权级处理器在不同状态下的可用处理器模式如图5.6所示。

图5.6 特权级处理器在不同状态下的可用处理器模式

一个通用的操作系统,如Linux希望运行在非安全状态下。厂商特定的固件或对安全性敏感的软件希望占用安全状态。在一些情况下,运行在安全状态下的软件比运行在非安全状态下的软件有更多的特权。

注:当前的处理器模式和执行状态被保存在当前程序状态寄存器(Current Program Status Register,CPSR)中。特权软件可以修改处理器的状态和模式。

5.2.2 寄存器

本节介绍Cortex-A9处理器提供的寄存器类型。

1.通用寄存器

图5.7 通用寄存器

Arm架构中提供了16个32位的通用寄存器(R0~R15)给软件使用,如图5.7所示。其中,15个(R0~R14)用于通用的数据存储,而R15则用于程序计数器。当CPU内核执行指令时,会修改R15的值。对R15的写操作将改变程序流。软件也可以访问CPSR。前面所执行模式下CPSR的内容将保存和复制到一个被称为保存的程序状态寄存器(Saved Program Status Register,SPSR)中。

虽然软件可以访问寄存器,但是根据运行软件的模式和所访问的寄存器,一个寄存器可能对应不同的物理存储位置,这称为分组(Banking)。如图5.8所示,背景为灰色的寄存器被分组。它们使用物理区分保存方法,只有当进程在特殊模式下运行时才可访问它们。

在所有模式下,低寄存器和R15共享相同的物理存储空间。对高寄存器来说,在不同模式下,程序员可见的寄存器组如图5.8所示。例如,将R8~R12分组用于FIQ模式,即在不同的物理存储空间访问它们。对不是用户模式和系统模式的其他模式而言,将R13和SPSR分组。

图5.8 Arm CPU内的寄存器集

在分组情况下,软件不能按照以前那样指定所访问的寄存器实例。例如,在用户模式下执行程序,指定R13将访问R13_user;在SVC模式下执行程序,指定R13将访问R13_svc。

在所有模式下,R13寄存器都是堆栈指针,当不要求堆栈操作时,它可以作为通用寄存器使用。

R14(链接寄存器)用于保存进入子程序后从子程序返回的地址,通常通过BL指令来实现。当它没有用于保存返回地址时,它也可以作为通用寄存器。R14_svc、R14_irq、R14_fiq、R14_abt和R14_und的用法类似,当产生中断和异常时,或者在中断或异常处理程序中执行分支(跳转)或链接指令时,其用于保存来自R15的返回值。

R15是程序计数器,用于保存当前程序地址。在Arm状态下读取R15时,[1:0]比特位总为零,[31:2]比特位保存着PC;在Thumb状态下,对[0]比特位的读总是返回0。

注:(1)实际上,在Arm状态下,总是指向当前指令前面的8字节;在Thumb状态下,总是指向当前指令前面的4字节。

(2)复位时,R0~R14的值是不确定的。此外,在使用堆栈指针SP之前,必须由启动程序对其进行初始化。

2.HYP模式

对于支持虚拟化扩展的实现,在HYP模式下,Cortex-A9处理器提供了额外的寄存器。系统管理程序工作在特权级PL2上,它访问自己的R13(SP)和SPSR版本。HYP模式使用用户模式,链接寄存器用于保存函数的返回地址,并且有一个专用的寄存器ELR_hyp,用于保存异常返回地址。HYP模式只用于非安全世界,提供了用于虚拟化的工具。

3.程序状态寄存器

在任何时刻,软件都可以访问16个寄存器(R0~R15)及CPSR。在用户模式下,访问CPSR的一个限制形式称为应用程序状态寄存器(Application Program Status Register,APSR)。

当前状态寄存器用于保存APSR标志、当前处理器的模式、中断禁止标志、当前处理器的状态(Arm/Thumb/ThumbEE/Jazelle)、端、用于IT块的执行状态位。

程序状态寄存器(Program Status Register,PSR)构成一个额外的分组寄存器集,每种异常模式都有它自己的保存程序状态寄存器(Saved Program Status Register,SPSR),当发生异常时,它们将自动保存发生异常前的CPSR。在用户模式下,不可以访问它们。

对应用程序的程序员来说,必须使用APSR访问CPSR的一部分,可以在用户模式下修改它们。APSR只能用于访问N、Z、C、V、Q和GE[3:0]比特位。通常,不能直接访问这些比特位,但是可以通过条件码指令来设置和测试这些比特位。

例如,指令“CMP R0,R1”用于比较R0和R1的值。如果R0和R1的内容相同,则将Z标志置位。

CPSR比特位的分配如图5.9所示。

图5.9 CPSR比特位的分配

(1)N:来自ALU的负数结果。当结果为负数时,该位为1。

(2)Z:来自ALU的零结果。当结果为全零时,该位为1。

(3)C:来自ALU操作的进位输出。当结果有最高位进位时,该位为1。

(4)V:来自ALU操作的溢出。当结果溢出时,该位为1。

(5)Q:累计饱和(也称为sticky)。

(6)J:用于确认CPU是否处于Jazelle状态。

(7)GE[3:0]:一些SIMD指令使用它。

(8)IT[7:2]:Thumb-2指令组执行if-then条件。

(9)E:控制加载/保存端。

(10)A:禁止异步异常终止。

(11)I:禁止IRQ。

(12)F:禁止FIQ。

(13)T:指示CPU是否处于Thumb状态。

(14)M[4:0]:指定处理器的模式。这些模式包括:①USR模式为10000;②FIQ模式为10001;③IRQ模式为10010;④SVC模式为10011;⑤MON模式为10110;⑥ABT模式为10111;⑦HYP模式为11010;⑧UND模式为11011;⑨SYS模式为11111。

通过指令直接写CPSR模式比特位就可以改变CPU的模式。对于更普遍的情况,当出现异常结果时,处理器自动修改模式。在用户模式下,程序员不能对PSR的[4:0]比特位进行操作,这些比特位用于控制处理器的模式;也不能操作A、I和F比特位,它们用于使能/禁止异常。

4.协处理器

CP15称为系统控制协处理器,提供对CPU大量特性的控制能力。它包含最多16个32位的基本寄存器。访问CPU由特权控制,在用户模式下,有些寄存器不可使用。CP15寄存器访问指令指定要访问的基本寄存器,指令中的其他域用于更准确地定义访问及增加CP15内32位物理寄存器的数量。在CP15内,将16个32位的基本寄存器分别命名为c0~c15,但是经常用它们的名字作为参考,如CP15系统控制寄存器称为CP15.SCTLR。

CP15内的寄存器集如表5.2所示。

表5.2 CP15内的寄存器集

续表

通过一个通用处理器寄存器(Rt)读/写CP15内的寄存器CRn,以实现对所有系统结构功能的控制。指令中的Op1、Op2和CRm域用于选择寄存器或操作。访问CP15的指令格式如代码清单5.1所示。

代码清单5.1 访问CP15的指令格式

(1)Op1为协处理器指定的4位操作码,对CP15来说,Op1为0000。

(2)CRn为目标寄存器的协处理寄存器编号,即c0~c15。

(3)CRm为额外的目标寄存器或源操作数寄存器,如果不需要设置额外信息,则将其设置为c0。

(4)Op2提供附加信息,如寄存器的版本号或访问类型,用于区分同一编号的不同物理寄存器,可以省略Op2或将其设置为0。

下面以只读MIDR为例,说明读取该寄存器的方法。图5.10所示为MIDR比特位的分配。

图5.10 MIDR比特位的分配

(1)[31:24]为制定者,对Arm设计的处理器来说,其值为0x41。

(2)[23:20]为变种,给出了处理器的版本号。

(3)[19:16]为架构,对Arm架构v7来说,其值为0xF。

(4)[15:4]为器件号,如0xC09表示Cortex-A9处理器。

(5)[3:0]为版本,给出了处理器的补丁版本。

在特权模式下,程序员可以使用下面的指令读取MIDR:

5.系统控制寄存器

通过使用CP15来访问系统控制寄存器(SCTLR)。SCTLR用于控制标准的存储器和系统工具,以及提供状态信息,用于CPU内所实现的功能。只有当CPU处于PL1或更高特权级时,才可以访问SCTLR。SCTLR的简化视图如图5.11所示。

图5.11 SCTLR的简化视图

(1)TE:Thumb异常使能,用于控制是在Arm状态下还是在Thumb状态下发生异常。

(2)NMFI:支持不可屏蔽FIQ(MMFI)。

(3)EE:异常端,用于定义在进入异常时CPSR.E比特位的值。

(4)U:表示所用的对齐模型。

(5)FI:FIQ配置使能。

(6)V:用于选择异常向量表的基地址。

(7)I:指令缓存使能位。

(8)Z:分支预测使能位。

(9)C:缓存使能位。

(10)A:对齐检查使能位。

(11)M:MMU使能位。

启动代码序列的一部分用于设置CP15.SCTLR,使能分支预测,如代码清单5.2所示。

代码清单5.2 设置SCTLR

5.2.3 流水线

在Cortex-A9处理器内实现的流水线采用了高级取指和指令预测技术,可以避免由于存储器延迟引起指令的停止而影响分支指令的执行。在Cortex-A9处理器中,可以预先加载最多4个指令缓存行,用于减小存储器延迟对指令吞吐量的影响。在每个周期内,CPU取指单元能够向指令译码缓冲区连续发送2~4个指令,以保证高效地使用超标量流水线。CPU实现一个超标量译码器,用于在一个周期内对2个完整的指令进行译码。4个CPU流水线中的任何一个流水线都能从发布队列中选择指令。在每个周期内,并行流水线支持2个算术单元、加载和保存单元的并行执行,以及解析任何分支(跳转)。

通过将物理寄存器动态重命名到一个虚拟可用的寄存器池中来使能Cortex-A9处理器采用预测执行指令技术。CPU通过使用虚拟寄存器重命名来消除寄存器之间的依赖性,但不会影响程序的正确执行。通过基于展开循环的有效硬件,该特性允许代码加速。同时,通过在相邻指令间消除数据的依赖性来提高流水线的利用率。

Cortex-A9处理器中的存储器系统通过提交相互依赖的加载-存储指令进行解析,以降低流水线出现停止的可能性。通过自动或用户驱动的预取操作,Cortex-A9处理器支持最多4个数据缓存行的填充要求。

CPU的一个关键特性就是允许指令无序写回,这样可以释放流水线资源而不依赖系统提供的和所要求的数据顺序。

在指令条件或解析前面的分支之前,或者在需要写的数据可用之前,CPU能预测出加载-保存指令。如果用于执行加载/保存的条件失败,则刷新任何不利的影响,如修改寄存器的行为。

5.2.4 分支预测

为了减小分支对高度流水CPU造成的不利影响,在Cortex-A9处理器内静态地和动态地实现分支预测。在编译程序时,由指令提供静态分支预测。通过前一条指定指令的执行结果动态地实现分支预测可以确定是否执行分支。动态分支预测逻辑使用一个全局分支历史缓冲区(Global Branch History Buffer,GHB)。GHB是一个有4096个入口的表,包含用于指定分支的2位预测信息,在每次执行分支指令时,更新预测信息。分支执行和总的指令吞吐量得益于分支目标地址缓存(Branch Target Address Cache,BTAC)的使用。在BTAC中,保存着最近分支的目标地址。该512个入口的地址缓存结构是2路×256个入口。根据所计算的有效地址和转换后的物理地址,在产生真正的目标地址前,将用于指定分支的目标地址送到预加载单元中。此外,如果一个指令循环适配4个BTAC入口,则将关闭对指令缓存的访问,以降低功耗。

Cortex-A9处理器能预测条件分支、无条件分支、间接分支、PC目的数据处理操作,以及在Arm和Thumb状态之间切换的分支。然而,Cortex-A9处理器不能预测下面的分支、指令。

(1)除在Arm和Thumb状态之间切换的分支外,在其他状态之间切换的分支。

(2)带有S后缀的指令,这些指令用于从异常返回,这是由于这些指令可能改变特权模式和安全状态,对程序的执行有不利的影响。

(3)所有用于改变模式的指令。

通过将CP15 c1控制寄存器的Z比特位设置为1,用户可以使能程序流预测功能。在使能程序流预测功能前,必须执行一次BTAC刷新操作,将GHB设置为已知状态。Cortex-A9处理器用一个有8个入口的返回堆栈缓存保存32位子程序的返回地址。这个特性显著地减小了执行子程序调用带来的不利影响,可以寻址最大8级深度的嵌套程序。

5.2.5 指令和数据对齐

Arm架构指定了Arm指令为32位宽度,要求字对齐。Thumb指令为16位宽度,要求半字对齐。Thumb-2指令为16位或32位宽度,也要求半字对齐。数据访问可以是非对齐的,CPU内的保存/加载单元将其分解为对齐访问。在需要时,就插入这些访问的数据并发送到CPU的寄存器文件中。

注:APU和PS整体只支持用于指令与数据的小端结构。

1.端

术语小端(Little-Endian)和大端(Big-Endian)最早出现在20世纪80年代丹尼科恩(Danny Cohen)的论文 On Holy Wars and a Plea for Peace 中。

对于存储器自身,其有两种基本的查看方法,即小端和大端。在使用大端的机器中,在存储器中,一个对象的最高有效位保存在地址的最低有效位中;在小端机器中,最高有效字节保存在地址的最高有效位中。

术语字节排序(Byte-Ordering)不同于端。考虑如代码清单5.3所示的代码片段。

代码清单5.3 端访问

在一个32位的大端机器中,赋给c的值为最高有效字节0x44;在一个小端机器中,赋给c的值为最低有效字节0x11。图5.12给出了通过STR指令将一个寄存器的32位数据写到地址0x1000中的过程,核执行LDRB指令,对一个字节进行读操作。根据存储器系统使用大端还是小端,指令序列将返回不同的值。

图5.12 大端和小端

Arm核支持大端和小端模式,但是在通常情况下,默认为小端模式。用于Arm的Linux只使用小端模式;x86使用小端模式;PowerPC通常使用大端模式,尽管它也能使用小端模式。一些普通的文件格式和网络协议指定不同的端。例如,BMP和GIF文件是小端,而JPG文件是大端;TCP/IP是大端,但是USB和PCI是小端。

因此,需要考虑两个问题,即代码的可移植性和数据共享。使用多个块构建的一个系统包括一个或多个核、DSP、外设、存储器和网络连接。当在这些元素之间共享数据时,会有潜在的数据冲突,可能需要修改代码。

Cortex-A系列处理器支持系统使用不同的端配置,通过CPSR的E比特位实现在小端和大端之间的切换。指令REV可以对Arm寄存器内的字节进行翻转,这样就可以在小端和大端之间提供简单的转换。

软件可以动态地修改CPSR的E比特位,SETEND汇编指令同于实现该功能。CP15.SCTLR(系统控制寄存器c1)包含EE比特位,定义了异常时所切换的端模式,以及转换表查找的端。

现代的Arm处理器支持一个大端格式,其架构被称为BE8,只应用于数据存储器系统。以前的Arm处理器使用不同的大端格式,其架构被称为BE-32,应用于数据和指令。

2.对齐

Arm核的对齐访问是非常重要的。在以前的Arm处理器中,对存储器进行非对齐访问是可以的。在Arm7和Arm9处理器中,在存储器中执行非对齐的LDR和对齐访问是相同的,但是需要对返回的数据进行旋转,因此,在所要求地址中的数据被放在所加载寄存器的最低有效字节中。一些以前的编译器和操作系统都能通过该行为进行优化,但当把代码从Armv4/Armv5移植到Armv7中时会出现问题。

程序员可以配置Arm的MMU(通过使用CP15.SCTLR的A比特位),让其自动检测非对齐访问,并且异常终止这些访问。

对Cortex-A系列处理器来说,其支持非对齐访问,但需要设置CP15.SCTLR的U比特位来使能这样的访问,这就意味着读/写字和半字的指令可以访问没有对齐到半字和字边界的地址。然而,加载和保存多个指令(LDM和STM),以及加载或保存双字(LDRD/STRD)必须对齐字边界。加载和保存浮点值也需要对齐。ABI施加了更强的额外对齐约束。

与对齐访问相比,非对齐访问需要消耗额外的周期,因此对齐也是一个性能问题。此外,不保证这样的访问是原子的,这就意味着一个外部的代理(系统中的其他核)可能执行一个存储器访问,它看上去会穿过非对齐访问。例如,它可能读被访问的位置,看到一些字节新的数据,而其他字节是以前的数据。

一个对齐的字地址是4的倍数,如0x100、0x104、0x108、0x10c、0x110等,如图5.13所示。

一个非对齐的字地址如图5.14所示。先从地址0中取出3字节,再从地址4中取出1字节。

图5.13 对齐的字地址

图5.14 非对齐的字地址

一个简单的例子,在使用memcpy()函数时,在字对齐边界处复制少量的字节将被编译到LDM或STM指令中。而在字边界处复制较大的数据块将使用优化的库函数,也使用LDM或STM指令。复制起始点或结束点不在字边界处的数据块,将导致调用通用的memcpy()函数,此时,速度明显变慢,如果源和目的没有对齐,则没有优化开始和结束碎片。

5.2.6 跟踪和调试

Cortex-A9处理器实现Armv7调试架构,处理器的调试接口由下面几部分构成。

(1)一个基准CP14接口,用于实现Armv7调试架构和Arm架构参考手册中描述的一套调试事件。

(2)一个扩展CP14接口,用于实现处理器指定的一套调试事件(Arm架构参考手册中进行了解释)。

(3)通过一个DAP,将一个外部的调试接口连接到外部的调试器上。

Cortex-A9处理器包含一个程序跟踪模块,该模块提供了Arm CoreSight技术,用于其中一个Cortex-A9处理器的程序流跟踪能力,并且提供了观察处理器真实指令流的能力。Cortex-A9处理器程序跟踪宏(Program Trace Module,PTM)使得对所有代码分支和带有周期计数使能统计分析功能的程序流变化可见。通过PTM模块和CoreSignt设计工具,软件开发人员能够非强制性地跟踪多个处理器的执行历史,并且通过标准的跟踪接口将带有校正时间戳的历史信息保存到片上缓冲区或片外存储区中。这样,就提高了开发和调试过程的可视性。

Cortex-A9处理器也可对程序计数器和事件监控器进行配置,用于搜集处理器与存储器系统工作时的统计信息。 qKTydM47GGIn4/Zb4u26eFQk3JzHi/sVlwYKi932BfYoPCLLoQgYSo2Ao3julkL0

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开