Bootstrap

内存管理单元——MMU

一、基本概念介绍
MMU是Memory Management Unit的缩写,中文名是内存管理单元,有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线仲裁以及存储体切换(bank switching,尤其是在8位的系统上)。
内存管理单元(MMU)的一个重要功能是使系统能够运行多个任务,作为独立程序在自己的私有虚拟内存空间中运行。它们不需要了解系统的物理内存映射,即硬件实际使用的地址,也不需要了解可能同时执行的其他程序。


mmu开启以后会有以下特点:
1.多个程序独立运行
2.虚拟地址是连续的(物理内存可以有碎片)
3.允许操作系统管理内存
下图显示的系统说明了内存的虚拟和物理视图。单个系统中的不同处理器和设备可能具有不同的虚拟地址映射和物理地址映射。操作系统编写程序,使MMU在这两个内存视图之间进行转换


要做到这一点,虚拟内存系统中的硬件必须提供地址转换,即将处理器发出的虚拟地址转换为主内存中的物理地址。MMU使用虚拟地址中最重要的位来索引转换表中的条目,并确定正在访问哪个块。MMU将代码和数据的虚拟地址转换为实际系统中的物理地址。该转换将在硬件中自动执行,并且对应用程序是透明的。除了地址转换之外,MMU还可以控制每个内存区域的内存访问权限、内存顺序和缓存策略。
MMU对执行的任务或应用程序可以不了解系统的物理内存映射,也可以不了解同时运行的其他程序。每个程序可以使用相同的虚拟内存地址空间。即使物理内存是碎片化的,还可以使用一个连续的虚拟内存映射。此虚拟地址空间与系统中内存的实际物理映射分开的。应用程序被编写、编译和链接,以在虚拟内存空间中运行。


二、TLB--Translation Lookaside Buffer
如上图所示,TLB是MMU中最近访问的页面翻译的缓存。对于处理器执行的每个内存访问,MMU将检查转换是否缓存在TLB中。如果所请求的地址转换在TLB中导致命中,则该地址的翻译立即可用。TLB本质是一块高速缓存。数据cache缓存地址(虚拟地址或者物理地址)和数据。TLB缓存虚拟地址和其映射的物理地址。TLB根据虚拟地址查找cache,它没得选,只能根据虚拟地址查找。所以TLB是一个虚拟高速缓存。
每个TLB entry通常不仅包含物理地址和虚拟地址,还包含诸如内存类型、缓存策略、访问权限、地址空间ID(ASID)和虚拟机ID(VMID)等属性。如果TLB不包含处理器发出的虚拟地址的有效转换,称为TLB Miss,则将执行外部转换页表查找。MMU内的专用硬件使它能够读取内存中的转换表。然后,如果翻译页表没有导致页面故障,则可以将新加载的翻译缓存在TLB中,以便进行后续的重用。简单概括一下就是:硬件存在TLB后,虚拟地址到物理地址的转换过程发生了变化。虚拟地址首先发往TLB确认是否命中cache,如果cache hit直接可以得到物理地址。否则,一级一级查找页表获取物理地址。并将虚拟地址和物理地址的映射关系缓存到TLB中。

如果操作系统修改了可能已经缓存在TLB中的转换的entry,那么操作系统就有责任使这些未更新的TLB entry invaild。当执行A64代码时,有一个TLBI,它是一个TLB无效的指令:

TLBI <type><level>{IS} {, <Xt>}

TLB可以保存固定数量的entry。可以通过由转换页表遍历引起的外部内存访问次数和获得高TLB命中率来获得最佳性能。ARMv8-A体系结构提供了一个被称为连续块entry的特性,以有效地利用TLB空间。转换表每个entry都包含一个连续的位。当设置时,这个位向TLB发出信号,表明它可以缓存一个覆盖多个块转换的单个entry。查找可以索引到连续块所覆盖的地址范围中的任何位置。因此,TLB可以为已定义的地址范围缓存一个entry从而可以在TLB中存储更大范围的虚拟地址。
处理器不允许导致以下任何错误的缓存到tlb:
A translation fault (unmapped address).
An address size fault (address outside of range).
An access flag fault
Translation tables 的工作原理是将虚拟地址空间划分为大小相等的块,并在表中为每个块提供一个 entry。 Translation tables 中的entry 0 提供block 0 的映射,entry 1 提供block 1 的映射,依此类推。 每个entry都包含相应物理内存块的地址以及访问物理地址时要使用的属性。
三、内核和应用程序虚拟地址空间的分离
操作系统通常有许多应用程序或任务并发运行。每一个任务都有自己独特的转换表集,作为在一个任务和另一个任务之间切换上下文过程的一部分,内核从一个任务切换到另一个任务。然而,大部分内存系统只由内核使用,并且固定了虚拟到物理地址映射,其中转换表条目很少更改。ARMv8体系结构提供了许多特性来有效地处理这个需求。
映射表基地址在转换表基寄存器(TTBR0_EL1)和(TTBR1_EL1)中指定。当VA的上几位均为0时,选择TTBR0指向的转换表。当VA的上几位都设置为1时,选择TTBR1。您可以启用VA标记来排除检查中的前8位。来自获取指令或数据访问的处理器的虚拟地址是64位。但是,必须在一个48位物理地址内存映射中映射前面定义的两个区域。EL2和EL3有一个TTBR0,但没有TTBR1。这意味着:

  • 如果EL2正在使用AArch64,那么它只能使用在0x0到0x0000FFFF_FFFFFFFF范围内的虚拟地址。
  • 如果EL3正在使用AArch64,那么它只能使用在0x0到0x0000FFFF_FFFFFFFF范围内的虚拟地址。

下图显示了如何将内核空间映射到高地址内存区域,以及与每个应用程序关联的虚拟地址空间映射到低地址内存区域。然而,这两个都映射到一个比它们小得多的物理地址空间。


TCR_EL1在EL1和EL0处的其他内存管理功能。下图显示了那些控制地址范围和颗粒大小的字段。


中部物理地址大小(IPS)字段控制最大输出地址大小。如果转换指定的输出地址超出此范围,则访问出现故障,000=32位物理地址,101=48位。两位平移颗粒(TG)TG1和TG0字段分别给出了内核或用户空间的颗粒大小,即00=4KB、01=16KB、11=64KB。对于第一次查找的映射表级别。完整的映射过程可能需要三到四级的映射表。不需要实现所有等级的映射表。第一级的查找实际上是由颗粒大小和TCR_ELn.TxSZ字段决定的。可以通过TTBR0_EL1和TTBR1_EL1单独配置。
四、将虚拟地址转换为物理地址
当处理器发出64位虚拟地址进行指令获取或数据访问时,MMU硬件将虚拟地址转换为相应的物理地址。对于一个虚拟地址,前16位[63:47]必须全部为0或1,否则该地址将引发故障。通过使用低位来给出选定部分内的偏移量,以便MMU将来自块表entry的物理地址位与来自原始地址的低位组合起来,以生成最终地址。该体系结构还支持带标记的地址。这是忽略地址中最重要的8位的地方(被视为不是地址的一部分)。这意味着该比特可以用于其他东西,例如,记录有关指针的信息。


如上图所示:在一个简单的地址转换中,只涉及到一级页表的查找。假设我们使用的是一个具有42位虚拟地址的64KB颗粒。MMU翻译一个虚拟地址如下:
1.如果VA[63:42] = 1,则TTBR1用于第一页表的基本地址。当VA[63:42] = 0时,TTBR0用于第一页表的基本地址。
2.该页表包含8192(2^13)个64位的页表条目,并使用VA[41:29]进行索引。MMU从表中读取相关的第2页表条目。
3.MMU会检查页表条目的有效性,以及是否允许所请求的内存访问。假设它是有效的,则允许进行内存访问。
4.在上图中,页表条目引用了一个512MB的页面(它是一个块描述符)。
5.bit[47:29]取自这个页表条目,并形成物理地址的bit[47:29]。
6.因为我们有一个512MB的页面,所以VA的位被取[28:0]来形成PA。
7. 返回完整的PA[47:0],以及页面表条目中的其他信息。
在实际过程中,这样一个简单的翻译过程严重限制了划分地址空间的精细程度。一级表条目还可以指向二级页表,而不是只使用这个一级翻译页表。
通过这种方式,一个操作系统可以进一步将大量的虚拟内存划分为更小的页面。对于二级页表,第一级描述符包含第二级页表的物理基本地址。与处理器请求的虚拟地址相对应的物理地址可以在第二级描述符中找到。下图显示了一个64位的翻译示例,从第一阶段第二级一个64位颗粒对普通64KB页面。

每个二级页表都与一个或多个一级条目相关。可以有多个一级描述符指向同一个二级表,这意味着可以将多个虚拟地址别名到同一个物理地址。
上图描述了一种有两级查找的情况。同样,这也假设了一个64KB的颗粒和42位的虚拟地址空间。

1.如果VA[63:42] = 1,则TTBR1用于第一页表的基本地址。当VA[63:42] = 0时,TTBR0用于第一页表的基本地址。
2.该页表包含8192(2^13)个64位的页表条目,并通过VA[41:29]进行索引。MMU从表中读取相关的第2页表条目。
3.MMU检查第2级页表条目的有效性,以及是否允许所请求的内存访问。以确定它是否有效和是否允许内存访问。
4. 在上图中,二级页表条目是指三级页表的地址(它是一个表描述符)。
5.bit[47:16]来自第二级页表条目,并形成第3级页表的基地址。
6.VA的[28:16]位用于索引第3级页表条目。MMU从表中读取相关的三级页表条目。
7.MMU检查第3级页表条目的有效性,以及是否允许所请求的内存访问。以确定它是否有效和是否允许内存访问。
8.在上图中,第3级页表条目是指一个64KB的页面(它是一个页面描述符)。
9. Bit[47:16]取自三级页面表条目,用于形成PA[47:16]。
10.因为有一个64KB的页面,所以VA[15:0]形成了PA[15:0]。
4.1 安全和非安全地址
理论上,安全的和非安全的物理地址空间是相互独立的,并且是并行存在的。一个系统可以被设计成有两个完全独立的内存系统。然而,大多数实际系统将安全和不安全视为访问控制的属性。正常(非安全)世界只能访问非安全的物理地址空间。安全世界可以同时访问这两个物理地址空间。这也是通过转换表来控制的。


这样做会影响高速缓存的一致性。例如,从技术上讲,因为安全0x8000和非安全0x8000是不同的物理地址,因此它们可以同时在缓存中。在安全内存和非安全内存位于不同位置的系统中,不会有任何问题。它们更有可能是在同一个位置。理想情况下,内存系统将阻止对非安全内存的安全访问和对安全内存的非安全访问。实际上,大多数操作程序只阻止对安全内存的非安全访问。同样,这意味着可能会在两次缓存中对安全和不安全区域使用相同的物理内存,这会导致程序错误。为了避免这种情况,安全世界必须始终使用对非安全内存的非安全访问。
4.2 配置和启用MMU
写入控制MMU的系统寄存器是发生上下文变化的事件,它们之间没有排序要求。

MSR TTBR0_EL1, X0 // Set TTBR0 
MSR TTBR1_EL1, X1 // Set TTBR1 
MSR TCR_EL1, X2 // Set TCR 
ISB // The ISB forces these changes to be seen before / 
// the MMU is enabled. 
MRS X0, SCTLR_EL1 // Read System Control Register configuration data 
ORR X0, X0, #1 // Set [M] bit and enable the MMU. 
MSR SCTLR_EL1, X0 // Write System Control Register configuration data 
ISB // The ISB forces these changes to be seen by the / 
// next instruction


4.3 禁用内存管理单元时的操作
当阶段1 MMU被禁用时,对于非安全的EL0和EL1阶段将在HCR_EL2.DC BIT被置位以后会启用data cache,默认内存类型为正常不可共享、内部可回写读写分配、外部可回写读写分配。
五、ARMv8-A的翻译表
ARMv8-A体系结构支持三种不同的翻译表格式:

  • ARMv8-AArch64长描述符格式。
  • ARMv7-一种长描述符格式,如ARMv7-A架构的大型物理地址扩展(LPAE),可以在ARM Cortex-A15处理器中找到。
  • ARMv7-短描述符格式。

在AArch32状态下,可以使用现有的ARMv7-一个长和短的描述符格式来运行现有的guest操作系统和现有的应用程序代码,而无需修改。ARMv7-A短描述符只能在EL0和EL1第1翻译阶段使用。因此,它们不能被hypervisors或安全监控器代码使用。
在AArch64执行状态下,始终使用ARMv8-长描述符格式。这非常类似于ARMv7——一种具有大型物理地址扩展名的长描述符格式。它使用了相同的64位长描述符格式,但也做了一些更改。它引入了一个新的第0级表索引,它使用与第1级表相同的描述符格式。此外,还增加了对多达48位的输入和输出地址的支持。输入的虚拟地址现在来自于一个64位的寄存器。但是,由于体系结构不支持完全64位寻址,地址的63:48位必须是相同的,即所有0或所有1,或者前8位可以用于VA标记。
AArch64支持三种不同的翻译颗粒。它们在翻译表的最低级定义块大小,并控制正在使用的翻译表的大小。较大的颗粒大小可以减少所需的页表级别的数量,这可能成为使用虚拟机管理程序提供虚拟化的系统中的一个重要考虑因素。
支持的颗粒大小分别为4KB、16KB和64KB,并通过实现定义了支持这三个颗粒中的哪一种。创建页面表的代码能够读取系统寄存器ID_AA64MMFR0_EL1,以找出支持的大小。Cortex-A53处理器支持以上三种尺寸,但一些处理器的早期版本不是这样,比如Cortex-A57,它不支持16K颗粒尺寸。可以为翻译控制寄存器(TCR_EL1)中的每个翻译表配置大小。


5.1 AArch64描述符格式
可以在从0到3的所有级别中使用描述符格式。0级描述符只能输出1级表的地址。第3级描述符不能指向另一个表,并且只能输出块地址。因此,第3级的表格的格式略有不同。下图显示表描述符类型由entry的bit 1:0标识,并且可以引用:

  • 下一级别表的地址,在这种情况下,内存可以进一步细分为更小的块。
  • 一个可变大小的内存块的地址。
  • 页表条目,可以标记为故障或无效。


5.2 颗粒大小对翻译表的影响
这里有三种不同的颗粒大小可能会影响所需的翻译表的数量和大小:

  1. 4KB

当使用4kB的颗粒大小时,硬件可以使用4级查找过程。48位的地址每个级别有9个地址位,即每个512个条目,最后12位在4kB内的一个字节直接来自原始地址。
在512条目L0页表为虚拟地址的47:39位。每个页表条目都跨越了512 GB的范围,并指向一个L1表。在该512个L1页表entry中,第38:30位被用作索引来选择一个条目,每个条目点指向一个1GB块或一个L2表。位29:21索引到一个512条目L2表,每个条目指向一个2MB的块或下一个表级别。在最后一层,位20:12索引到一个512条目L2表,每个条目指向一个4kB块。

  1. 16KB

当使用16kB的颗粒大小时,硬件可以使用4级查找过程。48位地址每个级别有11个地址位(除了L0页表),即每个2048个条目,最后14位选择4kB内的一个字节直接来自原始地址。级别为L0的页表只包含两个条目。虚拟地址的位47从两个条目L0表中选择一个描述符。每个表条目都跨越128 TB范围,并指向一个L1表。在该2048个条目L1表中,第46:36位被用作一个索引来选择一个条目,每个条目指向一个L2表。bit 35:25的每个条目指向一个32 MB块或下一个表级别。在最后的翻译阶段,位24:14的每个条目指向一个16kB的块。

  1. 64KB

当使用64kB的颗粒大小时,硬件可以使用3级查找过程。L1页表只包含64个条目。虚拟地址的位47:42从64条目L1表中选择一个描述符。每个页表条目都跨越4TB范围,并指向一个L2表。在该8192条目L2表中,位41:29被用作索引来选择一个条目,每个条目都指向一个512 MB块。在最后的翻译阶段,位28:16索引到一个8192条目L3表,每个条目指向一个64kB的块。


5.3 高速缓存配置
MMU使用转换表和转换寄存器来控制哪些内存位置是可缓存的。MMU控制缓存策略、内存属性和访问权限,并提供虚拟到物理地址的转换。


5.4 缓存策略
MMU转换表还为内存系统中的每个块定义了高速缓存策略。定义为normal的内存区域可以标记为可缓存或不可缓存。翻译页表表条目中的bit [4:2]位指的是内存属性间接寄存器(MAIR)中的八个内存属性编码中的一个。内存属性编码指定访问该内存时使用的缓存策略。这些都是对处理器的提示,它定义了在一个特定的实现中是否支持所有的缓存策略,以及哪些缓存数据被视为是一致的。内存区域可以根据其可共享性属性来定义。
六、转换表配置
除了在TLB中存储单个转换外,您还可以将MMU配置为转换表存储在缓存中。这通常比从外部内存读取表更快地访问表。TCR_EL1有其他可以控制它的字段。附加字段指定了TTBR0和TTBR1的转换表的可缓存性和可共享性。相关字段称为SH0/1可共享性、IRGN0/1内部可存性和ORGN0/1外部可存性。下图显示了可缓存性的设置方法:


对应的内存可共享性表与转换表相关联。对于设备或强排序的内存区域,将忽略该值:


在TCR_EL1中指定的属性必须与为存储转换表的虚拟内存区域指定的属性相同。缓存转换表是正常的行为.对于转换控制寄存器,TCR_ELn有一个名为顶部字节忽略(TBI)的附加字段,该字段提供了带标记的寻址支持。通用寄存器有64位宽,但一个地址中高16位必须全部是0x FFFF或0x0000。任何试图使用不同的数据都会触发故障。
当启用标记寻址支持时,处理器将忽略虚拟地址的前8位,即[63:56]。它在内部设置了bit[55]来签名扩展地址为64位格式。一个虚拟地址的前8位可以用来传递数据。这些bit被忽略为寻址和转换故障。TCR_EL1对EL0和EL1都有单独的启用位。ARM没有为标记地址指定或强制指定特定的用途。
七、在EL2和EL3处的转换
对ARMv8-A体系结构的虚拟化扩展引入了翻译的第二个阶段。当系统中存在一个虚拟机管理程序时,可能会存在一个或多个操作系统。这些操作继续使用前面所述的TTBRn_EL1,MMU操作似乎没有改变。
系统管理程序必须在两个阶段的进程中执行一些额外的转换步骤,以便在不同的来宾操作系统之间共享物理内存系统。在第一阶段,虚拟地址(VA)被转换为中间物理地址(IPA)。这通常是在操作系统的控制下进行的。第二阶段由管理程序控制,然后将IPA转换为最终物理地址(PA)。管理程序和安全监视器还具有它们自己的代码和数据的阶段1转换表集,它们直接执行从VA到PA的映射。


阶段2的转换,将中间物理地址转换为物理地址,使用了在管理程序控制下的额外一组表。这些必须通过写入管理程序配置注册器HCR_EL2来显式启用。此过程仅适用于非安全的EL1/0访问。
此阶段2转换表的基地址在虚拟化转换表基寄存器VTTBR0_EL2中指定。它在内存的底部指定一个单个连续的地址空间。所支持的地址空间的大小将在虚拟化转换控制寄存器VTCR_EL2的TSZ[5:0]字段中指定。此寄存器的TG字段指定颗粒大小,而SL0字段控制表查找的第一级。任何超出定义地址范围的访问都会导致转换故障。


虚拟机监控程序EL2和安全监视器EL3都有自己的1级页表,它们可以直接从虚拟地址空间映射到物理地址空间。表基地址分别在TTBR0_EL2和TTBR0_EL3中指定,在内存底部启用一个可变大小的连续地址空间。TG字段指定颗粒大小,而SL0字段控制表查找的第一级。任何超出定义地址范围的访问都会导致转换故障。


安全监视器EL3有自己的专用转换表。表的基地址在TTBR0_EL3中指定,并通过TCR_EL3进行配置。转换表能够同时访问安全的和非安全的物理地址。TTBR0_EL3仅在安全监视器EL3模式下使用,而不是由受信任的内核本身使用。当向安全世界的转换完成后,受信任的内核将使用EL1转换,即TTBR0_EL1和TTBR1_EL1指向的转换表。由于这些寄存器不存储在AArch64中,因此安全监视器代码必须为安全世界配置新的表,并保存和恢复TTBR0_EL1和TTBR1_EL1的副本。TLB中的条目被标记为安全或不安全,因此当在安全和正常世界之间转换时,不需要进行TLB维护。
八、 访问权限
访问权限可通过转换表条目进行控制。访问权限控制区域是可读还是可写,或者两者都有,可以非特权访问可设置为EL0,特权访问设置为EL1、EL2和EL3,如下表所示。


操作系统内核运行在执行级别EL1中。它定义了转换表映射,它由内核本身和运行在EL0上的应用程序所使用。由于内核为非特权访问权限和应用程序指定不同的权限,因此需要区分非特权访问权限和特权访问权限指定不同的权限。在执行级别EL2运行的管理程序和安全监控器EL3有只供自己使用的转换方案,因此不需要在权限上进行特权和非特权分割。
另一种访问权限是可执行属性。块可以标记为可执行或不可执行属性(从不执行(XN))。您可以分别设置属性为非特权从不执行(UXN)和特权从不执行(PXN),并使用该属性来保护,例如,应用程序代码使用内核特权运行,或在非特权状态下尝试执行内核代码。设置这些属性可以防止处理器执行预测指令获取到内存位置,并确保预测指令获取不会意外地访问被这种访问干扰的位置,例如,先入先出(FIFO)页面替换队列。因此,设备区域必须始终标记为“永不执行”。


可以通过SCTLR寄存器来配置属性:

  • SCTLR_EL1.WXN在EL0处可写的区域被视为在EL0和EL1处的XN。在EL1处可写的区域被视为在EL1处的XN。
  • SCTLR_EL2和3.WXN.在ELn上可写的区域在ELn上被视为XN。

SCTLR_ELn位可以被缓存在一个TLB条目中。因此,更改SCTLR中的位可能不会影响tlb中已经存在的条目。当修改这些位时,一个TLB invalid,ISB sequence是必要的。
九、操作系统使用翻译表描述符
描述符中的另一个内存属性位,Access Flag(AF),指示何时首次使用块条目。

  • AF = 0:此块条目尚未被使用。
  • AF = 1:已使用此块条目。

操作系统使用访问标志位来跟踪正在使用的是哪些页面。软件管理标志。当首次创建页面时,其条目的AF设置为0。第一次通过代码访问页面时,如果AF为0,这将触发MMU故障。页面错误处理程序记录现在正在使用此页面,并在表条目中手动设置AF位。例如,Linux内核对ARM64上的PTE_AF使用[AF]位(AArch64上的Linux内核名称),它用于检查页面是否曾经被访问过。这将影响到一些内核内存管理的选择。例如,当一个页面必须耗尽内存时,不会替换正在主动使用的页面。
描述符的bit[58:55]被标记为保留位以供软件使用,并可用于在翻译表中记录特定操作系统的信息。例如,Linux内核使用其中一个位将条目标记为干净或脏。脏状态记录页面是否已被写入。如果页面后来被内存替换,一个干净的页面可以简单地丢弃,但一个脏的页面必须先保存其内容。


PXN, bit[53] :Privileged execute-never Contiguous, bit[52] : translation table entry 是连续的,可以存在一个TLB Entry中 DBM, bit[51] :Dirty Bit Modifier GP, bit[50] :for FEAT_BTI nT, bit[16] :for FEAT_BBM nG, bit[11] :缓存在TLB中的翻译是否使用ASID标识 AF, bit[10] : Access flag, AF=0后,第一次访问该页面时,会将该标志置为1. 即暗示第一次访问 SH, bits[9:8] :shareable属性 AP[2:1], bits[7:6] :Data Access Permissions bits, NS, bit[5] :Non-secure bit AttrIndx[2:0], bits[4:2] :指向MAIR系统寄存器,cache的缓存策略属性
十、安全性和MMU
ARMv8-A体系结构定义了两种安全状态,安全状态和不安全状态。它还定义了两个物理地址空间:安全的和不安全的,这样正常的世界只能访问非安全的物理地址空间。安全的世界可以同时访问安全的和非安全的物理地址空间。
在非安全状态下,将忽略转换表中的NS位和NSTable位。只能访问不安全的内存。在安全状态下,NS位和NSTable位控制虚拟地址是否转换为安全物理地址或非安全物理地址。您可以使用SCR_EL3.CIF,以防止在安全世界执行来自任何非安全物理地址的转换。此外,在安全的世界中,您可以使用SCR.CIF位来控制安全指令获取是否可以使非安全的物理内存。
十一、上下文切换
实现ARMv8-A体系结构的处理器通常用于运行复杂操作系统的系统,其中会并发运行许多应用程序或任务。每个进程在物理内存中都有自己独特的转换表。当应用程序启动时,操作系统会为它分配一组转换表条目,这些条目会将应用程序使用的代码和数据映射到物理内存中。随后,内核可以修改这些表,例如,可以在额外的空间中进行映射,并在应用程序不使用时被删除。
因此,在内存系统中可能存在多个任务。内核调度程序定期地将执行从一个任务转移到另一个任务。这被称为上下文切换,它要求内核保存与该进程相关联的所有执行状态,并恢复接下来要运行的进程的状态。内核还将转换表项切换到下一个要运行的进程。当前未运行的任务的内存完全不受正在运行的任务的影响。
确切需要保存和恢复的内容在不同的操作系统之间有所不同,但通常进程上下文切换包括保存或恢复以下部分内容:

  • 通用寄存器X0-X30。
  • 高级SIMD和浮点寄存器V0 - V31。
  • 状态寄存器。
  • TTBR0_EL1和TTBR0。
  • 线程进程ID(TPIDxxx)寄存器。
  • 地址空间ID(ASID)。

对于EL0和EL1,有两个转换表。TTBR0_EL1为虚拟地址空间的底部提供了转换,该空间通常是应用程序空间,而TTBR1_EL1覆盖了虚拟地址空间的顶部,通常是内核空间。这种拆分并不意味着所有的OS都是这么映射。
转换表条目包含一个非全局(nG)位。如果为特定的页面设置了nG位,则它与特定的任务或应用程序相关联。如果该位被标记为0,则该条目是全局的,并适用于所有任务。
对于非全局条目,当TLB更新并且条目标记为非全局标记时,除了正常转换外,TLB条目中还存储一个值。这个值被称为地址空间ID(ASID),它是操作系统分配给每个单独任务的一个数字。如果当前的ASID与存储在该条目中的ASID匹配,则后续的TLB查找才与该条目匹配。这表面允许标记为非全局状态但具有不同ASID值的特定页面存在多个有效的TLB条目。换句话说,当我们进行上下文切换时,我们并不一定需要刷新tlb。
在AArch64中,这个ASID值可以被指定为一个8位或16位的值,由TCR_EL1.As控制。作为位。当前的ASID值可以在TTBR0_EL1或TTBR1_EL1.TCR_EL1控制哪些TTBR持有ASID,但通常是TTBR0_EL1,它主要对应于应用程序空间。
此外,ARMv8-A体系结构还提供了供操作系统软件使用的线程ID寄存器。它们没有硬件意义,通常被线程库用作指向每个线程数据的基本指针。这通常被称为线程本地存储(TLS)。例如,pthreads库使用此特性,并包括以下寄存器:

  • 用户读取和写线程ID寄存器(TPIDR_EL0)。
  • 用户只读线程ID寄存器(TPIDRRO_EL0)。
  • 线程ID寄存器,只有特权访问(TPIDR_EL1)。

十二、具有用户权限的内核访问权限
有一些指令允许代码在EL1(例如,一个操作系统)上执行,以使用EL0或应用程序权限执行内存访问。例如,这可以用于删除系统调用提供的指针,并使操作系统检查是否只访问了应用程序可访问的数据。可以通过使用LDTR或STTR指令来实现。当在EL1执行时,这些指令执行加载或存储,就好像在EL0上执行一样。在所有其他异常级别上,LDTR和STTR的行为都类似于常规的LDR或STR指令。有通常的大小和有符号和无符号的变量作为正常的加载和存储指令,但有一个较小的偏移量和受限制的索引选项。
十三、内存属性

  • Normal类型:对该种类型的内存可以进行常见的读写操作或只读操作,系统中大部分内存都是这种类型;
  • Device类型:对该种类型的内存进行读写可能具有连带效应(side-effects,指对一个内存位置的读写操作会影响其它内存位置)或者从该种内存中的一个位置装载的值可能随着装载的次数而变化。通常内存映射外设(指使用访问内存的方法来访问的外设,举例:IIC、SPI、GIC等等)会采用这种内存类型。

内存属性Cacheability表示一个内存位置是否可以被分配到缓存中,这个内存属性有Non-cacheable、Write-Throuth Cacheable和Write-Back Cacheable三种选项,其含义为:

  • Non-cacheable:不使用缓存,直接更新内存;
  • Write-Throuth Cacheable:同时更新缓存和内存;
  • Write-Back Cacheable:先更新缓存,替换时将修改过的块写回内存。

官方文档的解释如下:
Shareability attribute (For Normal memory) • Inner Shareable, meaning it applies across the Inner Shareable shareability domain. • Outer Shareable, meaning it applies across both the Inner Shareable and the Outer Shareable shareability domains. • Non-shareable

;