当前位置: 首页 > news >正文

VFIO的使用及原理

vfio设备透传主要用于将设备直通给虚拟机以提高性能,本篇以一张网卡为例讲述VFIO设备的配置使用及底层原理。其中涉及的技术背景主要有qemu+kvm+vfio。

一、VFIO网卡的配置使用

1.host配置iommu

首先是宿主机host必须支持硬件虚拟化技术,如x86架构的VT-d,其中有关IO的有iommu的支持,x86默认是不开启的,可以通过追加内核参数“intel_iommu=on”来打开。

vim /etc/default/grub

添加完后重启宿主机,并dmesg | grep -i iommu查看是否开启成功

powerpc架构下的iommu是默认开启的,所以可以直接跳过此步。

2.选择设备

本次以一张网卡为例,常见的intel网卡如I350等都是支持VFIO透传的,先看一下系统总体网卡情况,然后在dmesg看到网卡的iommu支持。

ethtool -i ethxxx //查看某个网卡信息

lshw -C network //查看系统总体网络信息

记住一定要选择一个宿主机不用的网卡,如state=DOWN的或ifconfig查看 rx和tx=0 bytes的网卡来配置透传,毕竟vfio属于二选一,透传给VM则host不能再用了。

本次选择enP1p27s0fx这张网卡;

3.设备解绑与重新绑定vfio-pci驱动

#查看group里面的设备,可以发现这个group中共有4个设备

[root@localhost jcf]# ls /sys/bus/pci/devices/0001\:1b\:00.0/iommu_group/devices/
0001:1b:00.0 0001:1b:00.1 0001:1b:00.2 0001:1b:00.3
#将设备与驱动程序解绑,注意这里要把同一group下的4张网卡全部解绑
[root@localhost jcf]# echo 0001:1b:00.0 > /sys/bus/pci/devices/0001\:1b\:00.0/driver/unbind

[root@localhost jcf]# echo 0001:1b:00.1 > /sys/bus/pci/devices/0001\:1b\:00.1/driver/unbind
[root@localhost jcf]# echo 0001:1b:00.2 > /sys/bus/pci/devices/0001\:1b\:00.2/driver/unbind
[root@localhost jcf]# echo 0001:1b:00.3 > /sys/bus/pci/devices/0001\:1b\:00.3/driver/unbind
#找到设备的生产商&设备ID
[root@localhost jcf]# lspci -n -s 0001:1b:00.0
0001:1b:00.0 0200: 8086:1521 (rev 01)

#将设备绑定到vfio-pci驱动,这会导致一个新的设备节点“/dev/vfio/5”被创建
[root@localhost jcf]# echo 8086 1521 > /sys/bus/pci/drivers/vfio-pci/new_id
#查看刚生成的设备节点
[root@localhost jcf]# ls /dev/vfio/

若/sys/bus/pci/drivers/目录下没有vfio-pci目录,则记得insmod vfio_pci模块

此时host中已看不到之前的enP1p27s0fx网卡

4.创建虚机,添加参数 -device vfio-pci,host=xxxx,id=net0

/home/jcf/qemu-6.2.0/build/qemu-system-ppc64 -m 32G -smp 8 -boot c -hda /home/jcf/pseries.img -machine pseries --enable-kvm -device vfio-pci,host=0001:1b:00.0,id=net0 -vnc :25

通过qemu monitor可以看到该网卡已经透传到了虚机内。

4.1 若是通过SR-IOV配置的网卡,就是一开始多一步创建VF,其余步骤相同。

4.2 若是通过libvirt创建虚机,则需添加如下xml透传配置(其中DBDF要自行改变)
<devices> <hostdev mode='subsystem' type='pci' managed='yes'> <driver name='vfio'/> <source> <address domain='0x0001' bus='0x1b' slot='0x00' function='0x0'/> </source> </hostdev> <devices/>

此时上一步骤的解绑绑定都不需要了,libvirt自动设置好。

4.3 若是直通NVMe磁盘,则可以通过如下找到DBDF(ARM叫stream id)

5.登录并配置网络

qemu启动虚机后,可以通过vnc登录进虚机查看,如图发现有一张VFIO网卡。

ip addr add 10.100.11.111/24 dev enp0s2# 设置enp0s2 网口IP地址为10.100.11.111

此处VM的IP需要与Host保持在同一网段。

如果此时发现ping不通,请先确认下Host上的这张网卡是否是NO-CARRIER(没插网线),笔者曾经被它困扰了好久 -_-!

route -n //查看路由

ip route add default via 10.100.11.254 # 设置系统默认路由

ip route add default via 10.100.11.254 dev enp0s2 # 设置enp0s2默认网关为10.100.11.254
# 或
ip route add 10.100.11.0/24 via 10.100.11.254 dev enp0s2 # 设置10.100.11.0网段的网关为10.100.11.254,数据走enp0s2接口

此时也可通过ssh直接链接到VM

将上述配置写入到/etc/sysconfig/network-scripts/ifcfg-xxx,配置好其中的IPADDR,GATEWAY,ONBOOT=yes,就可以自动联网了。

抑或将以上两项写成sh脚本,放入/etc/rc.d/rc.local或单独成一个sh文件,这样可以方便手动调试自动联网。

6.恢复现场

测试完毕记得回归原状.

二、VFIO原理

0.config配置空间

1.DMA重映射

VFIO的目的是透传设备让Guest直接控制,以达类似Host的高速读写。但这样会引入安全问题,比如Guest1利用设备访问Host中Guest2或其它内存地址,所以便出现了DMA重映射。和MMU类似(在内存与CPU之间建立映射),IOMMU在内存与设备之间增加DMA重映射单元。当外设访问内存时,内存地址首先到达DMA重映射硬件,DMA重映射硬件根据这个外设的BDF,确定其对应的页表,查表得出物理内存地址,然后将地址送上总线。

qemu中,在vfio初始化阶段,会将Guest的各个MR通过ioctl(VFIO_IOMMU_MAP_DMA)系统调用,请求Host内核在页表中建立好GPA-HPA的映射关系。其中最主要的就是vm.ram,以arm64为例,DMA的映射在虚机启动时就已经静态建立好了,映射要涵盖整个GPA地址范围,同时虚机GPA对应的物理页都不会交换出去。

对于设备的MMIO空间如virtio_net_pci.rom、vga.ram/rom、VFIO.BAR,会在加载相应的设备驱动时,动态映射至Host中建立GPA-HPA的关联。

对于vfio iommu type1(x86和arm)驱动来说,Host内核中处理ioctl(VFIO_IOMMU_MAP_DMA)的核心函数是vfio_dma_do_map()->iommu_map(),继而调用arch相关的回调函数iommu_domain->iommu_ops->map(),其中arm架构的是arm_smmu_map(),x86架构是intel_iommu_map()。

在真正map之前中会先通过HVA获取pfn,然后在arch回调中根据iova(Guest不开启vsmmu时就是GPA),从页表中找到具体的表项,然后将HPA写入表项中,完成IOMMU页表的建立。

2.中断重映射

同样基于安全等因素的考虑,vfio设备中断和cpu之间也需要拦截,即在外设和CPU之间加了一个硬件中断重映射单元。当接收到来自外设的中断时,硬件中断重映射单元会对中断请求的来源进行有效性验证,然后以中断号为索引查询中断重映射表,代替外设向目标发送中断。

图7-61(宏观)

在初始化过程中,QEMU会在VM的fd上调用ioctl(KVM_IRQFD)设置一个eventfd与VFIO设备的虚拟中断号virq联系起来,当eventfd上有信号时则通过vfio驱动及kvm向虚拟机注入中断,且中断号为之前Guest中的virq。

同时,QEMU还会在VFIO设备的fd上调用ioctl(VFIO_DEVICE_SET_IRQS)通过vfio驱动在Host上申请真正的透传设备中断号,当vfio-pci驱动接收到直通设备的中断时就会通过ISR中断handler向前述eventfd发送信号。

这样即完成了物理设备触发中断、虚拟机接收中断的流程。

以MSI中断为例,当虚机内部为透传设备配置中断时,会触发vm_exit,这时会调用qemu中vfio_pci_write_config->vfio_msi_enable().

Qemu-6.2.0/hw/vfio/pci.c static void vfio_msi_enable(VFIOPCIDevice *vdev) { …… for (i = 0; i < vdev->nr_vectors; i++) { …… /* Attempt to enable route through KVM irqchip, default to userspace handling if unavailable. */ vfio_add_kvm_msi_virq(vdev, vector, i, false); kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &vector->kvm_interrupt, NULL, virq) kvm_irqchip_assign_irqfd(s, n, rn, virq, true); kvm_vm_ioctl(s, KVM_IRQFD, &irqfd); //向KVM中注入监听事件(在kvm中建立virq和eventfd的关联) } vfio_enable_vectors(vdev, false){ fds = (int32_t *)&irq_set->data; for (i = 0; i < vdev->nr_vectors; i++) { if (vdev->msi_vectors[i].use) { if (vdev->msi_vectors[i].virq < 0 || (msix && msix_is_masked(&vdev->pdev, i))) { fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); } else { fd = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt); } } fds[i] = fd; } ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set); //利用vfio提供的ioctl命令为透传设备申请真正的中断 } …… }

当透传设备产生中断时,vfio_msihandler ISR执行(MSI中断),该函数不做实际的服务程序处理,仅仅通过eventfd_signal激活irqfd_inject,然后最终调用arch相关回调向虚机注入中断,中断号即为虚机配置透传设备时的中断号。

图7-61(微观)

http://www.jsqmd.com/news/544262/

相关文章:

  • Unity AssetBundle内存管理指南:如何避免资源泄漏和性能问题
  • 绝区零一条龙:3步快速配置的智能自动化助手完整指南
  • 重构黑苹果配置体验:OpCore-Simplify自动化工具如何让复杂适配变简单
  • 提升代码可读性实战:coze-loop优化Python循环与函数调用案例分享
  • composer/semver 快速入门:10分钟学会版本比较与约束解析
  • 开源精品:夜莺Nightingale,企业级观测平台新选择
  • Claude Code Channels 取代 OpenClaw 的真相:15 分钟让 Mac Mini 变成 24/7 手机遥控 Agent
  • GLM-4-9B-Chat-1M实战案例:新闻媒体长篇调查报道事实核查与信源标注辅助
  • OpenClaw环境隔离:GLM-4.7-Flash多项目配置方案
  • 从Log4Shell漏洞看Java安全:为什么一个日志框架能“引爆”互联网?给开发者的深度复盘与防护清单
  • 【计算机网络】网络层次划分
  • DZ-FaceDetailer终极指南:如何在ComfyUI中免费实现专业级人脸修复增强
  • 2025年全国青少年信息素养大赛初赛真题(算法创意实践挑战赛C++初中组:文末附答案)
  • 能够将随意一张图,转换成Landing Page背景图的实战Prompt,亲测有效,屡试不爽
  • 3个维度掌控微信聊天记录:WeChatMsg数据管理全攻略
  • QT ModbusTcp主站开发实战:从连接配置到数据读取的完整流程
  • 5大核心特性:构建专业级卡牌游戏UI的Unity框架解决方案
  • JeecgBoot AI低代码开发平台完整实战指南:从零构建企业级智能应用
  • 尚硅谷Docker核心技术
  • 2026年洛阳GEO优化公司推荐Top5:从技术实力到效果落地的深度评估 - 小白条111
  • 从SWF中提取供应链配置:JPEXS Free Flash Decompiler安全研究报告
  • Rainmeter系统服务描述API:编程获取/设置完全指南
  • OCAuxiliaryTools:重新定义OpenCore配置的全流程管理方案
  • 为什么这款免费播放器能征服三大系统?终极跨平台体验揭秘
  • RSTP 保护机制
  • 危险品物流运输平台全景扫描:2026选运输平台就看这家 - 速递信息
  • 如何永久保存微信聊天记录:本地备份与数据分析完整指南
  • LivePortrait人像动画技术:3步实现高效肖像动画生成与编辑
  • 2026年芜湖豆包GEO优化公司Top5:从技术到效果的选型全指南 - 小白条111
  • MogFace人脸检测部署教程:ModelScope Pipeline自动加载configuration.json配置详解