提到MMU就要提到一个概念,虚拟地址(Virtual Address)。前面的文章中反复提到过虚拟地址的概念。
使用虚拟地址的好处是它允许管理软件,例如操作系统(OS)来控制呈现给软件的内存视图。操作系统可以控制哪些内存是可见的,哪些内存是可见的,哪些访问是允许的。应用程序知道它是由操作系统和硬件协同工作来执行地址转换的。实际上,每个应用程序都可以使用自己的一组虚拟地址,这些地址将映射到物理系统中的不同位置。当操作系统在不同的应用程序之间切换时,它会重新编程映射。这意味着当前应用程序的虚拟地址将映射到内存中正确的物理位置。
使用虚拟地址的另一个好处是操作系统可以将内存的多个碎片物理区域作为单个、连续的虚拟地址空间呈现给应用程序。虚拟地址也有利于软件开发人员,他们在编写应用程序时不知道系统的确切内存地址。使用虚拟地址,软件开发人员不需要关心物理内存。
虚拟地址和物理地址之间的映射存储在转换表(transla
tion tables)中:
转换表在内存中,由软件(通常是操作系统或管理程序)管理。地址转换表是动态的,可以根据软件的需要进行更新。负责虚拟地址到物理地址转换的部件就是MMU。MMU由两部分组成:
表遍历单元(Table Walk Unit),包含从内存中读取地址转换表的逻辑。
TLB(Translation Lookaside Buffer),缓存最近使用的地址转换。
软件发出的所有内存地址都是虚拟的。这些内存地址被传递给MMU,MMU检查TLB中最近使用的缓存地址转换。如果MMU没有找到最近缓存的地址转换,表遍历单元(TWU)将从内存中读取相应的表条目。
转换表的工作原理是将虚拟地址空间划分为大小相等的块,并在每个块的表中提供一个条目。
当转换发生时,由软件发出的虚拟地址将一分为二。在下图中被标记为“which entry”的高位告诉您要查找哪个块条目,并将它们用作表的索引。此输入块包含虚拟地址的物理地址。低阶位在图中被标记为“offset in blocks”,是该块中的偏移量,不会因转换而改变。
多级查找更为复杂。以下图为例,第一个表将虚拟地址空间划分为大的块。这个表中的每个条目可以指向一个大小相等的物理内存块,也可以指向另一个将块细分为更小块的表。我们称这种类型的表为“多级表”。在ARMv8-A中,最多可以支持四级查找。多级查找为虚拟化技术提供了支持。
这种多级查找方法允许描述较大的内存块和较小的内存块。大/小块体的特点如下:
大内存块比小内存块需要更少的读取级别。另外,大内存块在TLB中的缓存效率更高。
小内存块为软件提供了对内存分配的细粒度控制。但是,小内存块在TLB中的缓存效率较低。缓存效率较低,因为小内存块需要多次读取级别才能转换。
处理器在开始表查找时不知道转换的大小。处理器通过执行表遍历计算出正在转换的块的大小。
在ARMv8-A中有三个独立的虚拟地址空间,分别是:
NS.EL0 and NS.EL1 (Non-secure EL0/EL1).
NS.EL2 (Non-secure EL2).
EL3.
在虚拟化中,我们将操作系统控制的地址转换集称为stage 1。Stage 1表将虚拟地址转换为中间物理地址(IPA)。在Stage 1,操作系统认为IPA是物理地址空间。然而,hypervisor控制第二组转换,我们称之为Stage 2。Stage2 将IPA转换为物理地址。前面介绍ARM虚拟化的文章中有介绍,不再赘述。
Armv8-A是一个64位体系结构,但这并不意味着所有的地址都是64位的。虚拟地址以64位格式存储。因此,LDR指令和STR指令中的地址始终在X寄存器中指定。但是,并非X寄存器中的所有地址都有效。在Armv8.0-A中,物理地址的最多是48位。在Armv8.2-A中扩展到52位。
许多现代操作系统的所有应用程序似乎都运行在同一个地址区域,这就是我们所说的用户空间。实际上,不同的应用程序需要不同的映射。
理想情况下,我们希望不同应用程序的地址转换在TLB中共存,以防止TLB在上下文切换时失效。但是处理器如何知道要使用哪个版本的地址转换呢?在Armv8-A中,答案是地址空间标识符(Address SpaceIdentifiers,ASID)。
对于EL0/EL1虚拟地址空间,可以使用转换表项的属性字段中的nG位将转换标记为全局(G)或非全局(nG)。例如,内核映射是全局转换,而应用程序映射是非全局转换。全局转换应用于当前正在运行的应用程序。非全局地址转换仅适用于特定应用程序。
非全局映射在TLB中用ASID标记。在TLB查找中,TLB条目中的ASID将与当前选定的ASID进行比较。如果它们不匹配,则不使用TLB条目。下图显示了内核空间中没有ASID标记的全局映射,以及具有ASID标记的用户空间中的非全局映射。该图显示,允许多个应用程序的TLB条目在缓存中共存,ASID决定使用哪个条目。
EL0/EL1转换也可以使用虚拟机标识符(Virtual MachineIdentifier,VMID)进行标记。VMID允许来自不同VM的转换在缓存中共存。这与ASID处理来自不同应用程序的地址转换的方式类似。在实践中,这意味着一些转换将同时使用VMID和ASID进行标记,并且两者都必须与要使用的TLB条目相匹配。
如果一个系统包含多个处理器,那么在一个处理器上使用的ASID和VMID在其他处理器上的含义是否相同?对于Armv8.0-A来说,答案是它们的意思并不一定相同。软件不需要以相同的方式在多个处理器间使用给定的ASID。例如,ASID 5可能被一个处理器上的计算器和另一个处理器上的web浏览器使用。这意味着一个处理器创建的TLB条目不能被另一个处理器使用。
实际上,软件不太可能在处理器之间使用不同的ASID。软件在给定系统中的所有处理器上以相同的方式使用ASID和VMID更为常见。因此,Armv8.2-A在转换表基寄存器(TTBR)中引入了公共非私有(Common not Private,CnP)位。当设置了CnP位时,软件承诺在所有处理器上以相同的方式使用ASID和VMID,这允许一个处理器创建的TLB条目被另一个处理器使用。
转化粒度是可以描述的最小的存储块。Armv8-A支持三种不同的粒度:4KB、16KB和64KB。处理器支持的颗粒大小由实现定义,并由ID_AA64MMFR0_EL1报告。所有Arm Cortex-A处理器支持4KB和64KB。
当MMU被禁用时,所有地址都是平面映射的。也就是说,输入和输出地址是相同的。