ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PCIe直通与SR-IOV实战:从枚举、IOMMU到VFIO的底层原理与避坑指南

PCIe直通与SR-IOV实战:从枚举、IOMMU到VFIO的底层原理与避坑指南 1. 从一块网卡说起PCIe直通与SR-IOV到底在解决什么问题搞虚拟化的朋友大概率都遇到过这个场景宿主机上插了一张万兆网卡或者一张计算卡虚拟机里跑业务却只能走虚拟网桥吞吐上不去、延迟下不来CPU还被软中断吃得干干净净。这时候老鸟通常会甩出两个词——PCIe直通和SR-IOV。听起来很硬核但说白了就是两件事前者是把整块物理设备整租给一台虚拟机后者是把一块物理设备隔断成多个独立房间分租给多台虚拟机。这两个技术背后牵扯的东西非常多PCIe总线的枚举与配置空间、IOMMU的地址翻译与中断重映射、ACS对P2P流量的隔离控制、VFIO框架如何把设备安全地交给用户态、以及SR-IOV里PF和VF的层级关系。任何一个环节没搞明白轻则设备直通失败、虚拟机起不来重则整机掉卡、链路降速、AER报错刷屏。热词里提到的掉卡、降speed/lane、aer等问题、pcie枚举过程、pcie稳定性/兼容性问题全都是这条链路上的真实痛点。这篇内容适合谁看如果你是在做虚拟化平台、云主机底层、DPDK/SPDK高性能网络、或者AI训练集群里做GPU/网卡资源切分的工程师那这篇基本就是给你写的。如果你只是刚接触PCIe、想搞清楚为什么我的设备直通进去识别不到也能从里面找到排查思路。我会尽量把底层原理讲透同时给出可以直接抄的配置和排查命令不玩虚的。需要先说明一点下面涉及的具体命令、参数、寄存器偏移都是基于业界常见实践和公开规范整理的通用做法不同平台Intel/AMD/ARM、不同内核版本、不同设备厂商会有差异实际落地时请以你手上的硬件手册和内核文档为准。2. 先搞懂PCIe枚举设备是怎么被发现的2.1 枚举过程的本质是一棵树的深度优先遍历很多人一上来就研究直通结果连设备在系统里怎么出现的都没搞明白。PCIe的拓扑是一棵树Root Complex是根下面挂Root Port、Switch、Endpoint。系统启动时固件BIOS/UEFI或者操作系统会从总线0、设备0、功能0开始逐个扫描每个总线号下的设备号读Vendor ID。如果Vendor ID不是0xFFFF说明这个位置有设备再去读Header Type判断它是桥还是端点。如果是桥就给它分配一个新的总线号继续往下扫。这个过程就是PCIe枚举。它决定了你系统里lspci能看到什么。理解枚举对直通至关重要因为直通的前提是设备必须被正确枚举出来并且挂在一个支持隔离的Root Port或Switch端口下。你可以用下面这条命令看整棵拓扑树lspci -tv输出会以树形展示桥和设备的关系。如果发现某张卡挂在了一个来路不明的桥后面或者多个设备共享同一个Root Port且没有ACS支持那直通的隔离性就要打问号了。2.2 配置空间直通时真正被搬走的东西每个PCIe设备都有一段配置空间传统PCI是256字节PCIe扩展到了4KB。前64字节是标准头里面有Vendor ID、Device ID、Command、Status、BARBase Address Register等。BAR决定了设备需要多少MMIO空间和IO空间枚举时固件或内核会给BAR分配物理地址。直通的时候虚拟机要看到的其实是设备原样的配置空间但BAR指向的物理地址需要经过IOMMU重映射才能被虚拟机安全访问。这就是为什么IOMMU是直通的基石——没有它虚拟机里的驱动直接拿物理地址去访问等于让租客拿着整栋楼的钥匙。查看某个设备的配置空间lspci -s 01:00.0 -xxx-xxx会 dump 前256字节-xxxx能看完整的4KB。排查BAR分配异常、Capability结构错乱时非常有用。2.3 枚举阶段的常见坑掉卡与降速热词里掉卡、降speed/lane是枚举和链路训练阶段的经典问题。链路训练Link Training发生在设备上电后PCIe双方协商链路宽度lane和速率speed。如果信号完整性差、金手指氧化、供电不稳就可能协商到x1或者Gen1甚至直接训练失败导致设备不出现。排查链路状态lspci -s 01:00.0 -vvv | grep -i LnkCap\|LnkStaLnkCap是链路能力最大能到多少LnkSta是当前状态。如果Cap是x16 Gen4Sta却只有x4 Gen1那基本就是物理层或者插槽的问题。这时候别急着怀疑驱动先换插槽、擦金手指、检查供电。注意有些主板会把CPU直连的x16拆分成x8x8给两个插槽如果你只插一张卡却只跑出x8先查主板手册的lane分配策略不一定是故障。3. IOMMU与ACS隔离性的两道命门3.1 IOMMU不只是地址翻译还有中断重映射IOMMUIntel叫VT-dAMD叫AMD-Vi干两件事一是DMA重映射把设备发起的DMA地址从IOVA翻译成物理地址并且限制设备只能访问被授权的区域二是中断重映射Interrupt Remapping把设备的中断请求安全地投递到指定CPU和虚拟机。没有IOMMU设备直通就是灾难——设备可以DMA到任意物理内存虚拟机之间毫无隔离。开启IOMMU通常需要在BIOS里打开VT-d/AMD-Vi内核启动参数加intel_iommuon iommuptiommupt是pass-through模式对没被直通的设备用恒等映射减少性能开销。AMD平台对应amd_iommuon。验证IOMMU是否生效dmesg | grep -i -e DMAR -e IOMMU看到DMAR: IOMMU enabled之类的字样才算成功。3.2 ACS决定P2P流量能不能被隔离ACSAccess Control Services是PCIe的一个Capability它控制Peer-to-Peer流量能不能在Switch内部直接转发还是必须上送到Root Complex。为什么直通要关心ACS因为如果两个设备挂在同一个没有ACS的Switch下它们之间的P2P DMA可以绕过IOMMU的隔离A设备能直接读写B设备甚至B设备背后的内存隔离就形同虚设。检查设备是否支持ACSlspci -s 01:00.0 -vvv | grep -i ACS如果显示ACSCap但ACSCtl里没有开启可以用内核参数强制pciacs_mask01:00.0或者更常见的做法是用pcie_acs_override补丁强制拆分IOMMU组。但这里要提醒一句ACS override是我知道有风险但我接受的操作它牺牲了部分安全性换取分组灵活性生产环境慎用。3.3 IOMMU分组直通的最小单位IOMMU以组group为单位做隔离同一个组里的设备要么一起直通要么都不直通。查看分组for d in /sys/kernel/iommu_groups/*/devices/*; do n${d#*/iommu_groups/*}; n${n%%/*} printf IOMMU Group %s $n lspci -nns ${d##*/} done如果发现你要直通的网卡和一堆无关设备比如USB控制器、SATA控制器分在同一个组那直通就会把那些设备一起带走宿主机可能直接失去磁盘或键鼠。这时候要么换插槽换到独立的Root Port下要么上ACS override要么放弃。实操心得优先通过物理插槽调整来获得干净的IOMMU分组这比打补丁靠谱得多。服务器主板通常有多个CPU直连的PCIe插槽换一个往往就分开了。4. VFIO把设备安全地交给用户态4.1 VFIO的定位与工作模型VFIOVirtual Function I/O是Linux内核的一套框架它让用户态程序比如QEMU能够安全地访问物理设备。它依赖IOMMU做隔离把设备的各种资源MMIO区域、配置空间、中断抽象成文件描述符用户态通过ioctl来操作。VFIO的核心组件vfio-pci绑定设备的驱动接管设备后原驱动不再工作vfio_iommu_type1IOMMU类型1的容器驱动管理IOMMU映射vfio platform用于平台设备直通时设备从原驱动解绑绑定到vfio-pci然后QEMU通过-device vfio-pci把它交给虚拟机。4.2 绑定与解绑的完整操作先确认设备IDlspci -nns 01:00.0假设输出是01:00.0 0200: 8086:10fb厂商8086设备10fb。解绑原驱动echo 0000:01:00.0 /sys/bus/pci/devices/0000:01:00.0/driver/unbind绑定vfio-pciecho 8086 10fb /sys/bus/pci/drivers/vfio-pci/new_id或者用driver_override方式更稳妥echo vfio-pci /sys/bus/pci/devices/0000:01:00.0/driver_override echo 0000:01:00.0 /sys/bus/pci/drivers/vfio-pci/bindQEMU启动参数大致是-device vfio-pci,host01:00.0,idnet04.3 直通后设备识别不到的排查顺序这是最高频的问题。按下面顺序查宿主机lspci能不能看到设备看不到就是枚举/物理层问题IOMMU组是否干净dmesg有没有not in a group报错设备是否成功绑定vfio-pcilspci -k看Kernel driver in useQEMU是否报Failed to bind或group not viable虚拟机里lspci能否看到看不到可能是QEMU参数或BIOS问题虚拟机里能看到但驱动加载失败多半是BAR映射或中断问题常见坑有些设备有多个Function比如网卡带一个管理功能只直通其中一个Function会导致整个设备异常。要么全直通要么用FLRFunction Level Reset先复位。5. SR-IOV一块卡切成多块用的底层逻辑5.1 PF与VF的层级关系SR-IOVSingle Root I/O Virtualization的核心思想是物理设备PFPhysical Function支持创建多个虚拟功能VFVirtual Function每个VF有自己独立的配置空间、BAR、中断可以被独立分配给虚拟机。PF负责管理VF负责干活。一个支持SR-IOV的网卡PF是01:00.0创建出来的VF可能是01:00.1、01:00.2……每个VF在系统里都是一个独立的PCIe设备有独立的BDF。开启VFecho 4 /sys/class/net/eth0/device/sriov_numvfs这会在PF下创建4个VF。查看lspci | grep -i virtual function5.2 VF的隔离依赖什么VF虽然独立但它和PF共享物理链路和部分硬件资源。隔离性依赖IOMMU每个VF的DMA必须被独立翻译和限制ACS如果VF之间或VF与PF之间有P2P路径需要ACS来阻断硬件队列隔离网卡的TX/RX队列、中断向量必须硬件级隔离这也是为什么有些廉价网卡号称支持SR-IOV实际用起来VF之间互相干扰——硬件隔离做得不到位。5.3 SR-IOV与直通的取舍维度PCIe直通SR-IOV粒度整设备单VF隔离性强独占依赖硬件和IOMMU密度低一设备一VM高一设备多VM迁移难相对容易性能接近原生接近原生但有共享开销适用GPU、专用卡网卡、部分加速卡选型逻辑很直接设备稀缺、要极致性能、不需要多VM共享就直通设备贵、要多租户共享、要密度就SR-IOV。GPU现在也有SR-IOV比如某些厂商的vGPU方案但成熟度和网卡比还有差距。6. 稳定性与兼容性掉卡、降速、AER的实战排查6.1 AER报错怎么读AERAdvanced Error Reporting是PCIe的错误上报机制。dmesg里出现AER: Corrected error通常无害但Uncorrected (Fatal)就要重视了。常见的有Bad TLP链路传输错误多为信号完整性问题Bad DLLP数据链路层错误Receiver Error接收端物理层错误Completion Timeout设备没在规定时间响应排查思路先看是Correctable还是Uncorrectable再看是哪个设备报的。如果是直通设备报错先确认是不是ACS/IOMMU配置问题导致设备行为异常。lspci -s 01:00.0 -vvv | grep -i AER\|UESta\|CESta6.2 降速降lane的定位前面提过LnkCap和LnkSta的对比。如果Sta低于Cap逐项排查插槽是否支持该速率和宽度线缆/转接卡是否达标尤其是M.2转PCIe、Oculink等主板lane拆分策略设备固件是否需要更新有些平台还支持动态降速省电LnkCtl里的ASPM设置会影响。如果确认是ASPM导致的性能波动可以在内核参数里关掉pcie_aspmoff6.3 热插拔与枚举的交互热词里提到pcie热插拔功能。热插拔依赖设备的Hot-Plug Capability和平台的Attention Button/Power Indicator支持。在虚拟化场景里热插拔常用于动态给虚拟机加设备。但要注意直通设备的热拔除必须先在虚拟机里安全卸载驱动再在宿主机操作否则容易触发AER或者设备状态错乱。7. 常见问题速查表与避坑清单现象可能原因排查方向虚拟机看不到直通设备未绑定vfio-pci / IOMMU组不干净lspci -k、IOMMU分组脚本直通后宿主机失去磁盘设备与存储控制器同组换插槽或ACS override设备频繁掉线供电/信号/ASPM换插槽、关ASPM、查AER链路降速插槽/线缆/拆分策略对比LnkCap与LnkStaVF创建失败硬件不支持/固件未开查/sys/class/net/*/device/sriov_totalvfs中断不触发中断重映射未开查IOMMU中断重映射日志性能不达预期未开iommupt / 队列未隔离检查内核参数和队列配置避坑清单直通前一定先确认IOMMU分组干净别等虚拟机起不来才回头查SR-IOV的VF数量不要超过硬件totalvfs上限生产环境慎用ACS override它牺牲隔离性直通设备的热拔除要按虚拟机内卸载→宿主机解绑的顺序遇到AER先分清Correctable和Uncorrectable别一上来就换硬件8. 我个人在实际操作中的几点体会折腾这套东西这么多年最大的感受是大部分直通问题都不是虚拟化层的问题而是PCIe物理层和固件层的问题。我见过太多人一上来就改QEMU参数、换内核版本结果最后发现是插槽lane分配不对或者BIOS里VT-d根本没开。第二个体会是IOMMU分组是直通体验的分水岭。分组干净后面一路顺分组混乱你会花大量时间在ACS override和各种workaround上而且心里始终不踏实。所以选主板和插槽的时候多花十分钟看手册能省后面十个小时。第三个是SR-IOV的VF隔离别只看厂商宣传。实际压测一下VF之间的带宽干扰、中断延迟才能知道这块卡到底能不能上生产。有些卡VF数量一多单个VF的性能断崖式下跌这种就得重新评估方案。最后分享一个小技巧排查直通问题时养成先看dmesg和lspci -vvv的习惯把设备的链路状态、ACS、AER、IOMMU组信息一次性抓全比东查一点西查一点效率高得多。很多时候答案就明明白白写在dmesg里只是被刷屏淹没了。
返回列表