目录
第1章 内存管理单元MMU
1.1 什么是内存管理单元MMU
1.2 基本原理
1.3 关键概念
1.4 程序的局部性原理
第2章 DMA机制
2.1 什么是DMA
2.2 DMA的原理
2.3 基本过程
2.4 DMA的传送方式
第3章 IOMMU
3.1 什么是IOMMU
3.2 DMA重映射:设备逻辑/虚拟地址与任意物理内存地址的分离
3.3 DMA重映射:连续虚拟地址与不连续物理地址的映射(scatter/gather机制)
3.4 DMA重映射:对虚拟化的支持
3.5 中断重映射(可选)
它山之石:
MMU是Memory Management Unit的缩写,中文名是内存管理单元,有时称作分页内存管理单元(英语:paged memory management unit,缩写为PMMU)。它是一种负责处理中央处理器(CPU)的内存访问请求的计算机硬件。它的功能包括虚拟地址到物理地址的转换(即虚拟内存管理)、内存保护、中央处理器高速缓存的控制,在较为简单的计算机体系结构中,负责总线的仲裁以及存储体切换(bank switching)。
MMU位于处理器内核和连接高速缓存以及物理存储器的总线之间。当处理器内核取指令或者存取数据的时候,都会提供一个有效地址(effective address),或者称为逻辑地址、虚拟地址。这个地址是可执行代码在编译的时候由链接器生成的。不同于开发嵌入式处理器系统的程序员,桌面型计算器的程序开发人员通常对硬件的物理配置信息所知甚少。将存储器系统虚拟化,程序员就不需要了解存储器的物理配置细节。当应用代码需要使用存储空间时,操作系统通过MMU为其分配合适的物理存储空间。有效地址不需要和系统的实际硬件物理地址相匹配,而是通过MMU将有效地址映射成对应的物理地址,以访问指令和数据。
每条MMU匹配规则所对应的存储器的大小定义为页。页的大小通常设定为不会对程序的性能造成显著影响的最小的程序和代码的长度。当暂时不使用物理内存的内容时,可将其保存到硬盘等外部存储器里,将其空间用于其他程序;当再次使用这部分内容时再从外部存储器写回到实际物理内存中。通过这种方法,系统就可以提供多于实际物理内存容量的“虚拟内存”。
如果MMU定义的页太大,那么进行虚拟内存页面替换所花费的时间就太长;
如果页太小,就会引起过于频繁的页面替换。
通常最小的页设定为4 KB。
为了加快MMU规则匹配的处理过程,有效地址和实际物理地址的对应表(页表)通常保存在一块单独的高速缓存中,称为对应查找表(Translation Lookaside Buffer,TLB),TLB和实际物理存储器可以同时进行并行的访问。有效地址的高位作为在TLB进行匹配查找的依据,而有效地址的低位作为页面内的偏址。
TLB可以包含很多个表项(entry),每个表项对应一个MMU的页。操作系统或者应用启动代码必须正确的初始化TLB的所有表项。
当应用程序提供的有效地址正好位于某个TLB表项制定的地址范围内时,称为产生了一次TLB命中;
如果这个有效地址没有位于任何一个TLB表项制定的地址范围内,称为一个TLB缺失,或者TLB未命中。TLB未命中往往发生在应用程序出现错误的时候,所以TLB未命中所引发的异常处理可以很有效的发现和调试这类错误。虚拟内存利用TLB未命中的异常来完成页面交换,并根据交换的内容对应的调整TLB表项的参数。通常TLB表项还会指定一些存储器读写的其他参数,只有当这些参数也和当前的存储器读写的参数符合的时候,才能产生TLB命中。
地址范围
任何时候,计算机上都存在一个程序能够产生的连续的地址集合,我们称之为地址范围。
地址范围的大小由CPU的位数决定,例如一个32位的CPU,它的地址范围是0~0xFFFFFFFF (4G),而对于一个64位的CPU,它的地址范围为0~0xFFFFFFFFFFFFFFFF (16E)。
虚拟地址
这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址。
物理地址
与虚拟地址空间和虚拟地址相对应的则是物理地址空间和物理地址,大多数时候我们的系统所具备的物理地址空间只是虚拟地址空间的一个子集。
这里举一个最简单的例子直观地说明这两者,对于一台内存为256M的32bit x86主机来说,
它的虚拟地址空间范围是0~0xFFFFFFFF(4G),
而物理地址空间范围是0x00000000 ~ 0x0FFFFFFF(256M)。
地址映射
在没有使用虚拟存储器的机器上,程序地址被直接送到内存总线上,使具有相同地址的物理存储器被读写;
而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到存储器管理单元MMU,把虚拟地址映射为物理地址。
分页机制
大多数使用虚拟存储器的系统都使用一种称为分页(paging)机制。
虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页帧(frame),页和页帧的大小必须相同。
在这个例子中我们有一台可以生成32位地址的机器,它的虚拟地址范围从0~0xFFFFFFFF(4G),而这台机器只有256M的物理地址,因此他可以运行4G地址空间大小的程序,但该程序不能一次性调入内存运行。这台机器必须有一个达到可以存放4G程序的外部存储器(例如磁盘或是FLASH),以保证程序片段在需要时可以被调用。在这个例子中,页的大小为4K,页帧大小与页相同——这点是必须保证的,因为内存和外围存储器之间的传输总是以页为单位的。对应4G的虚拟地址和256M的物理存储器,他们分别包含了1M个页和64K个页帧。
很显然,可执行程序的地址空间可以大于物理内存RAM的地址空间范围。
而程序有必须调入到高速的物理内存中才能高效执行。这就需要利用到页表的命中、不命中、替换等机制。而页表机制之所以能够工作,得益于页表程序的程序的局部性原理。
页表存在的基本原理是:程序的局部性原理
程序的局部性原理是指程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域。
局部性原理又表现为:时间局部性和空间局部性。
时间局部性是指如果程序中的某条指令一旦执行,则不久之后该指令可能再次被执行; 如果某数据被访问,则不久之后该数据可能再次被访问。(得益于程序三大基本结构之循环执行结构)
空间局部性是指一旦程序访问了某个存储单元,则不久之后,其附近的存储单元也将被访问。(得益于程序三大基本结构之顺序执行结构)
另外,根据程序的局部性理论,Denning提出了工作集理论。所谓工作集是指进程运行时被频繁访问的页面集合。显然我们知道只要使程序的工作集全部集中在内存中,就可以大大减少进程的缺页次数;否则会使进程在运行过程中频繁出现缺页中断,从而出现频繁的页面调入/调出现象,造成系统性能的下降,甚至出现“抖动”。
划分工作集可以按定长时间或定长页面两种方法进行划分。当颠簸现象发生时,说明系统的负荷过大,通常采用处理器均衡调度。另一种是控制缺页率,当缺页率达到上限时,则增加内存分配量;当缺页率达到下限时,就减少内存的分配量。
IOMMU主要用来解决设备DMA的地址映射,因此在了解IOMMU之前,有必要先了解一下DMA机制。
DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。
DMA 传输将数据从一个地址空间复制到另外一个地址空间。当CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工作。DMA 传输对于高效能 嵌入式系统算法和网络是很重要的。
在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。在DMA控制总线的过程中,CPU只是暂停总线的范围,并没有进行进程上下文的切换。
(1)请求:
CPU对DMA控制器初始化,并向I/O接口发出操作命令,I/O接口提出DMA请求。
(2)响应
DMA控制器对DMA请求判别优先级及屏蔽,向总线裁决逻辑提出总线请求。当CPU执行完当前总线周期即可释放总线控制权。此时,总线裁决逻辑输出总线应答,表示DMA已经响应,通过DMA控制器通知I/O接口开始DMA传输。
(3)传输
DMA控制器获得总线控制权后,CPU即刻挂起或只执行内部操作,由DMA控制器输出读写命令,直接控制RAM与I/O接口进行DMA传输。
在DMA控制器的控制下,在存储器和外部设备之间直接进行数据传送,在传送过程中不需要中央处理器的参与。开始时需提供要传送的数据的起始位置和数据长度。
(4)结束
当完成规定的成批数据传送后,DMA控制器即释放总线控制权,并向I/O接口发出结束信号。
当I/O接口收到结束信号后,一方面停 止I/O设备的工作,另一方面向CPU提出中断请求,使CPU从不介入的状态解脱,并执行一段检查本次DMA传输操作正确性的代码。最后,带着本次操作结果及状态继续执行原来的程序。
由此可见,DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,使CPU的效率大为提高。
DMA技术的出现,使得外围设备可以通过DMA控制器直接访问内存。与此同时,CPU可以继续执行程序。
那么DMA控制器与CPU怎样分时使用内存呢?通常采用以下三种方法:
(1)停止CPU访问内存
当外围设备要求传送一批数据时,由DMA控制器发一个停止信号给CPU,要求CPU放弃对地址总线、数据总线和有关控制总线的使用权。DMA控制器获得总线控制权以后,开始进行数据传送。在一批数据传送完毕后,DMA控制器通知CPU可以使用内存,并把总线控制权交还给CPU。图(a)是这种传送方式的时间图。很显然,在这种DMA传送过程中,CPU基本处于不工作状态或者说保持状态。
优点: 控制简单,它适用于数据传输率很高的设备进行成组传送。
缺点: 在DMA控制器访问内存阶段,内存的效能没有充分发挥,相当一部分内存工作周期是空闲的。这是因为,外围设备传送两个数据之间的间隔一般总是大于内存存储周期,即使高速I/O设备也是如此。例如,软盘读出一个8位二进制数大约需要32us,而半导体内存的存储周期小于0.5us,因此许多空闲的存储周期不能被CPU利用。
(2)周期挪用(CPU并没有停止不访问内存的指令)
当I/O设备没有DMA请求时,CPU按程序要求访问内存;
一旦I/O设备有DMA请求,则由I/O设备挪用一个或几个内存周期。
这种传送方式的时间图如下图(b):
I/O设备要求DMA传送时可能遇到两种情况:
(1) 此时CPU不需要访内,如CPU正在执行乘法指令。由于乘法指令执行时间较长,此时I/O访内与CPU访内没有冲突,即I/O设备挪用一二个内存周期对CPU执行程序没有任何影响。
(2) I/O设备要求访内时CPU也要求访内,这就产生了访内冲突,在这种情况下I/O设备访内优先,因为I/O访内有时间要求,前一个I/O数据必须在下一个访问请求到来之前存取完毕。显然,在这种情况下I/O 设备挪用一二个内存周期,意味着CPU延缓了对指令的执行,或者更明确地说,在CPU执行访内指令的过程中插入DMA请求,挪用了一二个内存周期。 与停止CPU访内的DMA方法比较,周期挪用的方法既实现了I/O传送,又较好地发挥了内存和CPU的效率,是一种广泛采用的方法。但是I/O设备每一次周期挪用都有申请总线控制权、建立线控制权和归还总线控制权的过程,所以传送一个字对内存来说要占用一个周期,但对DMA控制器来说一般要2—5个内存周期(视逻辑线路的延迟而定)。因此,周期挪用的方法适用于I/O设备读写周期大于内存存储周期的情况。
(3)DMA与CPU交替访问内存
如果CPU的工作周期比内存存取周期长很多,此时采用交替访内的方法可以使DMA传送和CPU同时发挥最高的效率。
这种传送方式的时间图如下:
此图是DMA与CPU交替访内的详细时间图.假设CPU工作周期为1.2us,内存存取周期小于0.6us,那么一个CPU周期可分为C1和C2两个分周期,其中C1专供DMA控制器访内,C2专供CPU访内。
这种方式不需要总线使用权的申请、建立和归还过程,总线使用权是通过C1和C2分时制的。CPU和DMA控制器各自有自己的访内地址寄存器、数据寄存器和读/写信号等控制寄存器。在C1周期中,如果DMA控制器有访内请求,可将地址、数据等信号送到总线上。在C2周期中,如CPU有访内请求,同样传送地址、数据等信号。事实上,对于总线,这是用C1,C2控制的一个多路转换器,这种总线控制权的转移几乎不需要什么时间,所以对DMA传送来讲效率是很高的。
这种传送方式又称为“透明的DMA”方式,其来由是这种DMA传送对CPU来说,如同透明的玻璃一般,没有任何感觉或影响。在透明的DMA方式下工作,CPU既不停止主程序的运行,也不进入等待状态,是一种高效率的工作方式。当然,相应的硬件逻辑也就更加复杂。
IOMMU:input/output memory management unit。Device的IOMMU类似于CPU的MMU。
在计算机领域,IOMMU(Input/Output Memory Management Unit)是一个内存管理单元(Memory Management Unit),它的作用是连接DMA-capable I/O总线(Direct Memory Access-capable I/O Bus)和主存(main memory)总线。
传统的内存管理单元会把CPU访问的虚拟地址转化成实际的物理地址。
而IOMMU则是把设备(device)访问的虚拟地址转化成物理地址。
为了防止设备错误地访问内存,有些IOMMU还提供了访问内存保护机制。
CPU程序(内核或用户空间):通过MMU,实现CPU的逻辑地址到物理内存地址的映射。
其他硬件设备,如网口:通过IOMMU,实现外设的逻辑地址到物理内存地址的映射。
IOMMU允许系统设备在虚拟内存中进行寻址,也就是将虚拟内存地址映射为物理内存地址,让实体硬件设备和设备驱动程序可以在虚拟的内存环境中工作,这样可以帮助系统扩充内存容量,提升性能。
IOMMU实现两大功能:
(1)DMA Remapping =》 DMA重映射 => 设备逻辑/虚拟地址与任意物理内存地址的分离
(2)Interrupt Remapping =》 中断重映射
(3)虚拟机的支持
硬件设备通过DMA,实现设备逻辑地址到任意物理内存地址之间传送。
要在64位内存系统上支持32位硬件设备,比如说网卡,即网卡设备只能访问32位的物理地址空间。
如果没有IOMMU,就需要在物理内存底端,也就是32位设备能够访问到的地方设置一个叫做"bounce buffers"的东西,如果设备要访问高端内存,操作系统就要在高端内存和"bounce buffers"之间做一个拷贝。带来的性能影响显而易见。
如果有了IOMMU,这个问题就迎刃而解了。在设备驱动做DMA绑定的时候,系统返回给驱动的不再是物理地址,而是内核空间的某个地址(有的书上叫做总线地址),传输的时候,这个内核空间地址会经由IOMMU单元,IOMMU将这个逻辑地址转换为物理地址。
scatter/gather并不会带来性能上的好处,但是会简化设备驱动程序。
例如网卡驱动在发送包的时候,DMA绑定后,系统可能会返回给设备驱动多个不连续的物理地址,Solaris叫做cookie。这样的话,每一个cookie都需要占用一个发送描述符。如果系统支持IOMMU的话,系统只会返回给设备驱动一个cookie。当然了有专家提醒,因为这个原因,如果设备驱动是在没有IOMMU的情况下开发的,在支持IOMMU的系统上是没有问题的。但反之不然。
IOMMU除了上述功能外还加入了对虚拟化的支持。
IOMMU允许系统硬件设备在虚拟内存中进行寻址,也就是将虚拟内存地址映射为物理内存地址,让实体设备可以在虚拟的内存环境中工作,这样可以帮助系统扩充内存容量,提升性能。
IOMMU的一个重要用途是在虚拟化技术(virtualization)
在虚拟化环境中,存在多个虚拟机访问同一个物理机的同一个物理网卡的情形。
虚拟机上运行的操作系统(guest OS)通常不知道它所访问的host-physical内存地址。
如果要进行DMA操作,就有可能破坏内存,因为实际的硬件(hardware)不知道guest-physical和host-physical内存地址之间的映射关系。IOMMU根据guest-physical和host-physical内存地址之间的转换表(translation table),re-mapping硬件访问的地址,就可以解决这个问题。
深入了解iommu系列一:iommu硬件架构和驱动初始化 - 知乎
什么是IOMMU? - 知乎
https://www.jianshu.com/p/fcc6c65f7e83