前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >IOMMU(八)-vIOMMU

IOMMU(八)-vIOMMU

原创
作者头像
惠伟
修改2021-08-26 17:49:35
1.9K0
修改2021-08-26 17:49:35
举报
文章被收录于专栏:虚拟化笔记虚拟化笔记

以前基于DPDK做NFV,转发程序跑在虚拟机中,先把硬件网卡passthrough给虚拟机,然后在虚拟机中把网卡绑定内核模块igb_uio,问题是igb_uio的代码没有upstream,依赖于内核版本,提前编译好的内核模块换个版本就不能运行,就想着用vfio-pci,这家伙早早upsteam,一般linux发行版本内核都自带,且不省事,理想是丰满的,现实是骨感的。

vfio-pci内核模块的probe函数返回了错误:

[51376781.097090] vfio-pci: probe of 0000:00:06.0 failed with error -22

代码语言:javascript
复制
static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	int ret;

	if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
		return -EINVAL;

	group = vfio_iommu_group_get(&pdev->dev);
	if (!group)
		return -EINVAL;
	ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
	if (ret) {
		vfio_iommu_group_put(group, &pdev->dev);
		kfree(vdev);
		return ret;
	}
	return ret;
}

22是EINVAL,看代码是iommu group导致的,再分析是因为机器没有iommu硬件单元,意思就是qemu没有模拟出iommu硬件单元,把模拟的iommu称为虚拟的iommu,就是viommu。

其实viommu和嵌套虚拟化关系很大,比如把pci passthroughed device再次passthrough给虚拟机中的虚拟机,把emulated pci device passthrough给虚拟机中的虚拟机。

qemu最早支持intel-iommu和iommu=smmuv3,后来有virtio-iommu,又演化出vhost-iommu,把virtio-iommu部分功能拿到内核来实现。整体上分为full emulated和hardware assisted emulation,full emulation就是virtio-iommu,纯软件实现iommu的所有功能,性能低,但virtio应用广,能和现有的实现结合起来,比如kernel中的vhost device-iotlb,dpdk中的vhost-user device-iotlb,iommu功能分布在qemu和virtio其它backend处。hardware assisted emulation肯定借助了硬件的好处,硬件实现了两层翻译和各种隔离,qemu做guest里driver和真正硬件之间的翻译,qemu不能直接给硬件提交工作,需要内核提供通道IOMMU Userspace API,通道下去再调用到硬件的驱动,好处就是可以和内核vfio-iommu那一套结合起来,自然而然就可以利用到fault handling,cache invalidation和PASID等,坏处就是guest里运行着厂商自己的driver,如果guest里运行virtio-iommu driver,外面能实现hardware assisted那么就更好。

还有一个问题就是,创建一个虚拟机,然后给这个虚拟机passthrough一个网卡,虚拟机的qemu进程并不需要用到hugepage,在这个虚拟机里运行DPDK需要用到hugepage,hugepage的好处就是长在内存pin住,虚拟机里DPDK用到的hugepage本质上还是qemu进程的非hugepage虚拟内存空间,如何保证DPDK的hugepage一直在真正的物理内存中?这和虚拟机中DPDK用不用vfio-pci没关系。

intel vt-d标准3.2版本第六章《Caching Translation Information》和第七章《Address Translation Faults》讲的东西似乎能解决这个问题,第六章节讲的是IOMMU硬件单元的cache,因为它用的转换表都在内存中,每次去内存读然后再遍历一遍开销很大,所以尽量cache(Context-cache,PASID-cache,IOTLB和Paging-structure Caches),有cache就得维护cache项的状态,是否有效,什么时候清理掉。还有一点就是Device-TLB,device发起一个address translation,IOMMU硬件单元查找自己的cache,然后把结果通过Translation-Completion给了device,device把结果缓存在自己的TLB。第七章讲了Non-recoverable Faults和Recoverable Faults,device发起一个request,IOMMU查找自己的page table发现没有对应的page,就给device-TLB返回一个有问题的Translation-Completion,device-TLB就能检测到这个错误,device上报给自己的driver,driver处理完后让device重试,这样的问题就是不够通用,device和driver各个厂商实现不一样。所以vt-d标准又说,如果device支持pcie page request service,那么device就给IOMMU发送一个page-request消息,IOMMU生成一个struct放在page request queue中,然后给CPU来个page request event中断,IOMMU驱动开始处理,指导IOMMU给device回复一个Page Group Response消息,device再重试刚才的request,这样的好处就是软件通用,代码都在IOMMU驱动中,device硬件要配合IOMMU硬件,整体上来说对硬件的要求很高。

好的,到此IOMMU系列写完,希望对大家有用。

参考文献

IOMMU Userspace API

vt-d 3.2 spec

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档