背景
IOMMU(Input/Output Memory Management Unit)输入输出内存管理单元
iommu到底是做什么的?很多文章都介绍过,但总是会云里雾里。我想我这篇也会如此。不过先把最核心结论(略显片面但能见本质)放前面吧:
iommu是用于CPU外围设备(简称外设,比如网卡)访问主存(DDR)的时候在外设和DDR之间的一道屏障。
以PCIe网卡为例,比如网卡收到包之后,网卡里面的DMA将数据包存储到DDR不能直接访问DDR,需要先发送携带访问地址的PCIe报文到IOMMU,IOMMU检查通过合法性之后,再将访问地址转化为实际的DDR 物理地址PA,然后将数据包写入主存。这里iommu起到的就是一层屏障的作用。
缘起
iommu在实际业务场景中应用最多的是云计算需要开启多租户场景,主要是为了多租户之间安全隔离。对于云计算场景单租户场景开的少一些,不过主要是为了性能。
iommu的出现从芯片设计上需要多一个硬件模块,既增加了功耗也增加了芯片面积提高了芯片成本。带来的真正受益到底是什么?
是性能?安全?
可能主要是为了多租场景的安全,为了多租安全隔离。云多租场景的广泛应用极大加强了这个技术的推广和发展。
有了IOMMU,对于一些用户态驱动程序的开发提供了安全的环境。由于IOMMU的映射功能,用户空间无法直接看到物理地址,这样即便恶意代码试图访问不该访问的地址也会被拦截。
一些概念
- 在Intel中叫IOMMU,在ARM中叫做SMMU
- 在iommu里面,经过iommu映射后的地址叫做iova,映射的一般是VA地址和PA地址的关系,输入是VA+PA列表,输出是iova。iova输出后,这个地址是最终会给到硬件外设。硬件拿着这个iova进行访存的时候会先经过iommu将iova转化为需要访问的PA列表,并直接进行访存后返回给外围设备。
- iommu开启后拦截来自于外设的内存访问,IOVA转换成PA,从而管理器io设备对内存访问的保护和隔离
- 在iommu里面,分了多个表,一般会根据PCIe设备的bdf创建iommu的表
- 在iommu里面可以同时处理来自多个设备的事务,每个事务有数据流标识Stream ID。每个数据流标识使用不同的一级页表和二级页表来进行地址转换。
- 在iommu中,基础管理单元是页表,页表的颗粒度支持4KB、16KB、64KB…等
- iommu支持几个接口:需要接收来自CPU的配置接口,访问主存的读写接口
- iommu除了做转译服务后面又还可以做中断重映射、I/O大页表转译等
- iommu可以不经过Hypervisor直接访问物理内存和I/O TLB处理器缓存。
- iommu硬件单元内部包括类似MMU的2大主体单元:TLB和TWU。TLB(TranslationLookasideBuffer)和TWU(TableWalkUnit)的作用,TLB作为缓存加速地址转换,而TWU负责硬件级页表查找。缺页时,会触发缺页中断,由内核处理。TLB的存在减少了CPU参与,提升了性能。在ARM上交TBU(变换缓冲器单元)和TCU(变换控制单元)。其中TCU 2个作用:上下文控制和页表遍历控制。其中TLB还有自己的L1和L2级缓存以及自己的TLB逻辑控制单元。更多参考兄弟篇:https://blog.csdn.net/essencelite/article/details/132179383
- RISC-V有自己的IOMMU规范文档
- IOMMU支持ATS(Address Translation Service)转换服务,不用经过RC(root completx)
一些实操
- intel的iommu在Intel VT-d功能中,需要开启内核配置选项,比如IOMMU_SUPPORT、IOMMU_API、INTEL_IOMMU
- intel如何开启iommu?在启动命令cmd_line中添加
intel_iommu=on
。该参数开启才会正确的初始化英特尔IOMMU模块。 - iommu如何开启虚拟机的直通? 在启动命令cmd_line中添加
iommu=pt
- iommu如何关闭虚拟机的直通?在启动命令cmd_line中添加
iommu=nopt
- 在DPDK里面的用户态驱动程序ibg_uio需要强制开启
iommu=pt
- VFIO-PCI既可以支持iommu=pt或iommu= on。
- iommu的nopt与iommu的on的区别是什么?
一些问题
- iommu在DMA和主存之间增加了一道操作,不应该会降低性能吗?
不全对。
先说HOST相关访存场景:iommu在DMA和主存之间增加了访存操作,但同时iommu将多个分散的DMA操作聚合成一个连续的DMA操作,减少了DMA操作的次数。尤其对于数据面操作频繁,且物理地址分散,性能要求较高的场景提升是倍增的关系。具体倍率取决于有无iommu的次数,与分散的内存块数量正相关。
再说Guest相关访存场景:如果开启了硬件设备直通到VM中,iommu开启后,对于设备访存带来的性能层面影响和HOST场景无本质差别。都是设备带着IOVA或者PA去访存。开了iommu就拿着IOVA
其他
兄弟篇:【1000个Linux内存知识-001】-MMU中的两个单元分别是什么?(TLB TWU)作用和使用时机?
综述
综述一句不太准确但能见第一性的话总结IOMMU,就是为了避免IO外设破坏或改写其他非权限范围内的内存,通过IOMMU引入访存过程来管理内存访问。管理方式会做地址映射,映射后的地址叫做IOVA。所以IOMMU是一个管理外设内存访问的地址转换和权限管理硬件单元。