一、MMU VS IOMMU

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_页表

Fig1. MMU地址转换框图

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_向客户机操作系统公开硬件辅助的虚拟化_02

Fig2. 同一虚拟机下IOMMU地址转换框图

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_用户空间_03

 

Fig3. 不同虚拟机下IOMMU地址转换框图

二、某个IO DEVICE如何找到其对应的IOPT?

设备发起DMA请求时,会将自己的Source Identifier(包含Bus/Device/Func)包含在请求中,IO MMU根据该标识完成映射。过程如下:

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_用户态_04

Fig3. IOMMU页表查询过程

说明:1、IOMMU的页表,可以认为同属于一个虚拟机的io device共用一个页表(也即一个虚拟机使用一个IOMMU页表),这其实也和Linux中只有一个GDT,并且被所有进程共享一样,类比方便理解。

2、Fig3中红线的部分,是两个Context Entry指向了同一个页表。这种情况在虚拟化场景中的典型用法就是这两个Context Entry对应的不同PCIe设备属于同一个虚拟机,那样IOMMU再将GPAàHPA过程中要遵循同一规则(同一个页表);

3、对于由PCIe switch扩展出的PCI桥及桥下设备,在发送DMA请求时,Source Identifier是PCIe switch的,这样的话该PCI桥及桥下所有设备都会使用PCIe switch的Source Identifier去定位Context Entry,找到的页表也是同一个,如果将这个PCI桥下的不同设备分给不同虚机,由于会使用同一份页表,这样会产生问题,针对这种情况,当前PCI桥及桥下的所有设备必须分配给同一个虚机,这就是VFIO中组的概念。详见VFIO分析。

扩展知识:

现在大部分IOMMU,都支持多进程访问。比如我有两个进程同时从用户态访问设备,他们自己管理iova,这样,他们给iommu提供的iova就可能是冲突的。所以,IOMMU硬件同时支持多张iopt,用进程的id作为下标(对于PCIE设备来说,就是pasid了),Fig.4展示pasid在GPU和CPU地址空间share的一个应用:

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_用户态_05

Fig.4 CPU和GPU地址空间共享

三、用户态驱动之UIO

向客户机操作系统公开硬件辅助的虚拟化 向客户机操作系统公开iommu_用户态_06

UIO框架导出sysfs和/dev/uioX 2套用户态接口,用户对设备节点/dev/uioX进行设备控制,mmap()接口用于映射设备寄存器空间,write()接口用于控制中断关闭/打开,read()接口用于等待一个设备中断。

因为对于设备中断的应答必须在内核空间进行,所以在内核空间有一小部分代码用来应答中断和禁止中断,其余的工作全部留给用户空间处理。如果用户空间要等待一个设备中断,它只需要简单的阻塞在对 /dev/uioX的read()操作上。当设备产生中断时,read()操作立即返回。UIO 也实现了poll()系统调用,你可以使用 select()来等待中断的发生。select()有一个超时参数可以用来实现有限时间内等待中断。

UIO的几个特点:

  • 一个UIO设备最多支持5个mem和portio空间mmap映射
  • UIO设备的中断用户态通信机制基于wait_queue实现
  • 一个UIO设备只支持一个中断号注册,支持中断共享

总的来说,UIO框架适用于简单设备的驱动,因为它不支持DMA,不能支持多个中断线,缺乏逻辑设备抽象能力。

四、用户态驱动之VFIO

1、IOMMU支持DMA remaping特性(相应的,MMU支持CPU remaping),可以屏蔽物理地址对上层的可见性,以确保IO设备只在分配给它们的VM domain内(虚拟机内)访问内存,可以利用IOMMU来开发用户态驱动和设备透传。VFIO就是利用IOMMU这个特性实现的。

2、VFIO驱动程序是一个与IOMMU具体硬件无关的框架,可以支持x86架构的VT-D、AMD-Vi,POWER PE,ARM等各种IOMMU硬件架构。使用VFIO可以实现安全的,非特权的,用户空间驱动程序。

相较于VFIO,用UIO框架实现的用户空间驱动,将不受IOMMU的保护,且中断支持有限,并且需要root权限运行。并且,UIO不支持DMA,所以通过DMA传输大流量数据的IO设备,如网卡、显卡等设备,无法使用UIO框架,VFIO作为UIO的升级版,就是为了解决UIO这一系列问题而出现的。

3、VFIO如何工作?通过用户态配置IOMMU,可以将DMA地址空间映射限制在进程虚拟空间中,这对高新能驱动和虚拟化场景下的device passthrough尤其重要。

4、VFIO的group和container

(1)group: pass through给同一个虚拟机的io device集合。Group 是IO MMU能够进行DMA隔离的最小硬件单元(隔离:即使用不同的页表)。

(2)container: 对于虚拟机,container这里可以简单理解为一个VM Domain(虚拟机)的物理内存空间,对于用户态驱动,container可以是多个group的集合。从这里看出——虚拟机其实是一个特殊的用户态驱动。

参考文章:

IOMMU & iomap &VFIO & uio - yimuxi )

[Linux] VFIO - 简书 (jianshu.com)

IOMMU和VFIO概述-lvyilong316-ChinaUnix博客