PVE 8 直通核显给 Jellyfin:IOMMU 分组与常见报错的完整排查

PVE 8 直通核显给 Jellyfin:IOMMU 分组与常见报错的完整排查

核显直通是 PVE 玩家绕不开的一道坎。网上教程大多只贴配置,不解释为什么这么配,一旦报错就只能从头翻。这篇按「能验证的顺序」重排了一遍,每一步都有检查手段。

一、先确认硬件真的支持

直通的前提是 CPU 和主板都允许把核显从宿主机隔离出去。

  • Intel 平台需要 CPU 支持 VT-d,主板 BIOS 里有 VT-d 或 Intel Virtualization Technology for Directed I/O
  • AMD 平台对应 IOMMU,通常和 SVM 分开
  • 部分品牌机 BIOS 锁死这些选项,那就只能作罢

在 PVE 宿主机上验证:

# 看到 IOMMU 相关的能力位就说明 CPU 支持
lscpu | grep -i -E 'vt-d|iommu'

# 打开内核参数后,这里会列出分组
dmesg | grep -i -E 'DMAR|IOMMU'

二、三处配置缺一不可

直通失败,九成是这三处漏了某一处。

1. GRUB 内核参数

nano /etc/default/grub
# Intel:
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt i915.enable_gvt=0"
# AMD:
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt"

update-grub

2. 加载 vfio 模块

echo -e "vfio\nvfio_iommu_type1\nvfio_pci\nvfio_virqfd" >> /etc/modules
update-initramfs -u -k all

3. 把设备 ID 绑给 vfio

# 查出核显的 vendor:device
lspci -nn | grep -i vga

# 写入绑定配置(示例 ID,按实际替换)
echo "options vfio-pci ids=8086:4690 disable_vga=1" > /etc/modprobe.d/vfio.conf
update-initramfs -u -k all
reboot

三、验证是否真的隔离成功

重启后不要急着建虚拟机,先看两件事:

# 核显应该显示 Kernel driver in use: vfio-pci
lspci -k | grep -A 3 -i vga

# 确认设备在独立的 IOMMU 组里
find /sys/kernel/iommu_groups/ -type l | sort -V

如果 Kernel driver in use 还是 i915,说明绑定没生效,回到第二步检查 modprobe.d 里的 ID 是否写错。

四、四个常见报错

报错现象真实原因处理
虚拟机启动后黑屏,控制台无输出核显被宿主机占用,绑定未生效检查 vfio-pci 是否在 lsmod 里
Cannot open /dev/vfio/xx权限或分组错误确认设备在独立分组,必要时加 pcie_acs_override
Jellyfin 能识别但硬解失败驱动版本与内核不匹配容器内换 linuxserver/jellyfin 的 latest,或手动装 intel-media-va-driver
直通后宿主机无法用 HDMI 输出正常现象直通就是把设备交出去,宿主机别再想用它

pcie_acs_override 是一把双刃剑。它能让设备强行分组,但绕过的是硬件本身的隔离边界,安全性会下降。只有在你确认同组设备之间没有 DMA 风险时才用。

五、虚拟机侧的配置

在 PVE 的虚拟机硬件页里:

  1. 添加 PCI 设备,选中核显
  2. 勾选 All Functions(多 function 设备必须勾)
  3. 勾选 Primary GPU 只在你想用核显输出画面时需要
  4. 机器类型选 q35,BIOS 用 OVMF

Jellyfin 容器里再补一条设备映射:

services:
  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    devices:
      - /dev/dri:/dev/dri
    group_add:
      - "989"   # 容器内 render 组的 gid

六、我的最终结论

直通本身不复杂,复杂的是验证。把它拆成「硬件支持 → 内核参数 → 模块绑定 → 分组确认 → 虚拟机配置 → 容器映射」六步,每一步都能用一条命令验证,出问题时你就知道该往回退到哪一步。

如果你只是想跑 Jellyfin 硬解,其实还有个更省事的选择:不直通,直接把 /dev/dri 挂进 LXC 容器。少一层虚拟化,性能损耗也更小。

相关阅读

更多

评论

评论功能默认关闭。想开启的话,去 src/lib/site.ts 里把 giscus.enabled 改成 true,填上你的 repo 和 repoId 即可——基于 GitHub Discussions, 不需要服务器,也不用数据库。