使用INIPIN补丁在bhyve中实现NVIDIA GPU passthrough

我在 在bhyve中实现NVIDIA GPU passthrough 实践中采用了 bhyve Current state of bhyve Nvidia passthrough? 讨论中提供的补丁,也就是向Guest传递不同的id字符串激活GPU的虚拟化功能。但是这个patch根据不同的硬件和Guest组合似乎需要调整,在我的 Nvidia Tesla P10 GPU运算卡 环境实践没有成功。

参考 WanpengQian 网友提供的方法,我尝试 bhyve: assign a valid INTPIN to NVIDIA GPUs 补丁,即通过设置INT PIN寄存器的数值来实现这个直通虚拟化功能。本文记录实践过程

准备工作

已完成 在 bhyve 中运行 虚拟机

patch源代码

备注

目前网上提供针对NVIDIA passthru的补丁是采用 Backhoff自动化公司 freebsd-src ( 德国倍福自动化有限公司 )分支 phab/corvink/<RELEASE>/nvida-wip 来进行补丁的

所以这里源代码从 Backhoff自动化公司 freebsd-src 拉取

我尝试过 从源代码编译构建FreeBSD FreeBSD官方源码 releng/14.3 ,发现代码差异不能patch,再仔细看了 bhyve Current state of bhyve Nvidia passthrough? 讨论找到上述规律

下载 Backhoff 的 freebsd-src 源代码
cd /usr/

# 重命名目录可能不行,需要cp然后清空目录
#mv src src-old
#
mkdir bechoff-src
git clone https://github.com/beckhoff/freebsd-src /usr/bechoff-src
  • checkoutphab/corvink/14.2/nvidia-wip 分支:

phab/corvink/14.2/nvidia-wip 分支
cd /usr/bechoff-src
git checkout phab/corvink/14.2/nvidia-wip
Download Raw Diff 并对 bhyve 代码打补丁
#cd /usr/bechoff-src
#这个补丁是针对 stable/15 或 phab/corvink/15.0/nvidia-wip
#curl https://reviews.freebsd.org/file/data/dnnvdlk6cbsbursoniwv/PHID-FILE-s3ttba5veb5qioermjqp/D51892.diff \
#    -o bhyve_pci_passthru_intpin.patch.txt
#git apply --verbose bhyve_pci_passthru_intpin.patch.txt

git apply --verbose pci_passthru_quirks.patch.txt

备注

我经过尝试对比发现 bhyve: assign a valid INTPIN to NVIDIA GPUs 实际上是针对 FreeBSD官方 stable/15 或者 Backhoff自动化公司 freebsd-src phab/corvink/15.0/nvidia-wip (根据 usr.sbin/bhyve/amd64/Makefile.inc 判断)

所以,我这里手工做了补丁修正,并生成一个针对 releng/14.3git diff 补丁 pci_passthru_quirks.patch.txt

  • 编译安装补丁以后的 bhyve :

编译补丁以后的 bhyve
cd /usr/src/usr.sbin/bhyve/
make -j8
sudo make install

配置PCI passthru

  • 检查 PCI 设备:

vm 检查 passthru 设备列表
vm passthru

输出显示 Tesla P10BHYVE ID1/0/0

备注

我分别测试了 Nvidia Tesla P10 GPU运算卡Nvidia Tesla P4 GPU运算卡 ,单独安装其中任一设备,都识别为 BHYVE ID1/0/0 ,所以下文案例共用步骤

vm 检查 passthru 设备列表: Tesla P10
DEVICE     BHYVE ID     READY        DESCRIPTION
...
vgapci0    1/0/0        No           GP102GL [Tesla P10]
...
vm 检查 passthru 设备列表: Tesla P4
DEVICE     BHYVE ID     READY        DESCRIPTION
...
vgapci0    1/0/0        No           GP104GL [Tesla P4]
...
  • 配置 /boot/loader.conf 屏蔽掉需要passthru的GPU:

  • 重启系统,然后再次检查 vm passthru ,此时看到 Tesla P10 / Tesla P4 的设备一列应该显示为 ppt0 :

屏蔽掉 Nvidia Tesla P10 GPU运算卡 之后显示为 ppt0
DEVICE     BHYVE ID     READY        DESCRIPTION
...
ppt0       1/0/0        No           GP102GL [Tesla P10]
...
屏蔽掉 Nvidia Tesla P4 GPU运算卡 之后显示为 ppt0
DEVICE     BHYVE ID     READY        DESCRIPTION
...
ppt0       1/0/0        No           GP102GL [Tesla P4]
...
  • 修订 xdev 虚拟机配置 /zroot/vms/xdev/xdev.conf

配置 xdev 添加直通PCI设备 1/0/0 也就是 Nvidia Tesla P10 GPU运算卡 / Nvidia Tesla P4 GPU运算卡
loader="uefi"
cpu=4
memory=16G
wired_memory="yes"
network0_type="virtio-net"
network0_switch="igc0bridge"
network0_device="tap0"
disk0_name="disk0"
disk0_dev="sparse-zvol"
disk0_type="virtio-blk"
passthru0="1/0/0"
graphics="yes"
graphics_listen="0.0.0.0"
graphics_port="5900"
uuid="2a96f70d-8988-11f0-be9b-0003ee002989"
network0_mac="58:9c:fc:0c:9c:e4"

安装CUDA驱动

参考之前在 在Ubuntu安装NVIDIA CUDA 经验,也包括我之前 Bhyve环境Ubuntu虚拟机运行Tesla P4 GPU的Docker ,快速完成 cuda-driver 安装:

安装纯后台开发工具
sudo apt install build-essential cmake vim-nox python3-dev -y
  • CUDA驱动需要内核头文件以及开发工具包来完成内核相关的驱动安装,因为内核驱动需要根据内核进行编译

安装 linux-headers (不过直接安装 cuda-driver 也会自动依赖安装):

安装inux-headers
apt-get install linux-headers-$(uname -r)
Debian/Ubuntu使用NVIDIA官方软件仓库安装CUDA驱动
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
  • 安装驱动 cuda-driver :

Debian/Ubuntu使用NVIDIA官方软件仓库安装CUDA驱动
sudo apt-get -y install cuda-drivers
  • 重启虚拟机操作系统

Nvidia Tesla P4 GPU运算卡

  • 日志报错

启动日志中有 RmInitAdapter 报错
[Tue Sep  9 02:26:33 2025] nvidia: module license taints kernel.
[Tue Sep  9 02:26:33 2025] nvidia-nvlink: Nvlink Core is being initialized, major device number 239

[Tue Sep  9 02:26:33 2025] nvidia 0000:00:06.0: can't derive routing for PCI INT A
[Tue Sep  9 02:26:33 2025] nvidia 0000:00:06.0: PCI INT A: no GSI - using ISA IRQ 10
[Tue Sep  9 02:26:33 2025] loop0: detected capacity change from 0 to 8
[Tue Sep  9 02:26:33 2025] NET: Registered PF_QIPCRTR protocol family
[Tue Sep  9 02:26:33 2025] NVRM: loading NVIDIA UNIX x86_64 Kernel Module  580.82.07  Wed Aug 27 18:39:48 UTC 2025
[Tue Sep  9 02:26:33 2025] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms  580.82.07  Wed Aug 27 18:05:23 UTC 2025
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: RmInitAdapter failed! (0x31:0xffff:2767)
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: rm_init_adapter failed, device minor number 0
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: RmInitAdapter failed! (0x31:0xffff:2767)
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: rm_init_adapter failed, device minor number 0
[Tue Sep  9 02:26:34 2025] [drm] [nvidia-drm] [GPU ID 0x00000006] Loading driver
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: RmInitAdapter failed! (0x31:0xffff:2767)
[Tue Sep  9 02:26:34 2025] NVRM: GPU 0000:00:06.0: rm_init_adapter failed, device minor number 0
[Tue Sep  9 02:26:34 2025] [drm:nv_drm_dev_load [nvidia_drm]] *ERROR* [nvidia-drm] [GPU ID 0x00000006] Failed to allocate NvKmsKapiDevice
[Tue Sep  9 02:26:34 2025] [drm:nv_drm_register_drm_device [nvidia_drm]] *ERROR* [nvidia-drm] [GPU ID 0x00000006] Failed to load device

参考