【笔记】Armv8-A 内存管理

0. 目录

1. 概述

本指南介绍:

  1. 虚拟地址如何转换为物理地址
  2. 转换表格式
  3. 如何管理TLBs

对以下可能有所帮助:

  1. 如boot编程或驱动编程
  2. 需要设置或管理MMU

将能够学会:

  1. 虚拟地址如何转换为物理地址
  2. 命名不同的地址空间
  3. 解释地址空间怎么映射到地址翻译的各个阶段
  4. 什么时候软件必须维护TLB,以及维护TLB的命令的语法

2. 什么是内存管理

内存管理描述如何控制系统中对内存的访问。每次操作系统或应用程序访问内存时,硬件都会执行内存管理。内存管理是一种将内存区域动态分配给应用程序的方法。

2.1 为什么需要内存管理

在处理器上执行的软件只能看到虚拟地址,而处理器会把虚拟地址转换成物理地址。这些物理地址被呈现给内存系统并指向内存中的实际物理位置。

3.虚拟地址和物理地址

使用虚拟地址的好处:

  1. OS可以控制提供给用户进程的内存视图,控制访问权限,实现沙箱型和硬件的抽象。
  2. 用多片物理地址实现连续的虚拟地址空间
  3. 软件开发人员不用考虑物理地址

每个应用程序都可以使用自己的一组虚拟地址,这些地址将被映射到物理系统中的不同位置。当操作系统在不同的应用程序之间切换时,它会重新编程映射。这意味着当前应用程序的虚拟地址将映射到内存中正确的物理位置。

虚拟地址通过映射转换为物理地址。虚拟地址和物理地址之间的映射存储在转换表(有时称为页表)中,由OS或者hypervisor来管理。如下图所示:

image-20210106142353110

4.内存管理单元The Memory Management Unit (MMU)

地址转换由MMU来执行,包括两个部分:

  1. table walk unit:包含从内存中读取translation tables的逻辑
  2. TLBs:缓存最近使用的表项

地址翻译过程如下图所示:用户进程给出虚拟地址->MMU查找TLB,命中则给出PA,否则->table walk unit到内存中读取相应的表项

image-20210106143401383

即便是访问cache也需要物理地址。从Armv6开始,数据cache存储数据也使用物理地址的标记。

注意:架构是行为规范,实现可以不一样,只要不被软件察觉。

4.1 Table entry表项

转换表的工作原理是将虚拟地址空间分成大小相等的块,并在每个块中提供一个表项。

每个条目包含一个对应的物理内存块的地址,以及访问物理地址时要使用的属性。

image-20210106144259735

4.2 查表 Table lookup

地址转换时,虚拟地址会被一分为二:

image-20210106155456546

这是一个单级查找。红框圈出的部分为虚拟地址的高位,指示应该查找哪一块表项,绿色圈出的低位用来表示在该块中的偏移位置。

4.3 多级翻译

第一个表(一级表)将虚拟地址空间划分为大的块。该表中的每个条目可以指向一个大小相等的物理内存块,也可以指向另一个表,该表将该块划分为更小的块。我们称这种类型的表为“多级表”。这里我们可以看到一个多级表的例子,它有三个层次:

image-20210106155928287

在Armv8-A中,级别的最大数目是4,级别编号为0到3。这种多层方法允许同时描述较大的块和较小的块。大块和小块的特点如下:

  • larger blocks:相比smaller blocks,它只要更少层级的读取翻译就可以得到对应的物理地址。同时,在TLB中的缓存效率也更高
  • small block:可以提供对内存分配fine-grain的控制。但是在TLB中的缓存效率较低,因为需要更多层级的读取翻译才可以得到物理地址

OS必须做好large block和small block之间的平衡,以达到效率和物理内存使用灵活上的平衡,从而达到最优的性能。

Note:在这种情况下,处理器并不知道此次翻译对应的block大小,它需要通过table walk的方式来得到。

5. Armv8-A中的地址空间

在Armv8-A中有几个独立的虚拟地址空间。下图显示了这些虚拟地址空间:

image-20210106163327118

三种虚拟地址空间:

  1. NS.EL0 和 NS.EL1 (非安全 EL0/EL1).
  2. NS.EL2 (非安全 EL2)
  3. EL3

这三种地址空间都是独立的。除此之外还有安全状态EL0、EL1、EL2的地址空间,只是没有放在这张图中。

该图还显示了来自非安全EL0和非安全EL1的虚拟地址经过两组翻译。这些表支持虚拟化,并允许管理程序虚拟化虚拟机(VM)所看到的物理内存视图。

在虚拟化中,我们把由客户机操作系统控制的转换称为阶段1。阶段1表将虚拟地址转换为中间物理地址(IPAs)。在阶段1中,操作系统认为ipa是物理地址空间。但是,hypervisor控制第二组转换,我们称之为阶段2。第二套翻译将ipa翻译为物理地址。下图展示了这两组翻译的工作原理:

image-20210106163309765

虽然在表项属性上有一些小的差异,但阶段1和阶段2的翻译过程通常是相同的。

注意:在Arm中,我们在许多示例中使用地址0x8000。0x8000也是与Arm链接器armlink链接的默认地址。地址来自早期的微型计算机,BBC Micro Model B,它的ROM地址是0x8000。BBC Micro Model B是由一家名为Acorn的公司建造的,该公司开发了Acorn RISC Machine (ARM),后来成为ARM。

5.1 地址大小

Armv8-A是64位体系结构,但这并不意味着所有地址都是64位的。

5.1.1 虚拟地址大小

虚拟地址以64位格式存储。因此,load指令(LDR)和store指令(STR)中的地址总是在X寄存器中指定的。然而,并不是X寄存器中的所有地址都是有效的。

下图显示了AArch64虚拟地址空间的布局:

image-20210106163852642

EL0/EL1虚拟地址空间有两个区域:内核空间和应用程序空间。这两个区域显示在图的左侧,内核空间在高地址区域,应用程序空间(标记为“用户空间”)在地址空间的低地址区域。内核空间和用户空间有独立的转换表,这意味着它们的映射可以保持独立。

在所有其他异常级别的地址空间的低地址有一个区域。该区域显示在图表的右侧。

注意:如果你设置了HCR_EL2.E2H为1,,那么主机操作系统将运行在EL2中,主机操作系统的应用程序运行在EL0中。在这个场景中,EL2也有一个高地址区域和一个低地址区域。

地址空间的每个区域的大小最多为2^52字节。然而,每个区域都可以独立地缩小到更小的尺寸。TCR_ELx寄存器中的TnSZ字段控制虚拟地址空间的大小。例如,下图显示了TCR_EL1控制EL0/EL1虚拟地址空间:

image-20210106164418113

虚拟地址空间大小的地址计算如下:

​ 虚拟地址空间大小的字节数=2^(64-TCR_ELX.TnSZ)

注意:所有的Armv8-A实现都支持48位虚拟地址。52位虚拟地址支持是可选的,由ID_AA64MMFR2_EL1报告。在编写本文时,没有一个Arm Cortex-A处理器支持52位虚拟地址。

5.1.2 物理地址的大小

物理地址的大小由实现方所定义,最大可达52位。ID_AA64MMFR0_EL1寄存器报告这个大小。对于Arm Cortex-A处理器,这通常是40位或44位。

5.1.3 中间地址IPA大小

如果在一个转换表项中指定的输出地址大于所实现的最大地址,内存管理单元(MMU)将产生一个地址大小错误的异常。

IPA空间的大小可以像配置虚拟地址空间一样配置。VTCR_EL2.T0SZ控制大小。可配置的最大大小与处理器支持的物理地址大小相同。这意味着您不能配置比支持的物理地址空间更大的IPA空间。

5.2 地址空间标识符-进程的tag翻译

许多现代操作系统的所有应用程序似乎都从相同的地址区域运行,这就是我们所描述的用户空间。实际上,不同的应用程序需要不同的映射。例如,这意味着VA 0x8000的转换取决于当前正在运行的应用程序。理想化的来讲,我们希望不同的进程所对应的TLB是互不冲突的,这就不会导致TLB的的刷新以及上下文切换。解决这个问题的手段就是使用Address Space Identifiers (ASIDs)。

对于EL0/EL1的虚拟地址空间,地址转换可以通过translations table entry的属性字段中的nG位被标记为Global (G) 或是 Non-Global (nG)。举个例子来说,内核映射是全局地址转换,应用则是非全局转换。全局转换应用于当前正在运行的应用程序,非全局转换应用于当前的应用。

非全局映射使用TLB中的ASID进行标记。在一次TLB查询中,如果TLB表项中的ASID和当前所选的ASID将会进行比较。如果不相匹配,那么TLB的表项不会使用。下图显示了内核空间的全局映射(不使用ASID)和用户空间的非全局映射(使用ASID)。

image-20210106191754833

从图中可以看出来,多个应用的TLB条目可以共存,通过ASID进行区分。

ASID存储在两个TTBRn_EL1寄存器中的一个中。通常TTBR0_EL1用于用户空间。因此,单个寄存器更新可以同时更改ASID和它所指向的转换表。

注意:当HCR_EL2.E2H==1时,ASID标记在EL2中也可用。

5.3 虚拟机标识符——VM的tag转换

EL0/EL1地址转换也可以使用虚拟机标识符(VMID)进行标记。VMIDs允许来自不同vm的转换共存于缓存中。这与ASIDs处理来自不同应用程序的地址转换的方式类似。在实践中,这意味着一些地址转换将同时使用VMID和ASID进行标记,并且这两个标记都必须匹配要使用的TLB表项。

注意:当安全状态支持虚拟化时,EL0/EL1转换总是使用VMID标记——即使没有启用阶段2转换。这意味着,如果您正在编写初始化代码而没有使用管理程序,那么在设置阶段1 MMU之前设置一个已知的VMID值是很重要的。

5.4 通用而非私有

如果一个系统包含多个处理器,那么在一个处理器上使用的asid和VMIDs在其他处理器上是否具有相同的含义?

对Armv8.0-A 版本,答案是否定的。没有要求对于多个processor之间要求ASID和VMID含义一致,即相同的ASID在不同的processor可能表示不同的进程。也即意味着,一个processor创建的TLB不能被另一个processor使用。

在实践中,软件不太可能在处理器之间以不同的方式使用ASIDs。对于软件来说,在给定系统中的所有处理器上以相同的方式使用ASIDs和VMIDs更为常见。因此,Armv8.2-A在转换表基寄存器(TTBR)中引入了通用非私有(CnP)位。当设置了CnP位后,软件承诺在所有处理器上以相同的方式使用ASIDs和VMIDs,这就允许一个处理器创建的TLB条目被另一个处理器使用。

6.控制地址转换

6.1 转换表格式

image-20210106192950987

每一个表项都是64位。低2位决定了这个表项的类型。

注意,有些表项仅在特定级别有效。表的最大级别数是4,这就是为什么没有第3级(或第4级)表的表描述符。类似地,0级也没有块描述符或页面描述符。因为0级表项覆盖了很大的虚拟地址空间,所以允许块是没有意义的。

注意:0-2级表描述符的编码与3级页描述符的编码相同。这种编码允许“递归表”,它指向自己。这很有用,因为它使计算特定页表条目的虚拟地址变得很容易,从而可以更新它。(??????)

7.翻译粒度

翻译粒度是可以描述的最小的内存块。没有更小的东西可以描述,只有更大的块,它们是颗粒的倍数。

Armv8-A支持三种不同的颗粒大小:4KB、16KB和64KB。

处理器支持的颗粒大小是由实现定义的,由ID_AA64MMFR0_EL1报告。所有的Arm Cortex-A处理器都支持4KB和64KB。所选的颗粒是可以在最新的level表中描述的最小块。更大的块也可以被描述。这个表显示了基于所选颗粒的不同级别表的块大小:

image-20210106194050010

注意:TCR_EL1有两个单独的字段,它们控制内核空间和用户空间虚拟地址范围的颗粒大小。这些字段称为TG1(用于内核空间)和TG0(用于用户空间)。对于程序员来说,一个潜在的问题是这两个字段有不同的编码。

7.1 地址转换的起始层级

由粒度和虚拟地址空间共同控制地址转换的起始层级。

上一个表总结了表中各级每个粒度的块大小(单个表项覆盖的虚拟地址范围的大小)。从块大小,您可以计算出虚拟地址的哪些位被用于索引每个级别的表。

以4KB粒度为例,这张表展示了用于索引不同级别的表项的位。

image-20210106195044167

这张表说明的是,当选择4KB的粒度时,各个表项等级所利用的地址的比特位。假如你设置TCR_ELx.T0SZ为32,那么虚拟地址空间就只有64−TOSZ=3264−TOSZ=32位,那么对应上表,你就可以发现,已经不需要level0了,直接从level1开始就可以完全表示整个虚拟地址空间了。而如果虚拟地址空间只有30位,那么只需要从level2开始就可以完整表示整个地址空间了。也即,虚拟地址空间越小,那么所需的level也就越小。

7.2 控制地址转换的寄存器

地址翻译是通过如下这些寄存器来配合控制的:

  • SCTLR_ELx
    • M - 使能MMU
    • C - 使能数据和unified cache
    • EE - 遍历转换表的字节序
  • TTBR0_ELx and TTBR1_ELx
    • BADDR - 转换表开始的物理地址(PA)(或中间物理地址,IPA,表示EL0/EL1)。
    • ASID -用于非全局转换的地址空间标识符.
  • TCR_ELx
    • PS/IPS - PA或IPA空间大小,最大输出地址大小.
    • TnSZ - 表所覆盖的地址空间大小.
    • TGn - 粒度大小.
    • SH/IRGN/ORGN - MMU表遍历使用的可缓存性和可共享性.
    • TBIn - Disabling of table walks to a specific table.
  • MAIR_ELx
    • Attr - 控制阶段1表中的类型和可缓存性.

7.3 禁用MMU

如果MMU被禁用的话,那么所有地址都是flat-mapped,即输入等于输出。

8. TLB维护

注意:TLB中缓存的是 translations 而不是 translation tables。区别在于:TLB存储的是虚拟地址到硬件地址的直接映射关系,即下一次读取到的是直接的物理地址。

如果更改了一个转换表条目,或者影响表项解释方式的控件,那么就需要使TLB中受影响的表项无效。如果您没有使这些表项无效,那么处理器可能会继续使用旧的转换。

这些情况下,TLB不会对其进行缓存:

  • 转换错误(未映射的地址)。
  • 地址大小错误(地址不在范围内)。
  • 访问标志错误

因此,在第一次映射一个地址时,您不需要发出一个TLB invalidate。然而,如果你想做以下任何一件事,你需要发出一个TLB invalidate:

  • 取消映射:将一个地址标记为错误
  • 改变地址的映射:更改输出地址或其属性。例如,将地址权限从只读改为读写。
  • 更改表的解释方式:这种情况不太常见。但是,例如,如果改变了颗粒大小,那么对表的解释也会改变。因此,TLB invalidate是必要的。

8.1 TLB操作的格式

TLBI指令用于使tlb中的表项失效。这条指令的语法是:

TLBI <type><level>{IS|OS} {, <xt>}

其中:

  • <type> 哪些条目无效化
    • All - All entries
    • VA - Entry matching VA and ASID in -Xt
    • VAA - Entry matching VA in Xt, for any ASID
    • ASID - Any entry matching the ASID in Xt
    • and many more
  • <level> 所操作的地址空间.
    • E1 = EL0/1 virtual address space
    • E2 = EL2 virtual address space
    • E3 = EL3 virtual address space
  • <IS|OS> 操作是内部可共享的还是外部可共享的.
    • 当IS被添加到操作中时,它被广播到内部共享域中的其他核中。
    • 当OS被添加到操作中时,它被广播到外部可共享域的其他内核(在Armv8.4-A中添加)。
    • <Xt>Which address or ASID to operate on.
    • Only used for operations by address or ASID.

例如,考虑一个OS正在更新其内核转换表中的一个表项。一个典型的TLB无效序列是这样的:

STR X1, [X5] 		// 写入转换表表项
DSB ISH 			// 屏蔽指令 – not covered in this guide 
TLBI VAAE1IS , X0 	// 使EL0/1中由X0指定的VA无效
					// 所有asid的虚拟地址空间
DSB ISH 			// 屏蔽指令 – not covered in this guide 
ISB    				// 在这个处理器上同步上下文

9.地址转换指令

地址转换(AT)指令让软件为特定的地址查询翻译结果。结果的转换(包括属性)被写入Physical Address Register PAR_EL1中。

AT指令的语法允许您指定使用哪种翻译机制。例如,EL2可以查询EL0/EL1的翻译方式。然而,EL1不能使用AT指令查询EL2的翻译制度,因为这是违反特权的。

如果请求的翻译会导致错误,则不会生成异常。相反,将生成的故障类型记录在PAR_EL1中。

参考

https://developer.arm.com/architectures/learn-the-architecture/memory-management

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值