收起左侧

飞牛 fnOS 在 PVE 中使用 Intel iGPU SR-IOV VF 的完整配置指引

1
回复
76
查看
[ 复制链接 ]

0

主题

1

回帖

0

牛值

江湖小虾

这份文档基于一次完整的实战排障过程整理,目标是:在 Proxmox VE 宿主机上启用 Intel 核显 SR-IOV,将一个 VF 直通给飞牛 fnOS 虚拟机,并最终让飞牛视频服务成功使用 GPU 解码/转码。但是系统显示的不太对,这个无所谓了。

TL;DR

Intel i3-12100 的显卡通过 SR-IOV 拆分出了 3 个 VF,把第三个 VF 分配给飞牛的 vm。

image.png

飞牛影视中正常开启 GPU 加速

image.png

视频中使用 GPU 加速

image.png

资源利用率 OK,如果用 CPU 的话 CPU 早爆了

image.png

注:下面的这些部分是基于我和 chatgpt 5.4 对话解决问题过程中总结的部分,可以丢给你的 AI Agent 让他一步步指导你。

目录

  1. 适用范围与最终目标
  2. 正确架构:PF 留给宿主机,VF 给虚拟机
  3. PVE 宿主机前提条件
  4. PVE 宿主机配置步骤
  5. 把 VF 绑定到 vfio-pci
  6. 宿主机验证
  7. 飞牛 VM 配置
  8. 飞牛 guest 内安装 i915-sriov-dkms
  9. 飞牛 guest 内验证 GPU / VAAPI
  10. 飞牛视频服务的权限与应用层问题
  11. ffmpeg / libva ABI 冲突的处理
  12. 本次排障中踩过的坑
  13. 最终检查清单

1. 适用范围与最终目标

适用于以下场景:

  • 宿主机:Proxmox VE
  • GPU:Intel 核显,支持通过 strongtz/i915-sriov-dkms 实现 SR-IOV
  • 客体:飞牛 fnOS(Linux guest)
  • 目标:给飞牛分配一个 VF,并让飞牛视频服务能使用 GPU 解码/转码

最终成功标志:

  • 宿主机上 00:02.0i915 驱动
  • 宿主机上 00:02.1 ~ 00:02.xvfio-pci 驱动
  • 飞牛 guest 内有 /dev/dri/renderD128
  • vainfo --display drm --device /dev/dri/renderD128 正常
  • 飞牛媒体服务可正常使用 GPU

2. 正确架构:PF 留给宿主机,VF 给虚拟机

这是整套方案里最重要的原则。

功能 应该给谁
00:02.0(PF,主功能) 宿主机 PVE 自己使用,由 i915 驱动
00:02.1 / 00:02.2 / 00:02.3 ...(VF) 分配给虚拟机,通过 vfio-pci 直通

绝对不要把 00:02.0 这个 PF 直通给飞牛。

这样会把宿主机自己的核显主功能拔走,导致 SR-IOV 状态混乱、VM 启动卡死、8006 掉线,甚至宿主机整体失联。

3. PVE 宿主机前提条件

  1. BIOS 中开启 VT-d / Intel IOMMU
  2. PVE 已安装并正常启动
  3. 已安装 i915-sriov-dkms 对应版本
  4. 确认你的核显设备 ID,例如本次为 8086:4692(Alder Lake-S UHD 730)

可先查看设备:

lspci -nn | grep -i 'vga\|display'

4. PVE 宿主机配置步骤

4.1 调整 GRUB 启动参数

宿主机最终采用 i915 路线,而不是 xe 路线。

cp /etc/default/grub /etc/default/grub.bak.$(date +%F-%H%M%S)

sed -i 's#^GRUB_CMDLINE_LINUX_DEFAULT=.*#GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on i915.enable_guc=3 i915.max_vfs=3 module_blacklist=xe"#' /etc/default/grub

grep '^GRUB_CMDLINE_LINUX_DEFAULT' /etc/default/grub

不要保留这些旧参数:

  • xe.max_vfs=...
  • xe.force_probe=...
  • module_blacklist=i915
  • i915.force_probe=${device_id} 这种未展开变量

4.2 固定 VF 数量

apt-get install -y sysfsutils || true

grep -q 'devices/pci0000:00/0000:00:02.0/sriov_numvfs' /etc/sysfs.conf 2>/dev/null \
  && sed -i 's#^devices/pci0000:00/0000:00:02.0/sriov_numvfs = .*#devices/pci0000:00/0000:00:02.0/sriov_numvfs = 3#' /etc/sysfs.conf \
  || echo 'devices/pci0000:00/0000:00:02.0/sriov_numvfs = 3' >> /etc/sysfs.conf

cat /etc/sysfs.conf

4.3 更新引导与 initramfs

update-grub
update-initramfs -u -k all
proxmox-boot-tool refresh

5. 把 VF 绑定到 vfio-pci

目标:宿主机保留 PF,VF 全部交给 vfio-pci,避免宿主机图形栈误占用 VF。

5.1 确保 vfio-pci 开机加载

echo "vfio-pci" >/etc/modules-load.d/vfio.conf
touch /etc/initramfs-tools/modules
grep -qxF 'vfio-pci' /etc/initramfs-tools/modules || echo 'vfio-pci' >> /etc/initramfs-tools/modules

5.2 写 udev 规则绑定 VF

cat >/etc/udev/rules.d/99-i915-vf-vfio.rules <<'EOF'
ACTION=="add", SUBSYSTEM=="pci", KERNEL=="0000:00:02.[1-3]", ATTR{vendor}=="0x8086", ATTR{device}=="0x4692", DRIVER!="vfio-pci", RUN+="/bin/sh -c 'if [ -L /sys/bus/pci/devices/\$kernel/driver ]; then echo \$kernel > /sys/bus/pci/devices/\$kernel/driver/unbind; fi; echo vfio-pci > /sys/bus/pci/devices/\$kernel/driver_override; modprobe vfio-pci; echo \$kernel > /sys/bus/pci/drivers/vfio-pci/bind'"
EOF

5.3 重建 initramfs

update-initramfs -u -k all
proxmox-boot-tool refresh

本次配置里只创建了 3 个 VF,所以规则匹配的是 00:02.1 ~ 00:02.3。如果你后续改成更多 VF,要同步改规则和 i915.max_vfs

6. 宿主机验证

重启宿主机后检查:

cat /proc/cmdline
lspci -nnk -s 00:02
lspci -nn | grep -E '00:02\.[1-3]'
ls -l /dev/dri

预期结果:

  • /proc/cmdline 含有:intel_iommu=on i915.enable_guc=3 i915.max_vfs=3 module_blacklist=xe
  • 00:02.0Kernel driver in usei915
  • 00:02.1 / 00:02.2 / 00:02.3Kernel driver in usevfio-pci
  • /dev/dri 只保留宿主机的 card0renderD128

7. 飞牛 VM 配置

7.1 正确直通 VF

不要传 PF,只传 VF,例如:

qm set 108 --hostpci0 0000:00:02.3,pcie=1

7.2 关闭 vIOMMU

本次排障中,VM 启动时报过:

vfio 0000:00:02.3: Failed to set vIOMMU: aw-bits 48 > host aw-bits 39

根因是 VM 配置里有:

machine: q35,viommu=intel

修复方法:

qm set 108 --machine q35

也就是把 viommu=intel 去掉,只保留 machine: q35

7.3 一个可工作的示例配置

agent: 1
bios: ovmf
boot: order=scsi0
cores: 2
cpu: host
efidisk0: extra:vm-108-disk-0,efitype=4m,pre-enrolled-keys=1,size=1M
hostpci0: 0000:00:02.3,pcie=1
ide2: extra:vm-108-cloudinit,media=cdrom
machine: q35
memory: 4096
name: fnOS
net0: virtio=...,bridge=vmbr0,firewall=1
numa: 0
ostype: l26
scsi0: extra:vm-108-disk-1,iothread=1,size=64G,ssd=1
scsi1: extra:vm-108-disk-2,iothread=1,size=64G,ssd=1
scsihw: virtio-scsi-single
sockets: 1
vga: none

8. 飞牛 guest 内安装 i915-sriov-dkms

这是 guest 内最关键的一步。宿主机 SR-IOV 正常,并不代表飞牛 guest 自己能驱动这个 VF。guest 内同样需要安装 i915-sriov-dkms

8.1 先装依赖

apt update
apt install -y dkms build-essential pciutils vainfo git
apt install -y linux-headers-$(uname -r)

8.2 安装 guest 侧 DKMS 模块

你可以用已下载好的对应版本包,也可以自己通过源码安装。关键是版本要和内核兼容。

8.3 guest 内核参数

guest 最终采用:

i915.enable_guc=3 module_blacklist=xe

本次成功后的 /proc/cmdline 类似:

BOOT_IMAGE=/boot/vmlinuz-6.12.18-trim root=UUID=... ro modprobe.blacklist=pcspkr pcie_aspm=off quiet pcie_aspm=off i915.enable_guc=3 module_blacklist=xe

注意: guest 侧不需要再加宿主机用的 intel_iommu=oni915.max_vfs=... 这些参数。VF 数量由宿主机控制。

9. 飞牛 guest 内验证 GPU / VAAPI

9.1 先看设备与驱动

lspci -nnk | grep -A3 -i 'VGA\|Display'
dmesg | grep -iE 'i915|xe|drm|firmware'
ls -l /dev/dri

成功标志:

  • Kernel driver in use: i915
  • Running in SR-IOV VF mode
  • 出现 /dev/dri/renderD128

9.2 验证 VAAPI

vainfo --display drm --device /dev/dri/renderD128

如果输出中能看到各种 profile,例如:

  • VAProfileH264High
  • VAProfileHEVCMain10
  • VAProfileVP9Profile0
  • VAProfileAV1Profile0

说明 VAAPI 本身已经可用。

10. 飞牛视频服务的权限与应用层问题

10.1 把运行用户加入 videorender

设备权限通常是:

crw-rw---- 1 root video  ...
crw-rw---- 1 root render ...

如果飞牛的登录用户或媒体服务用户不在这些组里,即使 GPU 和 VAAPI 都好了,应用也用不了。

usermod -aG video fn
usermod -aG render fn

执行后需要重新登录会话,再看:

groups
id

预期:

Users video render Administrators

10.2 如果媒体服务不是用 fn 跑的

那应该把真正运行媒体服务的用户加进 video / render,不是只加登录用户。

11. ffmpeg / libva ABI 冲突的处理

这是本次配置里最后一个难点。

现象:

  • vainfo 成功
  • ffmpeg 报:
[AVHWDeviceContext] ... iHD_drv_video.so has no function __vaDriverInit_1_0

这说明不是 GPU 不通,而是 ffmpeg 使用的 VAAPI 用户态栈和驱动 ABI 不匹配

在本次飞牛环境里,vainfo 实际使用的是:

/usr/trim/lib/mediasrv/dri/iHD_drv_video.so

因此需要让应用继承这两个环境变量:

export LIBVA_DRIVER_NAME=iHD
export LIBVA_DRIVERS_PATH=/usr/trim/lib/mediasrv/dri

在某些场景下,还需要补:

export LD_LIBRARY_PATH=/usr/trim/lib/mediasrv:$LD_LIBRARY_PATH

经验结论:

如果 vainfo 能通,而应用内 GPU 不工作,优先怀疑:

  • 运行用户没有权限
  • 应用没有继承正确的 LIBVA_* 环境
  • 应用使用了另一套旧的 ffmpeg / libva

12. 本次排障中踩过的坑

  1. 把 PF 00:02.0 直通给飞牛

    这是最危险的错误,会导致宿主机 i915/SR-IOV 状态混乱,甚至宿主机启动 VM 时失联。

  2. 宿主机仍保留 xe 时代的旧参数

    例如 xe.max_vfsmodule_blacklist=i915。需要完全清理。

  3. VM 开了 vIOMMU

    导致 Failed to set vIOMMU: aw-bits 48 > host aw-bits 39,应去掉 viommu=intel

  4. 只在宿主机装了 i915-sriov-dkms,没有在 guest 装

    这样 guest 内通常只能看到 PCI 设备,但 i915 probe 失败,没有 /dev/dri

  5. 用户不在 video / render

    导致 VAAPI 设备节点存在,但应用访问不到。

  6. vainfo 成功,却误以为 ffmpeg 一定也会成功

    实际上 ffmpeg 可能使用了另一套不兼容的 libva/驱动路径。

13. 最终检查清单

# 宿主机
cat /proc/cmdline
lspci -nnk -s 00:02
ls -l /dev/dri

# VM 配置
qm config 108

# 飞牛 guest
cat /proc/cmdline
lspci -nnk | grep -A3 -i 'VGA\|Display'
dmesg | grep -iE 'i915|xe|drm|firmware'
ls -l /dev/dri
groups
id
vainfo --display drm --device /dev/dri/renderD128

通过标准:

  • 宿主机 PF 是 i915,VF 是 vfio-pci
  • VM 只直通 VF,不直通 PF
  • VM 配置里没有 viommu=intel
  • 飞牛内有 /dev/dri/renderD128
  • 飞牛内 vainfo 正常
  • 飞牛运行用户在 video / render
  • 飞牛视频服务使用正确的 VAAPI 用户态环境

这份文档基于一次完整成功的实战整理,已经覆盖宿主机、VF 绑定、飞牛 guest 驱动、权限、VAAPI 验证以及 ffmpeg/libva ABI 冲突等关键细节。后续如果你更换内核、升级 fnOS 或改 VF 数量,记得同步检查 GRUB、udev 规则、guest DKMS 版本以及应用层环境变量。


收藏
送赞 1
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

0

主题

1

回帖

0

牛值

江湖小虾

10 小时前 楼主 显示全部楼层

image.png

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则