ARTICLE DETAIL

资讯详情

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

KVM + VFIO 实战:银河麒麟 V11 上直通 RTX 5080 的完整指南

KVM + VFIO 实战:银河麒麟 V11 上直通 RTX 5080 的完整指南 把一张新款的 RTX 5080 整卡直通给虚拟机宿主机只留一张 GT 710 亮机卡负责显示输出听上去好像就是几条命令的事。但真正在银河麒麟高级服务器操作系统 V11 上把这套 KVM/QEMU libvirt VFIO 方案跑通牵扯到的内核参数、IOMMU 分组、虚拟机固件、NVIDIA 驱动策略每一项都能让你折腾到怀疑人生。我这台机器是 Intel i7 平台虚拟化层全部走开源方案宿主机装银河麒麟服务器版 V11。核心目标很明确宿主系统正常显示、虚拟机独占 RTX 5080 的全部算力、两边互不干扰。如果你也要做 GPU 直通或者刚好遇到“虚拟机认不到卡”“Windows 下驱动报 Code 43”“重启后设备失踪”这类问题这篇实践记录应该能帮你省下不少时间。先说结论整套方案可行计算性能损耗很小真正的坑基本都集中在启动阶段的设备分配和驱动侧。1. 方案选型为什么是“大卡算力 亮机卡 直通”的组合1.1 算力卡直通而不是 vGPU/MDev拿到 RTX 5080 之后我第一个考虑过的方案其实是 vGPU 虚拟化也就是把一张物理卡切成多个虚拟 GPU 分给好几台虚拟机。这个思路在数据中心里很常见但对桌面工作站级别的需求来说有两个现实障碍一是 NVIDIA 的 vGPU 授权和驱动管理非常繁琐个人环境没必要给自己找这个麻烦二是 16GB 显存切分之后单台虚拟机能拿到的算力和显存都会缩水某些计算任务反而跑不动。VFIO 直通就不一样它把整张物理显卡直接交给某一台虚拟机独占。虚拟机里的驱动面对的是真实硬件不需要任何中间层翻译性能接近物理机。对推理、渲染、视频编解码这类任务来说这个“独占”是最舒服的。1.2 GT 710 亮机卡的价值为什么还要专门插一张 GT 710很多人第一次做 GPU 直通时会忽略一个关键问题宿主系统本身也需要显示输出。RTX 5080 一旦绑给虚拟机宿主机上就很难再正常使用这块卡了。与其每次都拔线、切输出口不如直接加一张便宜的 GT 710 做宿主显示。这张卡性能非常弱但胜在驱动稳定、功耗低让桌面环境、Xorg、显示管理器跑在它上面完全够用。这样一来 RTX 5080 从开机那一刻起就可以被 vfio-pci 驱动接管宿主系统不会尝试加载它的驱动也就不会出现“宿主抢卡”导致的黑屏或设备冲突。1.3 Intel i7 平台和麒麟 V11 的搭配Intel i7 平台的虚拟化特性很完善VT-x 管 CPU 虚拟化VT-d 管设备直通KVM 对 Intel IOMMU 的支持路径非常成熟。相比某些平台上 IOMMU 分组乱七八糟的情况Intel 桌面平台只要 BIOS 里把 VT-d 打开大部分 PCIe 设备的分组都比较干净这是 GPU 直通能顺利走下去的硬件基础。银河麒麟高级服务器操作系统 V11 虽然有自己的软件生态但底层兼容 RHEL 系的包管理和系统结构所以 qemu、libvirt、virt-install 这些虚拟化组件可以直接用 yum/dnf 装。换句话说你在 CentOS/RHEL 上积累的 KVM 经验在麒麟 V11 上基本都能复用命令习惯也大差不差。2. 环境准备内核参数、模块与硬件拓扑检查2.1 先确认硬件虚拟化能力在修改任何配置之前先把宿主机的基础能力确认一遍。这一步看起来简单但我见过不少人在 BIOS 没开 VT-d 的情况下折腾了半天 IOMMU 分组纯浪费时间。grep -E vmx|svm /proc/cpuinfo看到 vmx 说明 Intel 虚拟化已经开启。接着用 dmesg 检查 VT-d 是否被内核识别dmesg | grep -i -e DMAR -e IOMMU如果这条命令没有任何输出大概率是 BIOS 里 VT-d 没开或者是 BIOS 里叫法不同。Intel 平台一般叫“VT-d”有些主板在超频菜单里有些在高级/北桥配置里。开启后保存重启再查一次。有些主板还有 SR-IOV 开关虽然普通 GPU 直通用不到但顺手打开没有坏处以后如果做网卡虚拟化也用得上。该开的开完之后还要确认一下当前内核uname -rRTX 5080 是新一代显卡如果宿主内核太老后续驱动加载和 vfio-pci 的兼容性都可能出问题。建议内核至少在 5.15 以上能用更新主线内核更好。2.2 给内核加 IOMMU 参数IOMMU 默认不一定完全开启需要显式告诉内核。用 grubby 修改内核引导参数是 RHEL 系发行版比较标准的做法麒麟 V11 也支持grubby --update-kernelALL --argsintel_iommuon iommuptiommupt的意思是让没有直通需求的设备尽量走常规路径减少 IOMMU 翻译开销对宿主整体性能更友好。改完之后重新生成引导配置grub2-mkconfig -o /boot/grub2/grub.cfg然后重启。重启后再次确认参数生效cat /proc/cmdline看到intel_iommuon iommupt就说明内核已经带着这两个参数启动了。另外提醒一句改 grub 前先备份虚拟机直通这种事情最怕的就是宿主机起不来备份一个 grub.cfg 成本极低但能救命。2.3 验证 IOMMU 分组IOMMU 分组决定了哪些 PCIe 设备可以被单独直通。如果你的显卡和一个网卡、一个 USB 控制器被分在同一组那你必须把整组设备全部直通过去或者放弃直通否则内核不会放行。我一般用一个简单脚本把分组情况列出来#!/bin/bash for g in /sys/kernel/iommu_groups/*; do echo IOMMU Group ${g##*/}: for d in $g/devices/*; do DEVICE_ID${d##*/} echo -n lspci -nns $DEVICE_ID done done输出结果里重点看 RTX 5080 的 PCI 地址。用lspci | grep -i nvidia先定位到卡lspci -nn | grep -i nvidia一般会看到类似01:00.0 VGA compatible controller [0300]: NVIDIA Corporation ...和01:00.1 Audio device [0403]: NVIDIA Corporation ...两行。前者是显卡主体后者是显卡自带声卡。查看分组脚本输出后如果这两个设备在同一个 IOMMU group 里那直通时必须把 0x0 和 0x1 一起处理这样最稳妥。2.4 用 vfio-pci 驱动接管显卡确认分组没问题之后把 RTX 5080 的 vendor:device ID 告诉 vfio-pci 驱动让它提前接管。NVIDIA 显卡的 vendor ID 固定是 10dedevice ID 每代卡不同以你机器上lspci -nn看到的为准。方法是创建一个 modprobe 配置echo options vfio-pci ids10de:xxxx,10de:yyyy /etc/modprobe.d/vfio.conf其中10de:yyyy是对应声卡的 ID。然后更新 initramfs否则重启后模块参数不会带进来dracut -f重启后查看显卡是否已经被 vfio-pci 接管lspci -nnk -d 10de:如果 Kernel driver in use 一栏显示vfio-pci说明接管成功。注意不要在这个阶段安装宿主机上的 NVIDIA 驱动除非你能保证它只绑定 GT 710。否则宿主驱动一加载直通就会乱套。3. 虚拟化组件安装与虚拟机创建3.1 安装 QEMU/KVM/libvirt 工具链银河麒麟 V11 安装虚拟化组件的命令很直接和 RHEL 系习惯一致yum install -y qemu-kvm libvirt virt-install edk2-ovmf virtio-win这几个包各司其职qemu-kvm是虚拟机运行时libvirt是管理接口virt-install用来命令行创建虚拟机edk2-ovmf提供 UEFI 固件virtio-win装完后能在 Guest 里挂载提供 Windows 下的 virtio 磁盘和网卡驱动。装完后启动 libvirtd 并设置开机自启systemctl enable --now libvirtd然后看一眼默认网络是否正常virsh net-list --all如果 default 网络没启动用virsh net-start default拉起来。没有网络的话虚拟机装完系统之后连不上网后面装驱动全靠挂 ISO会非常痛苦。3.2 用 virt-install 创建 Windows 虚拟机我这次 Guest 选的是 Windows Server 系统因为要跑计算负载图形桌面不是重点。创建命令如下virt-install \ --name win-gpu \ --memory 32768 \ --vcpus 16 \ --cpu host-passthrough,cache.modepassthrough \ --disk path/data/vms/win-gpu.qcow2,size200,formatqcow2,busvirtio \ --cdrom /data/iso/Windows.iso \ --os-variant win2k22 \ --network networkdefault,modelvirtio \ --graphics spice \ --video qxl \ --boot uefi逐个解释关键参数。--cpu host-passthrough让虚拟机直接暴露宿主 CPU 的特性集合对 NVIDIA 驱动的兼容性最好虚拟机里跑 CPU 密集型任务也不会有太大的性能损失。--boot uefi指定使用 OVMF 固件现代显卡通常需要 64 位 PCI BAR 地址空间传统 SeaBIOS 在这块很容易撞上地址分配问题。os-variant可以根据你实际安装的 Windows 版本调整用osinfo-query os可以查看支持列表。这台虚拟机我给的内存是 32GBCPU 16 核具体按你物理机资源灵活调。但有一点要注意RTX 5080 有 16GB 显存OVMF 在启动时要为显卡的 BAR 空间预留地址如果你的虚拟机内存分配过高、又用了很老的机器类型偶尔会出现地址冲突。解决办法就是坚持 q35 机器类型 OVMF别再用 i440fx 老古董。3.3 安装系统并注入 virtio 驱动Windows 安装镜像启动后如果安装界面里看不到磁盘多半是因为磁盘总线是 virtioWindows 没有自带驱动。这时候从 virtio-win ISO 里加载驱动即可。virtio-win 安装后 ISO 通常位于/usr/share/virtio-win/virtio-win.iso在虚拟机里挂载后选择对应系统的viostor驱动磁盘就能识别。系统装完先别急着装显卡驱动先把 virtio 网卡驱动也装上保证网络通。然后安装 QEMU Guest Agent这个对后续virsh平滑关机和获取虚拟机状态很有帮助。3.4 修改 domain XML 添加 GPU 直通设备虚拟机关机后用virsh edit win-gpu修改配置。把 PCI hostdev 加进去是核心步骤。下面是我最终使用的 hostdev 配置hostdev modesubsystem typepci managedyes driver namevfio/ source address domain0x0000 bus0x01 slot0x00 function0x0/ /source rom baron/ address typepci domain0x0000 bus0x07 slot0x00 function0x0/ /hostdevmanagedyes的意思是让 libvirt 在虚拟机启动时自动把设备绑定到 vfio-pci关机后自动归还宿主省去手动 detach/attach 的麻烦。source 里的地址是你物理卡在宿主上的 BDFaddress 里的地址是虚拟机 PCI 总线上的目标位置一般让 libvirt 自动分配即可。如果 NVIDIA 卡的声卡 function 也在这个 IOMMU group 里建议把它一起直通过去或者也绑定 vfio-pci避免虚拟机启动时设备分配不完整导致的奇怪问题。我实际测试时只直通显卡主体也能启动但偶尔会出现声卡中断消息刷屏把两个 function 一起直通后就安静了。还要检查 XML 里有没有这几个 featurefeatures acpi/ apic/ hyperv relaxed stateon/ vapic stateon/ spinlocks stateon/ /hyperv kvm hidden stateon/ /kvm /featureshidden stateon/会向 Guest 隐藏 KVM 虚拟化特征这一步对 NVIDIA 驱动尤其重要。NVIDIA 的 Windows 驱动对虚拟机环境有检测机制发现自己跑在虚拟机里时可能拒绝启动 GPU 甚至直接报错。虽然不是每次必现但做直通时把这个 feature 加上是标准操作。3.5 CPU 绑核与内存预留如果追求极致性能可以把虚拟机的 vCPU 物理绑定到特定核心上。用virsh vcpupin或者直接在 XML 的 cputune 里写cputune vcpupin vcpu0 cpuset0/ vcpupin vcpu1 cpuset2/ /cputune避开超线程的两个逻辑核通常效果更好让每个 vCPU 独占一个物理核的单个线程。这套配法对 GPU 直通场景不是必需但在 CPU 频繁参与数据传输时能降低抖动。内存方面RTX 5080 有 16GB 显存虚拟机建议分 32GB 内存才算匹配。宿主物理内存不足时会出现频繁 swap直通性能会很难看。4. Guest 系统内的驱动安装与验证4.1 Windows Guest 下的 NVIDIA 驱动直通配置好后启动虚拟机进入 Windows 后打开设备管理器正常情况下应该能看到一个带黄色感叹号的“Microsoft 基本显示适配器”或者未知 PCI 设备。这时安装 NVIDIA 官方驱动。驱动版本尽量选最新RTX 50 系列的架构很新老版本驱动大概率不认。安装完成后在设备管理器里确认显卡状态右键属性如果显示“这个设备运行正常”说明直通已经成功。如果出现 Code 43也就是 Windows 说设备报告错误NVIDIA 驱动初始化失败别慌按下面几个方向排查确认 XML 里有hidden stateon/隐藏 KVM 痕迹CPU 模式必须是 host-passthrough必须用 OVMF 启动虚拟机别用 SeaBIOS关闭 Windows 的 Secure Boot 试试换不同版本的 NVIDIA 驱动Code 43 本质上是驱动在初始化时发现环境异常而主动拒绝工作我遇到过换一个驱动版本就好、或者把 hyperv 相关 feature 微调一下就好的情况。总之多做组合试验不要一条路走到黑。4.2 Linux Guest 下的驱动安装如果 Guest 是 Linux直通后的驱动安装更简单。以 Ubuntu/Debian 系为例sudo apt install nvidia-driver-550装完确认一下 nouveau 确实没生效lsmod | grep nouveau如果还有 nouveau 输出说明驱动没有正确接管需要重新配置。正常安装后运行nvidia-smi能看到显卡型号、驱动版本、显存容量以及当前功耗就说明直通环境完全可用了。4.3 验证直通后的实际性能我跑了一个简单的 CUDA 向量加法测试对比虚拟机和物理机的执行时间结果两者几乎没差别。GPU 直通的开销主要体现在 PCIe 路径上的少量地址翻译和中断处理对于批量计算任务来说影响很小。可以用这些命令做基础验证nvidia-smi glxinfo -B vulkaninfo --summary能看到完整的 GPU 信息并且跑分与物理机差距在 3% 以内基本说明直通是健康的。5. 常见问题与排查手记5.1 虚拟机里看不到显卡先确认宿主机侧 vfio-pci 是否成功接管lspci -nnk -d 10de:如果显示的 Kernel driver 不是 vfio-pci说明设备没被正确绑定。回头检查 modprobe 配置和 initramfs 是否更新。还有一种情况是 IOMMU 分组被拆散导致部分 function 不能直通这时候优先尝试把整组设备都加入直通列表。5.2 设备复位失败虚拟机重启后显卡失踪这个问题通常表现为第一次冷启动直通正常但 Guest 重启后显卡在宿主侧变成不可用状态。这是因为显卡没有正确执行复位FLR/Function Level Reset重启后残留状态污染了硬件。解决方向有两个一个是虚拟机里关闭再启动而不是重启系统让 QEMU 有机会做完整 teardown另一个是改用 PCIe Root Port 拓扑尽量避免多个设备共享同一个复位域。virsh nodedev-reset pci_0000_01_00_0也可以手动触发复位但如果是 pcie-root-port 下的设备一般不会遇到这个问题。5.3 宿主机黑屏或登录界面抢占显卡如果开机后虚拟机能启动但宿主机显示器没画面大概率是 GDM/显示管理器尝试在 RTX 5080 上做输出。解决办法就是用 GT 710 做宿主显示并确保 vfio-pci 在显示管理器启动前接管 RTX 5080。可以把 vfio-pci 模块放进/etc/modprobe.d/配合 dracut 更新这样开机时内核就直接绑定了不给宿主驱动任何机会。5.4 常见问题速查表现象常见原因处理方式Guest 中显卡感叹号 / Code 43驱动检测到虚拟化环境隐藏 KVM使用 host-passthrough换驱动版本虚拟机启动后显卡未出现vfio-pci 未接管设备检查 modprobe 配置、initramfs、IOMMU 分组宿主机黑屏显示服务抢占 RTX 5080用 GT 710 输出vfio-pci 提前绑定虚拟机关机后设备 busy宿主机驱动或进程占用设备关闭显示管理器blacklist 对应模块Guest 重启后设备消失显卡复位不彻底使用 pcie-root-port必要时手动 nodedev-reset直通后性能差异大内存不足/CPU 绑核没做增加内存做 vCPU 绑核6. 个人实操体会整套配置做完我最想强调的还是“先查分组、再改内核、最后动虚拟机”。IOMMU 分组这个事如果一开始没看清后面所有步骤都会卡在设备分配上。我这次运气不错RTX 5080 的两个 function 在同一个分组没碰过需要打 ACS 补丁的麻烦。另外GT 710 亮机卡这种小配件平时觉得不起眼但在 GPU 直通方案里价值很大它把宿主显示和算力卡彻底解耦让整个系统稳定了一个数量级。还有一点体会是驱动版本的耐心。RTX 50 系列很新Guest 侧的 NVIDIA 驱动只要版本对一次就能点亮版本不对就会重复 Code 43。做这种项目别想着“一步到位”多留几个驱动版本备用多记录每一步的 dmesg 和 virsh 状态等最终跑通了再回头看所有坑其实都有明确线索。
返回列表