baron · 3月19日 · 四川

09-LearnTheArchitecture-MemoryManagement

快速连接

👉👉👉【精选】ARMv8/ARMv9架构入门到精通-目录 👈👈👈


 title=

1 Overview

本文介绍了 Armv8-A 中的内存转换,这是内存管理的关键。 它解释了虚拟地址如何转换为物理地址、转换表格式以及软件如何管理Translation Lookaside Buffers (TLB)。

这对于开发低级代码(例如引导代码或驱动程序)的任何人都很有用。 它与编写代码以设置或管理内存管理单元 (MMU) 的任何人都特别相关。

2 What is memory management?

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

2.1. Why is memory management needed?

应用处理器旨在运行丰富的操作系统,例如 Linux,并支持虚拟内存系统。 在处理器上执行的软件只能看到虚拟地址,处理器将其转换为物理地址。 这些物理地址呈现给内存系统并指向内存中的实际物理位置。

3 Virtual and physical addresses

使用虚拟地址的好处是它允许管理软件,例如操作系统 (OS),控制呈现给软件的内存视图。 操作系统可以控制哪些内存是可见的、该内存可见的虚拟地址以及允许对该内存进行哪些访问。 这允许操作系统沙盒应用程序(对另一个应用程序隐藏一个应用程序的资源)并提供对底层硬件的抽象。

使用虚拟地址的一个好处是,操作系统可以将多个碎片化的内存物理区域作为单个、连续的虚拟地址空间呈现给应用程序。

虚拟地址也有利于软件开发人员,他们在编写应用程序时不会知道系统的确切内存地址。 使用虚拟地址,软件开发人员无需关心物理内存。 应用程序知道由操作系统和硬件共同完成地址转换。

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

虚拟地址通过映射转换为物理地址。 虚拟地址和物理地址之间的映射存储在转换表(有时称为页表)中,如下图所示:
在这里插入图片描述
Translation tables在内存中并由软件管理,通常是操作系统或管理程序。 翻译表不是静态的,可以随着软件需求的变化而更新。 这会更改虚拟地址和物理地址之间的映射。

4 The Memory Management Unit (MMU)

内存管理单元 (MMU) 执行地址翻译。MMU 包含以下内容:

  • The table walk unit : 它从内存中读取页表,并完成地址转换
  • Translation Lookaside Buffers (TLBs) : 缓存,相当于cache

软件看到的所有内存地址都是虚拟的。 这些内存地址被传递到 MMU,它检查最近使用的缓存转换的 TLB。 如果 MMU 没有找到最近缓存的翻译,表遍历单元从内存中读取适当的一个或多个表条目,如下所示:
在这里插入图片描述
在进行内存访问之前,必须将虚拟地址转换为物理地址(因为我们必须知道我们正在访问哪个物理内存位置)。 这种转换需要也适用于缓存数据,因为在 Armv6 和更高版本的处理器上,数据缓存使用物理地址(物理标记的地址)存储数据。 因此,必须先转换地址,然后才能完成缓存查找。

注意:架构是一种行为规范。 缓存必须表现得就像它们被物理标记一样。 一个实现可能会做一些不同的事情,只要这不是软件可见的。

4.1. Table entry

Translation tables 的工作原理是将虚拟地址空间划分为大小相等的块,并在表中为每个块提供一个entry。

Translation tables 中的entry 0 提供block 0 的映射,entry 1 提供block 1 的映射,依此类推。 每个条目都包含相应物理内存块的地址以及访问物理地址时要使用的属性。
在这里插入图片描述

4.2. Multilevel translation

在单级查找中,虚拟地址空间被分成大小相等的块。 在实践中,使用了表的层次结构。

第一个表(Level 1 表)将虚拟地址空间划分为大块。 该表中的每个条目都可以指向一个相等大小的物理内存块,也可以指向另一个表,该表将该块细分为更小的块。 我们称这种类型的表为“多级表”。 在这里我们可以看到一个具有三个级别的多级表的示例:
在这里插入图片描述
在 Armv8-A 中,最大级别数为 4 (扯淡!! 这里是错误的,看看就好),级别编号为 0 到 3。这种多级方法允许描述更大的块和更小的块。 大小块的特点如下:

  • 大块需要比小块更少的读取级别来翻译。 此外,在 TLB 中缓存大块的效率更高。 --这个特点好好理解,就很不错嘛
  • 小块为软件提供了对内存分配的细粒度控制。 但是,在 TLB 中缓存小块的效率较低。 缓存效率较低,因为小块需要通过级别多次读取才能进行转换。

为了管理这种权衡,操作系统必须平衡使用大型映射的效率与使用较小映射以获得最佳性能的灵活性

注意:处理器在开始查表时不知道翻译的大小。 处理器通过执行 table walk 计算出正在转换的块的大小。

5 Address spaces in Armv8-A

Armv8-A中有几个独立的虚拟地址空间。 此图显示了这些虚拟地址空间:
在这里插入图片描述
图中展示了三个虚拟地址空间:

  • NS.EL0 and NS.EL1 (Non-secure EL0/EL1).
  • NS.EL2 (Non-secure EL2).
  • EL3.

这些虚拟地址空间中的每一个都是独立的,并且有自己的设置和表。 我们经常将这些设置和表格称为“translation regimes”。 Secure EL0、Secure EL1 和 Secure EL2 也有虚拟地址空间,但图中未显示。
(注:Armv8.4-A 中添加了对 Secure EL2 的支持)

因为有多个虚拟地址空间,所以指定一个地址所在的地址空间很重要。例如NS.EL2:0x8000指的是Non-secure EL2虚拟地址空间中的地址0x8000。

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

在虚拟化中,我们将操作系统控制的一组转换称为stage 1。stage 1 表将虚拟地址转换为中间物理地址 (IPA)。 在stage 1 ,操作系统认为 IPA 是物理地址空间。 然而,管理程序控制stage 2转换。stage 转换将 IPA 转换为物理地址。 此图显示了两组翻译的工作原理:
在这里插入图片描述
虽然在 table format上有一些细微的差别,但 Stage 1 和 Stage 2 翻译的过程通常是相同的。

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

5.1. Address sizes

Armv8-A 是 64 位架构,但这并不意味着所有地址都是 64 位

5.1.1 Size of virtual addresses

虚拟地址以 64 位格式存储。 因此,加载指令 (LDR) 和存储指令 (STR) 中的地址始终在 X 寄存器中指定。 但是,并非 X 寄存器中的所有地址都是有效的。 下图展示了 AArch64 中虚拟地址空间的布局:
在这里插入图片描述
EL0/EL1 虚拟地址空间有两个区域:内核空间和应用程序空间。 这两个区域显示在图的左侧,内核空间在顶部,应用程序空间(标记为“用户空间”)在地址空间的底部。 内核空间和用户空间有单独的转换表,这意味着它们的映射可以分开。

注意:如果您将 HCR_EL2.E2H 设置为 1,则会启用主机操作系统在 EL2 中运行,而主机操作系统的应用程序在 EL0 中运行的配置。 在这种情况下,EL2 也有upper 和 lower region。

每个region是多大,是根据虚拟地址有效位决定的,即由TCG_EL1.TxSZ配置的
在这里插入图片描述
注意:所有 Armv8-A 实现都支持 48 位虚拟地址。 对 52 位虚拟地址的支持是可选的,由 ID_AA64MMFR2_EL1 获取。

5.1.2 Size of physical addresses

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

注意:在 Armv8.0-A 中,物理地址的最大大小为 48 位。 这在 Armv8.2-A 中扩展到 52 位

5.1.3 Size of intermediate physical addresses

如果在转换表条目中指定的输出地址大于实现的最大值,则内存管理单元 (MMU) 将生成异常作为地址大小错误。

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

5.2. Address Space Identifiers - Tagging translations with the owning process

许多现代操作系统的所有应用程序似乎都从同一地址区域运行,这就是我们所描述的用户空间。实际上,不同的应用程序需要不同的映射。例如,这意味着 VA 0x8000 的转换取决于当前正在运行的应用程序。

理想情况下,我们希望不同应用程序的翻译在翻译后备缓冲区 (TLB) 中共存,以防止需要在上下文切换时使 TLB 失效。但是处理器如何知道要使用哪个版本的 VA 0x8000 转换呢?在 Armv8-A 中,答案是地址空间标识符 (ASID)。

对于 EL0/EL1 虚拟地址空间,可以使用转换表条目的属性字段中的 nG 位将转换标记为全局 (G) 或非全局 (nG)。例如,内核映射是全局转换,应用程序映射是非全局转换。全局翻译适用于当前正在运行的任何应用程序。非全局翻译仅适用于特定应用程序。

非全局映射在 TLB 中使用 ASID 进行标记。在 TLB 查找中,将 TLB 条目中的 ASID 与当前选择的 ASID 进行比较。如果它们不匹配,则不使用 TLB 条目。该图显示了内核空间中没有 ASID 标签的全局映射和用户空间中带有 ASID 标签的非全局映射:
在这里插入图片描述
该图显示允许多个应用程序的 TLB 条目在缓存中共存,ASID 决定使用哪个条目。 ASID 存储在两个 TTBRn_EL1 寄存器之一中。 通常 TTBR0_EL1 用于用户空间。 因此,单个寄存器更新可以更改 ASID 和它指向的转换表。

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

5.3. Virtual Machine Identifiers - Tagging translations with the owning VM

EL0/EL1 转换也可以使用虚拟机标识符 (VMID) 进行标记。 VMID 允许来自不同 VM 的转换在缓存中共存。 这类似于 ASID 为来自不同应用程序的翻译工作的方式。 实际上,这意味着某些翻译将同时使用 VMID 和 ASID 进行标记,并且两者必须匹配才能使用 TLB 条目。

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

5.4. Common not Private

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

对于 Armv8.0-A,答案是它们不一定意味着相同的事情。不要求软件以相同的方式跨多个处理器使用给定的 ASID。例如,ASID 5 可能由一个处理器上的计算器和另一个处理器上的 Web 浏览器使用。这意味着由一个处理器创建的 TLB 条目不能被另一个处理器使用。

在实践中,软件不太可能跨处理器使用不同的 ASID。软件在给定系统中的所有处理器上以相同方式使用 ASID 和 VMID 更为常见。因此,Armv8.2-A 在转换表基址寄存器 (TTBR) 中引入了公共非私有 (CnP) 位。当 CnP 位被设置时,软件承诺在所有处理器上以相同的方式使用 ASID 和 VMID,这允许另一个处理器使用由一个处理器创建的 TLB 条目。

注意:我们一直在谈论处理器,但是,从技术上讲,我们应该使用术语处理元素 (PE)。 PE 是任何实现 Arm 架构的机器的通用术语。这一点很重要,因为在处理器之间共享 TLB 会很困难,因为存在微体系结构的原因。但是在多线程处理器中,每个硬件线程都是一个 PE,共享 TLB 条目更为可取。

6 Controlling address translation

6.1. Translation table format

在这里,我们可以看到翻译表entry有4种不同格式(<font color=red size=5>扯淡!!其实就3种,block descriptor和page descriptor其实是一种</font>):
在这里插入图片描述
注意:为清楚起见,此图未指定位字段的宽度。您可以在 Arm 架构参考手册 Armv8 中找到此信息,适用于 Armv8-A 架构配置文件:VMSAv8-64 转换表格式描述符。

每个entry是 64 位,底部的两位确定entry的类型。

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

注意:0-2 级表描述符的编码与级别 3 的页描述符相同。这种编码允许“递归表”,它们指向自身。这很有用,因为它可以轻松计算特定页表entry的虚拟地址,以便可以更新

7 Translation granule

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

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

处理器支持的粒度是实现定义的,由 ID_AA64MMFR0_EL1 报告。 所有 Arm Cortex-A 处理器都支持 4KB 和 64KB。 选择的粒度是最新级别表中可以描述的最小块。 也可以描述更大的块。 下表显示了基于所选粒度的每个级别表的不同块大小:
在这里插入图片描述
(星号*) 使用 52 位地址有限制。 当所选颗粒为4KB或16KB时,最大虚拟地址区域大小为48位。 同样,输出物理地址限制为 48 位。 只有在使用64KB颗粒时,才可以使用完整的52位。

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

7.1. The starting level of address translation

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

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

我们以 4KB 颗粒为例。 此图显示了用于为 4KB 颗粒索引不同级别表的位:
在这里插入图片描述

7.2. Registers that control address translation

地址转换由系统寄存器的组合控制:
(1)、SCTLR_ELx

  • M - Enable Memory Management Unit (MMU).
  • C - Enable for data and unified caches.
  • EE - Endianness of translation table walks.

(2)、TTBR0_ELx and TTBR1_ELx

  • BADDR - Physical address (PA) (or intermediate physical address, IPA, for EL0/EL1) of start of translation table.
  • ASID - The Address Space Identifier for Non-Global translations.

(3)、TCR_ELx

  • PS/IPS - Size of PA or IPA space, the maximum output addresssize.
  • TnSZ - Size of address space covered by table.
  • TGn - Granule size.
  • SH/IRGN/ORGN - Cacheability and shareability to be used by MMU table walks.
  • TBIn - Disabling of table walks to a specific table.

(4)、MAIR_ELx

  • Attr - Controls the Type and cacheability in Stage 1 tables.
7.3. MMU disabled

当 MMU 在一个转换阶段被禁用时,所有地址都是一一映射的。 平面映射意味着输入和输出地址相同。

8 Translation Lookaside Buffer maintenance

The Translation Lookaside Buffers (TLBs) 缓存最近使用的翻译。这种缓存允许后续查找重用翻译,而无需重新读取表。

注意:TLB 是翻译缓存,而不是翻译表缓存。区别很微妙。几个寄存器字段控制如何解释转换表entry。 TLB entry中的内容是在遍历表时给定配置的转换表entry的解释。在 Arm 架构参考手册 (Arm ARM) 中,此类寄存器字段被描述为“允许缓存在 TLB 中”。

如果更改转换表entry或影响条目解释方式的控件,则需要使 TLB 中受影响的条目无效。如果您不使这些条目无效,则处理器可能会继续使用旧的翻译。

处理器不允许导致以下任何错误的缓存到tlb,:

  • A translation fault (unmapped address).
  • An address size fault (address outside of range).
  • An access flag fault

因此,首次映射地址时无需发出 TLB 无效。 但是,如果您想执行以下任何操作,则确实需要发出 TLB 无效:

  • Unmap an address
    Take an address that was previously valid or mapped and mark it as faulting
  • Change the mapping of an address
    Change the output address or any of the attributes. For example, change an address from read-only to read-write permissions.
  • Change the way the tables are interpreted
    This is less common. But, for example, if the granule size was changed, then the interpretation of the tables also changes. Therefore, a TLB invalidate would be necessary.
8.1. Format of a TLB operation

TLBI 指令用于使 TLB 中的条目无效。 该指令的语法是:
TLBI <type><level>{IS|OS} {, <xt>}

9 Address translation instructions

地址转换 (AT) 指令允许软件查询特定地址的转换。 产生的转换(包括属性)被写入物理地址寄存器 PAR_EL1。

AT 指令的语法允许您指定要使用的翻译机制。 例如,EL2 可以查询 EL0/EL1 转换机制。 但是,EL1 不能使用 AT 指令查询 EL2 转换机制,因为这是对特权的破坏。


关注"Arm精选"公众号,备注进ARM交流讨论区。
图片1.png

推荐阅读
关注数
9467
内容数
212
以易懂、渐进、有序的方式,深入探讨ARMv8/ARMv9架构的核心概念。我们将从基础知识开始,逐步深入,覆盖最新的架构,不再纠缠于过时技术。本系列内容包含但不限于ARM基础、SOC芯片基础、Trustzone、gic、异常和中断、AMBA、Cache、MMU等内容,并将持续更新。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息