内核技术中文网»首页 论坛 圈点 查看内容

0 评论

0 收藏

分享

ARM64基础知识:体系结构编程与实践

1 ARM介绍

ARM公司主要向客户提供处理器IP。通过这种独特的盈利模式,ARM软硬件生态变得越来越强大。表1.1展示了ARM公司重大的历史事件。

表1.1 ARM公司重大的历史事件

ARM体系结构是一种硬件规范,主要是用来约定指令集、芯片内部体系结构(如内存管理、高速缓存管理)等。以指令集为例,ARM体系结构并没有约定每一条指令在硬件描述语言(Verilog或VHDL)中应该如何实现,它只约定每一条指令的格式、行为规范、参数等。为了降低客户基于ARM体系结构开发处理器的难度,ARM公司通常在发布新版本的体系结构之后,根据不同的应用需求开发出兼容体系结构的处理器IP,然后授权给客户。客户获得处理器IP之后,再用它来设计不同的SoC芯片。以ARMv8体系结构为例,ARM公司先后开发出Cortex-A53、Cortex-A55、Cortex-A72、Cortex-A73等多款处理器IP。

ARM公司一般有两种授权方式。

1.体系结构授权。客户可以根据这个规范自行设计与之兼容的处理器。 2.处理器IP授权。ARM公司根据某个版本的体系结构来设计处理器,然后把处理器的设计方案授权给客户。

从最早的ARM处理器开始,ARM体系结构已经从v1版本发展到目前的v8版本。在每一个版本的体系结构里,指令集都有相应的变化,其主要变化如下所示。

ARM体系结构又根据不同的应用场景分成如下3种系列。

  • A系列:面向性能密集型系统的应用处理器内核。
  • R系列:面向实时应用的高性能内核。
  • M系列:面向各类嵌入式应用的微控制器内核。

2 ARMv8体系结构基础知识

2.1 ARMv8体系结构

ARMv8是ARM公司发布的第一代支持64位处理器的指令集和体系结构。它在扩充64位寄存器的同时提供了对上一代体系结构指令集的兼容,因此它提供了运行32位和64位应用程序的环境。

ARMv8体系结构除了提高了处理能力,还引入了很多吸引人的新特性。

1.具有超大物理地址(physical address)空间,提供超过4 GB物理内存的访问。 2.具有64位宽的虚拟地址(virtual address)空间。32位宽的虚拟地址空间只能供4 GB大小的虚拟地址空间访 问,这极大地限制了桌面操作系统和服务器等的应用。64位宽的虚拟地址空间可以提供更大的访问空间。 3.提供31个64位宽的通用寄存器,可以减少对栈的访问,从而提高性能。 4.提供16 KB和64 KB的页面,有助于降低TLB的未命中率(miss rate)。 5.具有全新的异常处理模型,有助于降低操作系统和虚拟化的实现复杂度。 6.具有全新的加载-获取指令(Load-Acquire Instruction)、存储-释放指令(Store-Release Instruction),专门为C++11、C11以及Java内存模型设计。

ARMv8体系结构一共有8个小版本,分别是ARMv8.0、ARMv8.1、ARMv8.2、ARMv8.3、ARMv8.4、ARMv8.5、ARMv8.6、ARMv8.7,每个小版本都对体系结构进行小幅度升级和优化,增加了一些新的特性。

2.2 采用ARMv8体系结构的常见处理器内核

下面介绍市面上常见的采用ARMv8体系结构的处理器(简称ARMv8处理器)内核。

Cortex-A53处理器内核: ARM公司第一批采用ARMv8体系结构的处理器内核,专门为低功耗设计的处理器。通常可以使用1~4个Cortex-A53处理器组成一个处理器簇或者和Cortex-A57/Cortex-A72等高性能处理器组成大/小核体系结构。

Cortex-A57处理器内核: 采用64位ARMv8体系结构的处理器内核,而且通过AArch32执行状态,保持与ARMv7体系结构完全后向兼容。除ARMv8体系结构的优势之外,Cortex-A57还提高了单个时钟周期的性能,比高性能的Cortex-A15高出了20%~40%。它还改进了二级高速缓存的设计和内存系统的其他组件,极大地提高了性能。

Cortex-A72处理器内核: 2015年年初正式发布的基于ARMv8体系结构并在Cortex-A57处理器上做了大量优化和改进的一款处理器内核。在相同的移动设备电池寿命限制下,Cortex-A72相对于基于Cortex-A15的设备具有3.5倍的性能提升,展现出了优异的整体功效。

2.3 ARMv8体系结构中的基本概念

ARM处理器实现的是精简指令集体系结构。在ARMv8体系结构中有如下一些基本概念和定义。

处理机(Processing Element,PE):在ARM公司的官方技术手册中提到的一个概念,把处理器处理事务的过程抽象为处理机。 执行状态(execution state):处理器运行时的环境,包括寄存器的位宽、支持的指令集、异常模型、内存管理以及编程模型等。ARMv8体系结构定义了两个执行状态。AArch64:64位的执行状态。提供31个64位的通用寄存器。提供64位的程序计数(Program Counter,PC)指针寄存器、栈指针(Stack Pointer,SP)寄存器以及异常链接寄存器(Exception Link Register,ELR)。提供A64指令集。定义ARMv8异常模型,支持4个异常等级,即EL0~EL3。提供64位的内存模型。定义一组处理器状态(PSTATE)用来保存PE的状态。AArch32:32位的执行状态。提供13个32位的通用寄存器,再加上PC指针寄存器、SP寄存器、链接寄存器(Link Register,LR)。支持两套指令集,分别是A32和T32(Thumb指令集)指令集。支持ARMv7-A异常模型,基于PE模式并映射到ARMv8的异常模型中。提供32位的虚拟内存访问机制。定义一组PSTATE用来保存PE的状态。 ARMv8指令集:ARMv8体系结构根据不同的执行状态提供不同指令集的支持。A64指令集:运行在AArch64状态下,提供64位指令集支持。A32指令集:运行在AArch32状态下,提供32位指令集支持。T32指令集:运行在AArch32状态下,提供16位和32位指令集支持。 系统寄存器命名:在AArch64状态下,很多系统寄存器会根据不同的异常等级提供不同的变种寄存器。系统寄存器的使用方法如下。

<register_name>_Elx  //最后一个字母 x 可以表示0、1、2、3

如SP_EL0表示在EL0下的SP寄存器,SP_EL1表示在EL1下的SP寄存器。

本书重点介绍ARMv8体系结构下的AArch64执行状态以及A64指令集,对AArch32执行状态、A32以及T32指令集不做过多介绍,感兴趣的读者可以阅读ARMv8相关技术手册。

2.4 A64指令集

指令集是处理器体系结构设计的重点之一。ARM公司定义与实现的指令集一直在变化和发展中。ARMv8体系结构最大的改变是增加了一个新的64位的指令集,这是早前ARM指令集的有益补充和增强。它可以处理64位宽的寄存器和数据并且使用64位的指针来访问内存。这个新的指令集称为A64指令集,运行在AArch64状态下。ARMv8兼容旧的32位指令集——A32指令集,它运行在AArch32状态下。

A64指令集和A32指令集是不兼容的,它们是两套完全不一样的指令集,它们的指令编码是不一样的。需要注意的是,A64指令集的指令宽度是32位,而不是64位。

2.5 ARMv8处理器执行状态

ARMv8处理器支持两种执行状态——AArch64状态和AArch32状态。AArch64状态是ARMv8新增的64位执行状态,而AArch32是为了兼容ARMv7体系结构的32位执行状态。当处理器运行在AArch64状态下时,运行A64指令集;而当运行在AArch32状态下时,可以运行A32指令集或者T32指令集。

如图1.1所示,AArch64状态的异常等级(exception level)确定了处理器当前运行的特权级别,类似于ARMv7体系结构中的特权等级。

  • EL0:用户特权,用于运行普通用户程序。
  • EL1:系统特权,通常用于操作系统内核。如果系统使能了虚拟化扩展,运行虚拟机操作系统内核。
  • EL2:运行虚拟化扩展的虚拟机监控器(hypervisor)。
  • EL3:运行安全世界中的安全监控器(secure monitor)。

▲图1.1 AArch64状态的异常等级ARMv8体系结构允许切换应用程序的运行模式。如在一个运行64位操作系统的ARMv8处理器中,我们可以同时运行A64指令集的应用程序和A32指令集的应用程序,但是在一个运行32位操作系统的ARMv8处理器中就不能运行A64指令集的应用程序了。当需要运行A32指令集的应用程序时,需要通过一条管理员调用(Supervisor Call,SVC)指令切换到EL1,操作系统会做任务的切换并且返回AArch32的EL0,从而为这个应用程序准备好AArch32状态的运行环境。

2.6 ARMv8支持的数据宽度

ARMv8支持如下几种数据宽度。

  • 字节(byte):8位。
  • 半字(halfword):16位。
  • 字(word):32位。
  • 双字(doubleword):64位。
  • 四字(quadword):128位。

【文章福利】 小编在群文件上传了一些个人觉得比较好得学习书籍、视频资料,有需要的可以进群【977878001】 领取!!!额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)

内核资料直通车: Linux内核源码技术学习路线+视频教程代码资料

学习直通车(腾讯课堂免费报名): Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

3 ARMv8寄存器

3.1 通用寄存器

AArch64执行状态支持31个64位的通用寄存器,分别是X0~X30寄存器,而AArch32状态支持16个32位的通用寄存器。

除用于数据运算和存储之外,通用寄存器还可以在函数调用过程中起到特殊作用,ARM64体系结构的函数调用标准和规范对此有所约定,如图1.2所示。

在AArch64状态下,使用X(如X0、X30等)表示64位通用寄存器。另外,还可以使用W来表示低32位的数据,如W0表示X0寄存器的低32位数据,W1表示X1寄存器的低32位数据,如图1.3所示。

▲图1.2 AArch64状态的31个通用寄存器

▲图1.3 64位通用寄存器和低32位数据## 3.2 处理器状态

AArch64体系结构使用PSTATE寄存器来表示当前处理器状态(processor state),如表1.3所示。

表1.3 PSTATE寄存器

3.3 特殊寄存器

ARMv8体系结构除支持31个通用寄存器之外,还提供多个特殊的寄存器,如图1.4所示。

▲图1.4 特殊寄存器## 1.零寄存器

ARMv8体系结构提供两个零寄存器(zero register),这些寄存器的内容全是0,可以用作源寄存器,也可以用作目标寄存器。WZR是32位的零寄存器,XZR是64位的零寄存器。

2.PC指针寄存器

PC指针寄存器通常用来指向当前运行指令的下一条指令的地址,用于控制程序中指令的运行顺序,但是编程人员不能通过指令来直接访问它。

3.SP寄存器

ARMv8体系结构支持4个异常等级,每一个异常等级都有一个专门的SP寄存器SP_ELn ,如处理器运行在EL1时选择SP_EL1寄存器作为SP寄存器

  • SP_EL0:EL0下的SP寄存器。
  • SP_EL1:EL1下的SP寄存器。
  • SP_EL2:EL2下的SP寄存器。
  • SP_EL3:EL3下的SP寄存器。

当处理器运行在比EL0高的异常等级时,处理器可以访问如下寄存器。

  • 当前异常等级对应的SP寄存器SP_ELn
  • EL0对应的SP寄存器SP_EL0可以当作一个临时寄存器,如Linux内核使用该寄存器存放进程中task_struct数据结构的指针。

当处理器运行在EL0时,它只能访问SP_EL0,而不能访问其他高级的SP寄存器。

4.备份程序状态寄存器

当我们运行一个异常处理程序时,处理器的备份程序会保存到备份程序状态寄存器(Saved Program Status Register,SPSR)里。当异常将要发生时,处理器会把PSTATE寄存器的值暂时保存到SPSR里;当异常处理完成并返回时,再把SPSR的值恢复到PSTATE寄存器。SPSR的格式如图1.5所示。SPSR的重要字段如表1.4所示。

▲图1.5 SPSR的格式表1.4 SPSR的重要字段

5.ELR

ELR存放了异常返回地址。

6.CurrentEL寄存器

该寄存器表示PSTATE寄存器中的EL字段,其中保存了当前异常等级。使用MRS指令可以读取当前异常等级。

  • 0:表示EL0。
  • 1:表示EL1。
  • 2:表示EL2。
  • 3:表示EL3。

7.DAIF寄存器

该寄存器表示PSTATE寄存器中的{DAIF }字段。

8.SPSel寄存器

该寄存器表示PSTATE寄存器中的SP字段,用于在SP_EL0和SP_ELn 中选择SP寄存器。

9.PAN寄存器

PAN寄存器表示PSTATE寄存器中的PAN(Privileged Access Never,特权禁止访问)字段。可以通过MSR和MRS指令来设置PAN寄存器。当内核态拥有访问用户态内存或者执行用户态程序的能力时,攻击者就可以利用漏洞轻松地执行用户的恶意程序。为了修复这个漏洞,在ARMv8.1中新增了PAN特性,防止内核态恶意访问用户态内存。如果内核态需要访问用户态内存,那么需要主动调用内核提供的接口,例如copy_from_user()或者copy_from_user()函数。

PAN寄存器的值如下。

  • 0:表示在内核态可以访问用户态内存。
  • 1:表示在内核态访问用户态内存会触发一个访问权限异常。

10.UAO寄存器

该寄存器表示PSTATE寄存器中的UAO(User Access Override,用户访问覆盖)字段。我们可以通过MSR和MRS指令设置UAO寄存器。UAO为1表示在EL1和EL2执行这非特权指令(例如LDTR、STTR)的效果与特权指令(例如LDR、STR)是一样的。

11.NZCV寄存器

该寄存器表示PSTATE寄存器中的{NZCV }字段。

3.4 系统寄存器

除上面介绍的通用寄存器和特殊寄存器之外,ARMv8体系结构还定义了很多的系统寄存器,通过访问和设置这些系统寄存器来完成对处理器不同的功能配置。在ARMv7体系结构中,我们需要通过访问CP15协处理器来间接访问这些系统寄存器,而在ARMv8体系结构中没有协处理器,可直接访问系统寄存器。ARMv8体系结构支持如下7类系统寄存器:

  • 通用系统控制寄存器;
  • 调试寄存器;
  • 性能监控寄存器;
  • 活动监控寄存器;
  • 统计扩展寄存器;
  • RAS寄存器;
  • 通用定时器寄存器。

系统寄存器支持不同的异常等级的访问,通常系统寄存器会使用“Reg_ELn ”的方式来表示。

  • Reg_EL1:处理器处于EL1、EL2以及EL3时可以访问该寄存器。
  • Reg_EL2:处理器处于EL2和EL3时可以访问该寄存器。
  • 大部分系统寄存器不支持处理器处于EL0时访问,但也有一些例外,如CTR_EL0。

程序可以通过MSR和MRS指令访问系统寄存器。

mrs X0, TTBR0_EL1    //把TTBR0_EL1的值复制到X0寄存器
msr TTBR0_EL1, X0    //把X0寄存器的值复制到TTBR0_EL1

4 Cortex-A72处理器介绍

基于ARMv8体系结构设计的处理器内核有很多,例如常见的Cortex-A53、Cortex-A55、Cortex-A72、Cortex-A77以及Cortex-A78等。本书的实验环境采用树莓派4B开发板,内置了4个Cortex-A72处理器内核,因此我们重点介绍Cortex-A72处理器内核。

Cortex-A72是2015年发布的一个高性能处理器内核。它最多可以支持4个内核,内置L1和L2高速缓存,如图1.6所示。

Cortex-A72处理器支持如下特性。

采用ARMv8体系结构规范来设计,兼容ARMv8.0协议。 超标量处理器设计,支持乱序执行的流水线。 基于分支目标缓冲区(BTB)和全局历史缓冲区(GHB)的动态分支预测,返回栈缓冲器以及间接预测器。 支持48个表项的全相连指令TLB,可以支持4 KB、64 KB以及1 MB大小的页面。 支持32个表项的全相连数据TLB,可以支持4 KB、64 KB以及1 MB大小的页面。 每个处理器内核支持4路组相连的L2 TLB。 48 KB的L1指令高速缓存以及32 KB的L1数据高速缓存。 可配置大小的L2高速缓存,可以配置为512 KB、1 MB、2 MB以及4 MB大小。 基于AMBA4总线协议的ACE(AXI Coherency Extension)或者CHI(CoherentHubInterface)。 支持PMUv3体系结构的性能监视单元。 支持多处理器调试的CTI(Cross Trigger Interface)。 支持GIC(可选)。 支持多电源域(power domain)的电源管理。

▲图1.6 Cortex-A72处理器内部体系结构## 1.指令预取单元

指令预取单元用来从L1指令高速缓存中获取指令,并在每个周期向指令译码单元最多发送3条指令。它支持动态和静态分支预测。指令预取单元包括如下功能。

  • L1指令高速缓存是一个48 KB大小、3路组相连的高速缓存,每个缓存行的大小为64字节。
  • 支持48个表项的全相连指令TLB,可以支持4 KB、64 KB以及1 MB大小的页面。
  • 带有分支目标缓冲器的2级动态预测器,用于快速生成目标。
  • 支持静态分支预测。
  • 支持间接预测。
  • 返回栈缓冲器。

2.指令译码单元

指令译码单元对以下指令集进行译码:

  • A32指令集;
  • T32指令集;
  • A64指令集。

指令译码单元会执行寄存器重命名,通过消除写后写(WAW)和读后写(WAR)的冲突来实现乱序执行。

3.指令分派单元

指令分派单元控制译码后的指令何时被分派到执行管道以及返回的结果何时终止。它包括以下部分:

  • ARM核心通用寄存器;
  • SIMD和浮点寄存器集;
  • AArch32 CP15和AArch64系统寄存器。

4.加载/存储单元

加载/存储单元(LSU)执行加载和存储指令,包含L1数据存储系统。另外,它还处理来自L2内存子系统的一致性等服务请求。加载/存储单元的特性如下。

  • 具有32 KB的L1数据高速缓存,两路组相连,缓存行大小为64字节。
  • 支持32个表项的全相连数据TLB,可以支持4 KB、64 KB以及1 MB大小的页面。
  • 支持自动硬件预取器,生成针对L1数据高速缓存和L2缓存的预取。

5.L1内存子系统

L1内存子系统包括指令内存系统和数据内存系统。

L1指令内存系统包括如下特性。

  • 具有48 KB的指令高速缓存,3路组相连映射。
  • 缓存行的大小为64字节。
  • 支持物理索引物理标记(PIPT)。
  • 高速缓存行的替换算法为LRU(Least Recently Used)算法。

L1数据内存系统包括如下特性。

  • 具有32 KB的数据高速缓存,两路组相连映射。
  • 缓存行的大小为64字节。
  • 支持物理索引物理标记。
  • 对于普通内存,支持乱序发射、预测以及非阻塞的加载请求访问;对于设备内存,支持非预测以及非阻塞的加载请求访问。
  • 高速缓存行的替换算法为LRU算法。
  • 支持硬件预取。

6.MMU

MMU用来实现虚拟地址到物理地址的转换。在AArch64状态下支持长描述符的页表格式,支持不同的页面粒度,例如4 KB、16 KB以及64 KB页面。

MMU包括以下部分:

  • 48表项的全相连的L1指令TLB;
  • 32表项的全相连的L1数据TLB;
  • 4路组相连的L2 TLB;

TLB不仅支持8位或者16位的ASID,还支持VMID(用于虚拟化)。

7.L2内存子系统

L2内存子系统不仅负责处理每个处理器内核的L1指令和数据高速缓存未命中的情况,还通过ACE或者CHI连接到内存系统。其特性如下。

  • 可配置L2高速缓存的大小,大小可以是512 KB、1 MB、2 MB、4 MB。
  • 缓存行大小为64字节。
  • 支持物理索引物理标记。
  • 具有16路组相连高速缓存。
  • 缓存一致性监听控制单元(Snoop Control Unit,SCU)。
  • 具有可配置的128位宽的ACE或者CHI。
  • 具有可选的128位宽的ACP接口。
  • 支持硬件预取。

5 ARMv9体系结构介绍

2021年ARM公司发布ARMv9体系结构。ARMv9体系结构在兼容ARMv8体系结构的基础上加入了一些新的特性,其中:

  • ARMv9.0兼容ARMv8.5体系结构;
  • ARMv9.1兼容ARMv8.6体系结构;
  • ARMv9.2兼容ARMv8.7体系结构。

ARMv9体系结构新加入的特性包括:

  • 全新的可伸缩矢量扩展(Scalable Vector Extension version 2,SVE2)计算;
  • 机密计算体系结构(Confidential Compute Architecture,CCA),基于硬件提供的安全环境来保护用户敏感数据;
  • 分支记录缓冲区扩展(Branch Record Buffer Extension,BRBE),它以低成本的方式捕获控制路径历史的分支记录缓冲区; 内嵌跟踪扩展(Embedded Trace Extension,ETE)以及跟踪缓冲区扩展(Trace Buffer Extension,TRBE),用于增强对ARMv9处理器内核的调试和跟踪功能;
  • 事务内存扩展(Transactional Memory Extension,TME)。

另外,ARMv9体系结构对AArch32执行环境的支持发生了变化。在EL0中,ARM64体系结构对AArch32状态的支持是可选的,取决于芯片设计;而在EL1/EL2/EL3中,ARM64体系结构将不再提供对AArch32状态的支持。

本文摘自:ARM64体系结构编程与实践

原文作者:极致Linux内核

原文地址:https://zhuanlan.zhihu.com/p/577979125(版权归原文作者所有,侵权联系删除

回复

举报 使用道具

全部回复
暂无回帖,快来参与回复吧
主题 1545
回复 0
粉丝 2
扫码获取每晚技术直播链接
快速回复 返回顶部 返回列表