IOMMU-VFIO-设备透传-笔记
1. IOMMU主要功能包括DMA Remapping和Interrupt Remapping。DMA Remapping:设备驱动通过DMA描述符告诉设备DMA控制器,本次DMA操作的存储器地址。在宿主机上,DMA描述符上存储的是物理地址,DMA可正常进行。在虚拟机上,设备通过VT-d等技术被直接分配给虚拟机后,DMA描述符上存储的是GPA(即HVA);而RC上映射的是HPA,故DMA不能正常进
1. IOMMU主要功能包括DMA Remapping和Interrupt Remapping。
DMA Remapping:
设备驱动通过DMA描述符告诉设备DMA控制器,本次DMA操作的存储器地址。
在宿主机上,DMA描述符上存储的是物理地址,DMA可正常进行。
在虚拟机上,设备通过VT-d等技术被直接分配给虚拟机后,DMA描述符上存储的是GPA(即HVA);而RC上映射的是HPA,故DMA不能正常进行;此时需要iommu将TLP中的GPA转换为HPA,然后存储器才能接收到数据。
疑问:设备 -> iommu -> rc -> 存储器 or 设备 -> rc -> iommu -> 存储器?答:倾向于前一种。
2. IOMMU作用:
1)屏蔽物理地址,起到保护作用。一是用户态驱动;二是设备透传给虚拟机。
2)将连续的GPA映射为不连续的HPA。
3. IOMMU工作原理:
IOMMU与MMU类似,也是利用页表完成GPA到HPA的映射。
如何找到页表?答:
设备发起DMA请求的TLP包中包含有BDF(Bus, Device, Function),IOMMU根据基址寄存器RTADDR_REG和BDF找到页表首地址。
属于同一虚拟机的不同设备须使用同一份页表。每个虚拟机(或者说每个IOMMU group)对应一个页表?答:是。
由PCIe switch扩展出的PCI桥及桥下设备,发起DMA请求时,均使用PCIe switch的BDF,导致对应同一份IOMMU页表;因此这些设备须分配给同一个虚拟机。
4. VFIO概念
VFIO是内核针对IOMMU提供的软件框架,支持DMA Remapping和Interrupt Remapping。VFIO利用IOMMU可屏蔽物理地址对上层的可见性,可用来开发用户态驱动,也可实现设备透传。
Group:
group是IOMMU能够进行DMA隔离的最小硬件单元;
一个group内可以有一个或多个device,取决于物理平台上硬件的IOMMU拓扑结构;
一个group中的所有设备只能透传给同一个虚拟机,也不分属于host和vm。
疑问:iommu拓扑结构怎么改变?答:硬件拓扑,可通过将pci设备查到主板其他pci插槽上改变。
Container:
对于用户态驱动,可以是多个group的集合;对于虚拟机可以理解为一个VM Domain的物理内存空间(多个group中的所有设备可直通给同一个虚拟机?答:是)。
5. VFIO用户态驱动:
/* 获取container文件句柄 */
container = open("/dev/vfio/vfio", O_RDWR);
/* 编写某个设备的用户态驱动前,首先将设备从原内核驱动detach,并attach到vfio-pci驱动,即加入到某个vfio group中;
获取group文件句柄 */
group = open("/dev/vfio/26", O_RDWR);
/* 将group加入到container中 */
ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);
ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);
dma_map.vaddr = mmap(0, 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); // 用户态虚拟地址
dma_map.size = 1024 * 1024;
dma_map.iova = 0; // iommu转换前,设备发起DMA时使用的地址;vaddr经MMU,iova经iommu转换后的物理地址是相同的。
dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
疑问:
iova在用户态怎么赋值?始终赋值为0吗?
关于vfio用户态驱动和vfio框架值得研究。
6. 设备透传
pcie设备MMIO空间透传给虚拟机;而配置空间在host枚举时已配置好,不会透传给设备。
虚拟机地址映射:
GVA -> GPA -> HPA。
Qemu维护了GPA和HVA的映射关系。
设备透传时的地址转换:
设备:DMA请求中使用GPA,经IOMMU转换为HPA1。
虚拟机:GVA 经VM MMU-> GPA 经HOST MMU-> HPA2。
如何确保HPA1与HPA2相等?
设备在host上的vfio-pci驱动发挥什么作用?
参考:ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
设备使用的GPA对应iova;
虚拟机GPA对应的HVA,对应vaddr;
如此,保证了HPA1与HPA2相等。
qemu或kvm发挥什么作用?
设备透传操作过程:
将设备与host上的driver解绑定
echo "0000:18:00.0" > /sys/bus/pci/devices/0000\:18\:00.1/driver/unbind
将设备与host上的vfio-pci绑定
modprobe vfio
modprobe vfio-pci
echo "8086 158b" > /sys/bus/pci/drivers/vfio-pci/new_id
qemu命令行启动虚拟机时,添加参数:
-device vfio-pci,host=18:00.0
dmesg | grep iommu /* 内核启动后,设备属于哪个group就确定了。该命令可查看各个pci设备分别属于哪个group */
ls /sys/kernel/iommu_groups /* 查看有哪些iommu group,以及各个group中有哪些设备 */
ls /dev/vfio/ /* 只有待透传设备对应的group出现在/dev/vfio目录下,设备才可能透传成功 */
7. 测试记录:
物理千兆网卡直接分配给虚拟机,工作正常。
82599万兆网卡的VF分配给虚拟机失败。
原因:VF和PF在同一个iommu group中。
疑问:主板上带有金属封边的pcie插槽是pci bridge ??
现象:
82599万兆网卡插在该插槽上后,新出现了一个pri bridge,且与两个万兆网卡的PF和VF一起被划分至iommu group 1中;无法将VF分配给虚拟机。
将82599更换插槽后,pci bridge消失,两个万兆网卡的PF和VF分属于不同的iommu group, 且可以将VF分配给虚拟机。
参考:
https://www.cnblogs.com/yi-mu-xi/p/12370626.html:vfio概述(vfio/iommu/device passthrough)。
-----------------------------------------------------------------分割线-------------------------------------------------------------------------------
linux-4.18.1/Documentation/vfio.txt
1. 什么是vfio?
提供了DMA和中断重映射功能;无需root特权用户权限;
2. Groups, Devices, and IOMMUs
没有IOMMU时的问题是什么?
设备进行DMA操作时,可以访问整个物理内存空间,存在极大的安全隐患;
一个iommu group中可能包含多个设备;
group是vfio管理的最小粒度;
一个container可以包含多个group,这些group共享相同的页表,通过open /sys/vfio/vfio就可以创建一个container;
3. VFIO使用示例说明
1)获取设备的iommu group:readlink /sys/bus/pci/devices/domain:bus:dev.func/iommu_group
2)安装vfio-pci驱动:modprobe vfio-pci
3)将设备与主机驱动解绑,并绑定到vfio-pci驱动:
lspci -n -s 0000:06:0d.0
// 输出:06:0d.0 0401: 1102:0002 (rev 08)
echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind
echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id
4)查看该设备所在iommu group中,是否仍有其他设备:ls -l /sys/bus/pci/devices/0000:06:0d.0/iommu_group/devices
如果有,其他设备也需要绑定vfio-pci驱动;
pcie-to-pci桥后的设备都位于同一个iommu group中;
pcie-to-pci桥没有主机驱动,且vfio-pci驱动不支持pci桥;
5)更改/sys/vfio/group id文件的所有者,以使后续操作无需root权限:
chown user:user /dev/vfio/group id
4. VFIO使用示例说明
更详细应用,可参考dpdk实现。
5. VFIO总线驱动api (如:vfio-pci)
更多推荐
所有评论(0)