1、概述

  本文档介绍了ARMv8-A架构内存管理的关键——内存地址转换,包括虚拟地址(VA)到物理地址(PA)的转换、页表(或称地址转换表)格式以及TLBs(Translation Lookaside Buffers)管理。

  对于任何进行底层bootloader或者驱动代码开发的人员来说,这部分内容都是非常实用的,尤其是对进行MMU(Memory Management Unit)编码的人员。

  本文档可以帮助你解到VA如何转换成PA的、如何识别不同的地址空间、地址转换时地址空间是如何映射的以及TLB相关的操作。

2、什么是内存管理?

  内存管理描述了如何访问系统内存。每次操作系统或者应用程序尝试访问内存时,都是硬件负责进行内存管理的,对于应用程序而言,内存管理是一种动态分配内存区域的方式。

2.1、为什么需要内存管理?

  因为操作系统和应用程序需要大量的内存来运行,同时,应用程序往往运行在虚拟地址空间,需要实际映射到物理地址空间。

3、虚拟地址和物理地址

  使用虚拟地址的一个好处是,操作系统可以控制应用程序的内存布局,操作系统决定虚拟地址是否可见、是否允许访问。这种机制允许操作系统采取沙箱机制管理(即应用程序之间的隔离)应用程序,同时实现了对硬件的抽象。

  还有一个好处是,物理内存上不连续的内存区域,在虚拟内存地址空间中可以是连续的。

  对于应用程序开发人员而言,他们不需要关心具体的物理内存地址是否可以访问。

  实际上,每一个应用程序都维护一个独立的虚拟内存地址空间,它们被映射到不同的物理内存区域。操作系统在进行应用程序切换时负责重构虚拟内存地址空间,这就意味着当前应用程序的虚拟地址总是映射到正确的物理地址。

  虚拟地址通过映射的方式转换为物理地址。虚拟地址和物理地址的映射关系保存在页表(page tables,或称translation tables地址转换表)中,如下图所示:

  页表保存在内存中,由操作系统或者hypervisor(虚拟化技术)管理。页表不是静态的,而是根据应用程序对内存的需求及时更新的,页表更新的同时,也改变了虚拟地址和物理地址的映射关系。

4、MMU

  MMU负责地址转换,包括:

  1)table walk unit,负责从内存中读取页表;

  2)TLBs,负责缓存最近使用的页表项;

  需要强调的是,应用程序发起的任何内存地址访问都是虚拟地址。虚拟地址被发送给MMU,MMU首先在TLBs中查找是否有对应的页表项,如果没有找到对应的页表项,那么table walk unit会从内存中读取合适的页表项(table entry)。

  访问物理内存之前,必须完成虚拟地址到物理地址的转换。对于访问缓存数据而言,同样需要提前完成VA-2-PA的转换,因为ARMv6以后的处理器都将缓存数据通过物理地址的方式(physically tagged)缓存,因此,必须在cache lookup之前完成VA-2-PA转换。ARM CPU包含数据缓存和指令缓存,可以理解为片内物理内存,各自拥有独立的物理地址段。

4.1、Table Entry 页表项

  虚拟地址空间被划分为以页(32位系统下页大小通常为4KB)为单位的内存页,每一个内存页在页表中占据一个页表项,即Table Entry。页表项和内存页是一一对应的,Entry 0对应block 0(0号内存页),Entry 1对应block 1,依此类推。每一个页表项包含对应的物理地址以及访问属性。

4.2、Table lookup 页表查找

  地址转换必然要涉及到页表查找,当发生地址转换时,虚拟地址被分为两部分:

  上图是一个一级页表(ARMv8硬件上支持4级页表,Linux内核默认使用3级页表)查找过程图。

  虚拟地址的上半部分——Which entry,用来指定页表项,该页表项中保存了虚拟地址对应的物理地址。

  虚拟地址的下半部分——Offset in block,表示页内偏移地址,在转换过程中保持不变。

4.3、Mutilevel translation 多级页表转换

  多级页表实际上是将虚拟内存地址空间划分为多个相同大小的页存大页,再将每个内存大页划分为多个相同大小的内存小页。

  ARMv8最大支持4级页表,编号0~3。

  使用多级页表的好处是,内存大页可以加速地址转换的效率,比如提高TLBs缓存的有效性;同时,内存小页有给应用程序提供了对虚拟内存地址空间的细粒化管理。但是与此同时,TLBs缓存内存小页的有效性就比较差。

  为了降低这种开销,操作系统需要在内存大页的效率和内存小页的映射之间进行权衡,决定最合适的页表层级。

5、ARMv8-A虚拟地址空间

  ARMv8-A架构有几个独立的虚拟地址空间,如下图所示:

  上图显示了三种虚拟地址空间:

  1)NS.EL0 and NS.EL1 (Non-secure EL0/EL1)

  2)NS.EL2 (Non-secure EL2)

  3)EL3

  每一种虚拟地址空间都是独立的,而且拥有各自的页表设置(页表层级和页表),我们通常称这种页表设置为——translation regimes。同样的,Secure EL0/EL1/EL2也有各自的虚拟地址空间,只不过上图没有展示出来。

5.1、地址大小

  ARMv8-A架构是64位架构,但是并不意味着其地址位宽为64位。

5.1.1 虚拟地址位宽

  虚拟地址以64位的格式保存,LDR和STR指令通常将地址保存在X寄存器中,但是这并不意味着X寄存器中所有的地址都是有效的。

  下图演示了AArch64架构虚拟地址空间布局:

  EL0/EL1的虚拟地址空间分为两部分——内核空间和用户空间,内核空间在高地址,用户空间在低地址。内核空间和用户空间各自维护相互独立的页表,这也意味着它们的地址映射也是相互独立的。

  ARMv8架构目前最大支持48位虚拟地址。

5.1.2、物理地址位宽

  物理地址位宽由芯片决定,最大支持52位。ID_AA64MMFR0_EL1寄存器记录了芯片支持的物理地址位宽。对于ARM Cortex-A系列处理器而言,通常为40位或者44位。

  ARMv8.0-A架构最大支持48位物理地址,ARM8.2-A架构最大支持52位物理地址。

5.1.3、合适的物理地址位宽 IPA

  如果你在页表项(页表项中记录的是物理地址)中指定一个超过芯片最大物理地址的地址,那么MMU会产生一个物理地址大小异常。

  IPA地址空间大小可以像虚拟地址空间一样构建。VTCR_EL2.TOSZ寄存器控制地址大小,理论上最大可以配置到和芯片支持的物理地址空间一样的大小。

5.2、地址空间标识 ASID

  许多现代的操作系统让所有的应用运行在同样的地址区域,这就是我们提到的用户地址空间。实际上,不同的应用需要不同的地址映射。比如,VA 0x8000实际转换的物理地址取决于当前正在运行的应用,即每个应用程序自己维护一个页表。

  理想状态下,我们希望不同的应用的页表项共存于TLBs中,防止上下文切换时TLB中没有当前应用(准确地讲应该是指进程)的页表项。但是处理器怎么知道不同应用的VA 0x8000对应的物理地址呢?在ARMv8-A架构中,答案是Address Space Identifier (ASIDs)。

   对于EL0/EL1虚拟地址空间,通过页表项属性字段的nG位标记页表为Global(G)或者Non-Global(nG)。比如,内核地址映射为全局页表,应用程序地址映射为非全局页表。不管当前执行的是哪个应用程序,全局页表都是生效的;非全局页表只有在特定应用执行时才生效。

  非全局页表项在TLBs中使用ASID标记。在进行TLB查找时,将当前选择的ASID与TLB页表项中的ASID进行比较。如果不匹配,则表示当前TLB页表项无效。下图显示了全局页表和局部页表,以及ASID标记:

  上图展示了不同应用的TLB页表项可以在缓存中共存,由ASID决定哪一个页表项生效。

  ASID保存在两个TTBRn_EL1寄存器之中,通常用户空间使用TTBR0_EL1寄存器。因此,TTBRn_EL1寄存器值的更新会同时更新ASID和当前生效的页表项。

  需要注意的是,当HCR_EL2.E2H置位时,ASID标记在EL2模式同样生效。

5.3、虚拟机标识 VMID

  通过VMID(Virtual Machine Identifier)允许不同的虚拟机页表共存于cache中,类似于ASID。

5.4、Common not Private (CnP)

  试想,在一个多处理器系统中,一个处理器上的ASIDs和VMIDs是否可以同样应用在其他处理器上呢?

  对于ARMv8.0-A架构而言,答案是完全没有必要。因为应用程序不需要ASID跨处理器生效。比如,ASID 5在A处理器上可能是计算机程序,在B处理器上是浏览器。这一点说明,一个处理器创建的TLB页表项不能用在其他处理器上,即每个处理器维护自己的页表。

  但是ARMv8.2-A架构在TTBR(Translation Table Base Register)寄存器中引入了Common not Private(CnP)位,通过设置CnP位,软件可以使ASIDs和VMIDs跨处理器生效,即允许一个处理器创建的页表项在另外一个处理器上同样生效。

6、地址转换控制

6.1、页表格式

  以下是集中页表项的格式:

  每一个页表项都是64位,最低两位表示页表层级。

  顶层页表没有Table描述符,底层页表没有Page描述符。

7、页大小 Translation Granule

  页是虚拟地址空间分配的最小单位。ARMv8-A架构支持4KB/16KB/64KB几种大小的页。

  ID_AA64MMFR0_EL1寄存器设置了芯片支持的页大小,所有ARM Cortex-A系列处理器都支持4KB和64KB页。

  4KB和16KB页最大支持48位虚拟地址,如果要支持52位虚拟地址,必须使用64KB页。

  TCR_EL1寄存器有两个字段分别控制内核空间和用户空间页大小。

7.2、虚拟地址的各级页表序号

  以4KB页为例。

7.2、控制地址转换的寄存器

  SCTLR_ELx

    M - 使能MMU

    C - 使能数据缓存和unified缓存(所有处理器共用的缓存)

    EE - 页表字节序

  TTBR0_ELx和TTBR1_ELx

    BADDR - 起始页表项的物理地址

    ASID - 局部页表的地址空间标识

  TCR_ELx

    PS/IPS - 最大物理地址位宽

    TnSZ - 页表覆盖的地址空间大小

    TGn - 页大小

    SH/IRGN/ORGN - MMU页表遍历是的缓存性和共享性

    TBIn - 禁止页表遍历到指定的页表项

  MAIR_ELx

    Attr - 一级页表的类型和缓存性

7.3、关闭MMU

  当MMU禁用时,所有的地址都flat-mapped,可以理解为没有虚拟地址。

8、TLB维护

  TLB缓存最近使用的页表项,从而允许接下来的页表项查找复用缓存的页表项,而不需要重新加载页表。

  当内存中的页表项发生改变时,必须丢弃TLB中缓存对应的页表项,从而保证页表项的一致性。

  当发生如下错误时,TLBs不应该缓存页表项:

  1)发生地址转换错误(unmapped address)

  2)发生地址发小错误(超出地址范围)

  3)访问权限错误

8.1、TLB操作方法

  使用TLBI指令丢弃TLB中的页表项,其语法如下:

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

  type字段表示丢弃哪个页表项:

    All - 所有页表项

    VA - 匹配xt字段中的VA和ASID的页表项

    VAA - 匹配xt中的VA的页表项,对所有ASID生效

    ASID - 匹配xt字段中ASID的页表项

  level字段表示虚拟地址空间类别

    E1 - EL0/1虚拟地址空间

    E2 - EL2虚拟地址空间

    E3 - EL3虚拟地址空间

  IS | OS字段设置内部共享或者外部共享

    IS - 广播到Inner Shareable domain的其他核

    OS - 广播到Outer Shareable domain的其他核

  Xt字段设置VA和ASID

  举例说明:

STR X1, [X5]    //写入页表入口
DSB ISH //设置内存屏障
TBLI VAAE1IS, X0 //丢弃EL0/1中匹配VA地址的页表项
DSB ISH //解除内存屏障
ISB //指令屏障,同步处理器上下文

9、地址转换指令

  使用地址转换指令(AT指令),可以查询指定VA对应的PA,结果写入PAR_EL1(Physical Address Register)寄存器。

  高级别的运行模式可以使用AT指令查询低级别运行模式的地址转换。

  需要注意的是,使用AT指令发生地址转换异常时,不会抛出任何异常,只会在PAR_EL1寄存器中记录下来。 

Learn The Architecture Memory Management 译文的更多相关文章

  1. 如何展开Linux Memory Management学习?

    Linux的进程和内存是两座大山,没有翻过这两座大山对于内核的理解始终是不完整的. 关于Linux内存管理,在开始之前做些准备工作. 首先bing到了Quora的<How can one rea ...

  2. Operating System Memory Management、Page Fault Exception、Cache Replacement Strategy Learning、LRU Algorithm

    目录 . 引言 . 页表 . 结构化内存管理 . 物理内存的管理 . SLAB分配器 . 处理器高速缓存和TLB控制 . 内存管理的概念 . 内存覆盖与内存交换 . 内存连续分配管理方式 . 内存非连 ...

  3. Android内存管理(1)WRANGLING DALVIK: MEMORY MANAGEMENT IN ANDROID PART 1

    from : http://www.raizlabs.com/dev/2014/03/wrangling-dalvik-memory-management-in-android-part-1-of-2 ...

  4. lwIP Memory Management

    http://lwip.wikia.com/wiki/Lwipopts.h Memory management (RAM usage) /** * MEM_LIBC_MALLOC==1: Use ma ...

  5. Objective-C Memory Management 内存管理 2

    Objective-C Memory Management 内存管理  2  2.1 The Rules of Cocoa Memory Management 内存管理规则 (1)When you c ...

  6. Durable NAND flash memory management

    词条积累 1.NAND flash memory http://www.searchstorage.com.cn/whatis/word_6052.htm http://baike.baidu.com ...

  7. Memory Management in Open Cascade

    Open Cascade中的内存管理 Memory Management in Open Cascade eryar@163.com 一.C++中的内存管理 Memory Management in ...

  8. Java (JVM) Memory Model – Memory Management in Java

    原文地址:http://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java Understanding JV ...

  9. Objective-C Memory Management

    Objective-C Memory Management Using Reference Counting 每一个从NSObject派生的对象都继承了对应的内存管理的行为.这些类的内部存在一个称为r ...

随机推荐

  1. pc和手机适应js代码

    如果是手机的话跳转到新的地址 <script type="text/javascript"> function IsPC() { var userAgentInfo = ...

  2. 本地远程调试Linux 部署的web 项目

    1.在linux tomcat 下面的 bin 目录下增加一个远程调试的命令: declare -x CATALINA_OPTS="-server -Xdebug -Xnoagent -Dj ...

  3. 第十二篇 JavaScript(简称JS) 实现显示与隐藏

    JavaScript   JavaScript简称JS.JS是脚本语言,它是一种轻量级的编程语言,是可以插入HTML页面的编程代码,几乎所有现代浏览器都是支持的. 理论老师不行,我就抄袭手册上的一些关 ...

  4. 关于rpm包的安装卸载等

    在Linux操作系统中,有一个系统软件包,它的功能类似于Windows里面的“添加/删除程序”,但是功能又比“添加/删除程序”强很多,它就是Red Hat Package Manager(简称RPM) ...

  5. Docker搭建Gitlab服务器

    1.使用docker搜索gitlab镜像 docker search gitlab 2.下载镜像: docker pull docker.io/gitlab/gitlab-ce 3.查看docker镜 ...

  6. httpd统计的其他方法,awk,sed等

    1. https://stackoverflow.com/questions/345546/how-to-get-requests-per-second-for-apache-in-linux 2. ...

  7. Apache提示You don't have permission to access / on this server 解决

    本文链接:https://blog.csdn.net/Niu_Eva/article/details/90741894 Apache提示You don’t have permission to acc ...

  8. Hibernate的缓存(收集)

    (1)缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中(一个数据结构中),这个数据结构通常是或类似Hashmap,当以后要使用某个对象 时,先查询缓存中是否有这个对象,如果有则使用缓存中的对 ...

  9. 【洛谷P4173】残缺的字符串

    题目大意:给定一个文本串和一个模板串,串中含有通配符,求文本串中有多少个位置可以与文本串完全匹配. 题解:利用卷积求解字符串匹配问题. 通配符字符串匹配的数值表示为 \[\sum\limits_{i ...

  10. 【hiho1087】Hamiltonian Cycle

    题目大意:给定一个 N 个点的有向图,计数图上哈密顿回路的条数. 题解:哈密顿回路需要经过除了初始位置,每个点恰好一次.如果已知一条哈密顿回路的方向,那么从这条路上任意一个点出发,得到的都是同样的结果 ...