IOVA的理解
物理地址(PA)或IO虚拟地址(IOVA)https://blog.csdn.net/majianting/article/details/102938013参考链接IOMMU和VFIO的解释:https://www.cnblogs.com/yi-mu-xi/p/12370626.html如何判断iommu/smmu 是否能用?https://www.cnblogs.com/yi-mu-xi/p/
物理地址(PA)或IO虚拟地址(IOVA)
https://blog.csdn.net/majianting/article/details/102938013
IOMMU和VFIO的解释:
https://www.cnblogs.com/yi-mu-xi/p/12370626.html
如何判断iommu/smmu 是否能用?
https://www.cnblogs.com/yi-mu-xi/p/12355584.html
不能单单从 /sys/kernel/iommu_groups 下面是否为空来判断,因为在没有iommu的时候,若使用vfio+noiommu模式(echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode), vfio 也会在 iommu_groups下面添加设备,此时该目录下非空,但其实iommu不能用。
来自 https://www.cnblogs.com/yi-mu-xi/p/12355584.html
iommu_group:代表共享同一个streamid的一组device,也就是多个device可以在同个group
domain :代表一个具体的设备使用iommu的详细spec
来自 https://blog.csdn.net/weixin_43503508/article/details/107924027
iommu-spec 要点
DMA隔离: 操作系统可以创建多个domain,为每个domain透传一个或多个设备,每个设备驱动将自己的io-buffer显式地注册到OS,OS将这些io-buffer透传到特定的domain,使用硬件强制完成DMA domain的保护
domain被定义为platform上的一个抽象环境,host物理内存的一个子集被分配到该domain中.允许访问物理memory的IO设备会被分配给一个domain,并且以domain的设备来标识。对于虚拟化应用,软件会将每个vm当做一个domain.
domain的隔离特性是通过禁止domain内的device访问domain外的memory来实现的。多个相互隔离的domain在以下情况支持,即当所有IO设备都被透传到一些domain,domain内的设备只能访问domain内的物理资源。
DMA地址空间可能是device被透传到的vm的GPA地址空间,可能是host应用中DMA请求时的VA地址空间,可能是vm内的客户端应用的GVA地址空间,被host软件管理的IOVA地址空间,Guest软件管理的GIOVA地址空间。以上这些情况下,DMA重映射将device发起的DMA请求中的地址转换为对应的HPA.
Root Table的功能就是将设备映射到对应domain。Root Table的地址可以从 Root Table Address Register (RTADDR_REG)中读取,Root Table含有256个entry,因为PCI bus number space是0-255,Root Table中的每个entry都指向对应的Context Table,后者代表的是该bus上的所有device,Context Table一共256个entry,而每个PCI device最多有8个function,一条PCI bus上最多有32个device,所有256个entry正好可以实现device[i]_function[j]的全映射,Context Table中的每个entry都将一个device 映射到对应的domain,source_id中的device和function_number就是用来在Context Table中找到对应entry的。可以通过编辑device对应的Context Table中的entry,使多个device映射进一个domain.
https://www.cnblogs.com/haiyonghao/p/14440767.html
https://zhuanlan.zhihu.com/p/374919396
设备穿透之IOMMU分组
系统启动的时候会执行iommu_init函数进行内核对象iommu的初始化。主要是调用了kset_create_and_add函数创建了iommu_groups对象。在/sys/kernel目录下会出现iommu_groups目录。/sys/kernel/iommu_group
iommu_bus_init中会遍历总线下的设备,给每个设备调用回调函数add_iommu_group,将设备添加到iommu group中
然后调用iommu_group_get_for_dev给设备添加iommu group,不同体系结构最后实际都是调的该函数接口。
最后重点是调用iommu_group_add_device将设备添加到iommu_group中去。
然后将设备添加到组中,并创建软链接,将/sys/kernel/iommu_groups/xx/devices/设备PCI号,链接到/sys/devices/pci总线ID/设备号上。
同时设备结构中包含的iommu_group对象会指向其所在的组。
dev->iommu_group = group;
然后会给设备做DMA映射,iommu_group_create_direct_mapping主要是将设备对应的虚拟机地址空间段映射到物理地址空间。其会遍历设备映射的地址段,然后调用iommu_map给每段虚拟地址空间都映射到相应的物理内存页上。
arm下调用的就是arm_smmu_device_group,然后根据设备是否是PCI,分别调用generic_device_group或pci_device_group。最终调用的是iommu_group_alloc分配内存空间。
iommu_group_add_device
IOMMU是如何划分PCI device group的?
https://zhuanlan.zhihu.com/p/341895948
根据内核函数iommu_get_domain_for_dev
只要dev的group一样,那么dev的iommu_domain就一样!
arm_smmu_attach_dev ARM_SMMU_DOMAIN_BYPASS 是否可以不经过smmu
/sys/bus/pci/devices/
https://zhuanlan.zhihu.com/p/341895948
在虚拟化引入之前,IOMMU主要有两个功能:
1/创建IOVA到HPA的映射,让设备能够访问任意物理内存。比如,有些I/O设备的寻址空间只有4G,但是平台的物理内存大于4G,为了让这样的I/O设备能够访问4G空间以上的内存,就需要建立一个IOVA -> HPA的映射。
2/通过IOVA -> HPA的映射,创建内存连续的DMA访问,提高系统性能。比如,内核分配2个不相邻的4KB内存页,若没有IOMMU,需要建立两次DMA操作才能访问到这两个内存页,若有IOMMU,则可以将这两个不相邻的物理内存页映射到相邻的IOVA上,这样设备只需要建立一次DMA操作,即可访问到这两个不相邻的物理内存页。
虚拟化对IOMMU的主要应用就是对设备的隔离
对于PCIe架构而言,PCIe设备发出的所有TLP包都会包含一个requester ID(即PCI设备的Bus、Device和Function Number),这个ID可以唯一地辨别一个PCI设备,TLP的接收设备可以使用这个ID来查找IOVA的地址转换页表,这样PCIe设备就可以使用虚拟地址(IOVA)访问物理内存。这时候,对于透传给虚拟机的PCI设备,软件需要做的就是将PCIe设备所在的虚拟机的虚拟机物理地址GPA(Guest Physical Address)到主机物理地址HPA(Host Physical Address)的映射告知IOMMU,当PCIe设备发生DMA的时候,IOMMU选择目标虚拟机的GPA->HPA的映射表对地址进行转换,这样就能够让透传的PCI设备只能访问到虚拟机的物理地址空间,即分配给虚拟机的物理内存,达到设备隔离的目的。
device group指的是从IOMMU角度看能够进行隔离的最小设备集
device group中所有的设备将会共享一个IOVA地址空间。对于传统PCI总线上的设备而言,TLP中不包含Requester ID,无法进行设备区分,所以整个传统PCI总线上的设备都将被划分到同一个device group上。PCIe设备发出的TLP带有requester ID,所以可以进行设备区分,也就是可以使用独立的IOVA地址空间。
从设备发出的TLP是否都能够到达IOMMU,如果设备发出的TLP可以不经过IOMMU,IOMMU就无法对TLP中包含的地址进行转换,即IOMMU无法控制设备的访问地址,无法达到隔离的目的。
总的来说,iommu device group的划分总体来说按照以下两个规则 :
一条传统PCI总线或者PCI-X总线上的PCI设备都划分到同一个device group。
从PCIe设备往上看,在设备通往PCIe树根节点的路径上,所有的PCIe downstream port和multi-function device都需要通过ACS特性,将peer-to-peer转发的功能关闭。若某个PCIe downstream port或multi-function未通过ACS特性关闭peer-to-peer特性,则下面的所有设备都必须归到同一个iommu group,否则该PCIe设备就可以独立成一个iommu group。
内核函数pci_device_group()用于对pci设备进行device group的划分
ARM SMMU驱动
https://www.it610.com/article/1281626899642073088.htm
https://blog.csdn.net/u012403024/article/details/109530639
DMA地址翻译的过程和虚拟地址翻译的过程是完全一致的,
唯一不同的地方在于MMU地址翻译是将进程的虚拟地址(HVA)翻译成物理地址(HPA),而IOMMU地址翻译则是将虚拟机物理地址空间内的GPA翻译成HPA。IOMMU页表和MMU页表一样,都采用了多级页表的方式来进行翻译
来自: https://blog.csdn.net/Rong_Toa/article/details/108997226
An IOVA may correspond to a core’s page table’s virtual address
(VA), intermediate physical addresses (IPA), physical addresses (PA), or use entirely different
page tables as the cores.
为了支持I/O透传机制中的DMA设备传输,而引入了IOMMU技术(ARM称作SMMU)
Intel和AMD都在处理器架构中提供了对Passthrough I/O的支持。Intel将这种支持称为VT-d(Virtualization Technology for Directed I/O),AMD称之为IOMMU(I/O Memory Management Unit)。所以有必要了解一下Passthrough技术。
https://www.cnblogs.com/zhuguihua/archive/2012/11/03/2752841.html
domain
在了解VFIO之前需要了解3个基本概念:device, group, container,它们在逻辑上的关系如上图所示。
Group 是IOMMU能够进行DMA隔离的最小硬件单元,一个group内可能只有一个device,也可能有多个device,这取决于物理平台上硬件的IOMMU拓扑结构。 设备直通的时候一个group里面的设备必须都直通给一个虚拟机。 不能够让一个group里的多个device分别从属于2个不同的VM,也不允许部分device在host上而另一部分被分配到guest里, 因为就这样一个guest中的device可以利用DMA攻击获取另外一个guest里的数据,就无法做到物理上的DMA隔离。 另外,VFIO中的group和iommu group可以认为是同一个概念。
Device 指的是我们要操作的硬件设备,不过这里的“设备”需要从IOMMU拓扑的角度去理解。如果该设备是一个硬件拓扑上独立的设备,那么它自己就构成一个iommu group。 如果这里是一个multi-function设备,那么它和其他的function一起组成一个iommu group,因为多个function设备在物理硬件上就是互联的, 他们可以互相访问对方的数据,所以必须放到一个group里隔离起来。值得一提的是,对于支持PCIe ACS特性的硬件设备,我们可以认为他们在物理上是互相隔离的。
Container 是一个和地址空间相关联的概念,这里可以简单把它理解为一个VM Domain的物理内存空间。对于用户态驱动,Container可以是多个Group的集合。
https://www.cnblogs.com/yi-mu-xi/p/12370626.html
VFIO使用DMA Remapping为每个Domain建立独立的IOMMU Page Table将直通设备的DMA访问限制在Domain的地址空间之内保证了用户态DMA的安全性, 使用Interrupt Remapping来完成中断重映射和Interrupt Posting来达到中断隔离和中断直接投递的目的。
dev/iommu_group/iommu_domain 三者关系的简单理解
https://blog.csdn.net/tiantao2012/article/details/62892281
group = iommu_group_get(dev);
而iommu_group 有包含iommu_domain
总结一下:dev->iommu_group->domain.可见domain 代表一个具体的设备使用iommu的详细spec。
有了domian只有就可以通过iommu_dma_init_domain 来设定这个dev使用smmu详细的spec
int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
u64 size, struct device *dev)
————————————————
而目前系统中的iommu_group 主要分成两个group,一个是pcie。一个是generic ,这个从下面这个函数中可以看出
static struct iommu_group *arm_smmu_device_group(struct device *dev)
参考链接:
http://www.elecfans.com/d/1306594.html
更多推荐
所有评论(0)