在bhyve中实现AMD GPU passthrough

在bhyve中实现Intel GPU passthrough 类似,尝试 AMD Radeon Instinct MI50 设置 bhyve 的PCIe passthru,思路相同:

  • 通过bhyve passthru将host主机的 AMD Radeon Instinct MI50 直通给ubuntu虚拟机,采用之前已经部署好的 idev 虚拟机

安装 vm-bhyve

备注

使用 vm-bhyve 作为管理器来完成部署

  • 安装 vm-bhyve

安装 vm-bhyve
pkg install vm-bhyve bhyve-firmware
  • 创建 vm-bhyve 使用的存储:

创建虚拟机存储数据集
zfs create zdata/vms

#zfs set recordsize=64K zdata/vms

zfs create zdata/vms/.config
zfs create zdata/vms/.img
zfs create zdata/vms/.iso
zfs create zdata/vms/.templates
  • /etc/rc.conf 中设置虚拟化支持:

配置 /etc/rc.conf 支持虚拟化
# needed for virtualization support
vm_enable="YES"
vm_dir="zfs:zdata/vms"
  • /boot/loader.conf 添加:

/boot/loader.conf
# needed for virtualization support 
vmm_load="YES"
  • 初始化:

初始化
vm init

PCI passthru

  • 检查 PCI 设备:

检查可以passthrough的设备
 vm passthru
  • 输出显示:

输出显示 Radeon Instinct MI50 32GB
DEVICE     BHYVE ID     READY        DESCRIPTION
...
vgapci0    4/0/0        No           Vega 20 [Radeon Pro VII/Radeon Instinct MI50 32GB]
  • 配置 /boot/loader.conf 屏蔽掉需要passthru的Radeon Instinct MI50 32GB 4/0/0 :

屏蔽掉 Radeon Instinct MI50 32GB 4/0/0
pptdevs="4/0/0 0/2/0 1/0/0"

配置

  • 配置模版配置 /zdata/vms/.templates/x-vm.conf (如果已经安装好 idev ,则直接修改虚拟机配置 /zdata/vms/idev/idev.conf )

模版配置 /zdata/vms/.templates/x-vm.conf
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"
disk0_size="50G"
passthru0="4/0/0"
graphics="yes"
graphics_listen="0.0.0.0"
graphics_port="5901"
  • 创建虚拟机 idev :

创建虚拟机 idev
vm create -t x-vm -s 60G idev
  • 安装ubuntu:

安装虚拟机
vm install idev ubuntu-24.04.2-live-server-amd64.iso

备注

由于我在 在bhyve中实现Intel GPU passthrough 已经安装部署好 idev ,所以我这里实践是采用修改虚拟机配置 /zdata/vms/idev/idev.conf

看起来非常顺利启动了虚拟机

  • 登陆虚拟机 idev 检查虚拟机内部 lspci 输出:

虚拟机内部 lspci 检查输出可以看到AMD Radeon Instinct MI50 32GB
...
00:06.0 Display controller: Advanced Micro Devices, Inc. [AMD/ATI] Vega 20 [Radeon Pro VII/Radeon Instinct MI50 32GB] (rev 01)
00:07.0 VGA compatible controller: Device fb5d:40fb
...

至此 bhyve passthru AMD显卡的操作完成 看起来完成,但实际上后续针对 AMD GPU 安装 ROCm 驱动以及如何使用 ollama 来完成推理遇到了挫折: AMDGPU无法初始化

安装 ROCm

我最初以为 bhyve(BSD hypervisor) 对AMD GPU支持会比NVIIA好,所以看到上配置passthru丝滑完成,以为没有什么困难了。

安装步骤采用了 ROCm 快速起步 官方仓库安装,过程丝滑,没有任何报错。但是重启系统执行 rocm-smi 命令检查却给了我当头一棒: 无法识别

异常排查

警告

目前我没有解决 AMD Radeon Instinct MI50bhyve PCI Passthrough 问题: 我感觉类似 在bhyve中实现NVIDIA GPU passthrough 存在兼容支持问题。

由于需要尽快构建 Machine Learning 环境,我暂时放弃并改为直接在 Ubuntu Linux 物理主机上先 ROCm 快速起步 ,验证无误后再迁移到 采用OVMF实现passthrough GPU和NVMe存储 (并分别尝试 Ubuntu 环境和 LFS(Linux from scratch) 环境)。最后再返回 FreeBSD 环境构建。

虽然看上去成功安装了 ROCmAMDGPU driver ,但是我发现 rocm-smi 输出显示没有可用的AMD GPU:

rocm-smi 显示没有可用AMD GPU
WARNING: No AMD GPUs specified
===================================== ROCm System Management Interface =====================================
=============================================== Concise Info ===============================================
Device  Node  IDs           Temp    Power  Partitions          SCLK  MCLK  Fan  Perf  PwrCap  VRAM%  GPU%
              (DID,  GUID)  (Edge)  (Avg)  (Mem, Compute, ID)
============================================================================================================
============================================================================================================
=========================================== End of ROCm SMI Log ============================================
  • 检查 dmesg | grep amdgpu 发现初始化异常,通过完整的 dmesg 显示,似乎 atom_bios (看起来是bhyve模拟的bios存在问题不能支持 amdgpu )

检查系统日志发现AMD GPU初始化失败
[    3.252058] [drm] amdgpu kernel modesetting enabled.
[    3.252243] [drm] amdgpu version: 6.12.12
[    3.252406] [drm] OS DRM version: 6.8.0
[    3.253244] amdgpu: Virtual CRAT table created for CPU
[    3.253915] amdgpu: Topology: Add CPU node
[    3.257044] amdgpu 0000:00:06.0: can't derive routing for PCI INT A
[    3.257228] amdgpu 0000:00:06.0: PCI INT A: no GSI - using ISA IRQ 10
[    3.257425] [drm] initializing kernel modesetting (VEGA20 0x1002:0x66A1 0x1002:0x0834 0x01).
[    3.257597] [drm] register mmio base: 0xC1000000
[    3.257784] [drm] register mmio size: 524288
[    3.258559] amdgpu 0000:00:06.0: amdgpu: detected ip block number 0 <soc15_common>
[    3.258754] amdgpu 0000:00:06.0: amdgpu: detected ip block number 1 <gmc_v9_0>
[    3.258909] amdgpu 0000:00:06.0: amdgpu: detected ip block number 2 <vega20_ih>
[    3.259063] amdgpu 0000:00:06.0: amdgpu: detected ip block number 3 <psp>
[    3.259210] amdgpu 0000:00:06.0: amdgpu: detected ip block number 4 <powerplay>
[    3.259354] amdgpu 0000:00:06.0: amdgpu: detected ip block number 5 <dm>
[    3.259496] amdgpu 0000:00:06.0: amdgpu: detected ip block number 6 <gfx_v9_0>
[    3.259634] amdgpu 0000:00:06.0: amdgpu: detected ip block number 7 <sdma_v4_0>
[    3.259790] amdgpu 0000:00:06.0: amdgpu: detected ip block number 8 <uvd_v7_0>
[    3.259925] amdgpu 0000:00:06.0: amdgpu: detected ip block number 9 <vce_v4_0>
[    3.260507] amdgpu 0000:00:06.0: ROM [??? 0x00000000 flags 0x20000000]: can't assign; bogus alignment
[    3.299305] amdgpu 0000:00:06.0: amdgpu: Fetched VBIOS from ROM
[    3.299903] amdgpu: ATOM BIOS: 113-D1631711-100
[    3.303174] [drm] UVD(0) is enabled in VM mode
[    3.303344] [drm] UVD(1) is enabled in VM mode
[    3.303496] [drm] UVD(0) ENC is enabled in VM mode
[    3.303646] [drm] UVD(1) ENC is enabled in VM mode
[    3.303825] [drm] VCE enabled in VM mode
[    3.303995] amdgpu 0000:00:06.0: amdgpu: Trusted Memory Zone (TMZ) feature not supported
[    3.304184] amdgpu 0000:00:06.0: amdgpu: MODE1 reset
[    3.304333] amdgpu 0000:00:06.0: amdgpu: GPU mode1 reset
[    3.304766] amdgpu 0000:00:06.0: amdgpu: GPU psp mode1 reset
[    3.814317] [drm] psp mode1 reset succeed
[    4.093317] [drm] GPU posting now...
[   24.094673] [drm:atom_op_jump [amdgpu]] *ERROR* atombios stuck in loop for more than 20secs aborting
[   24.095199] [drm:amdgpu_atom_execute_table_locked [amdgpu]] *ERROR* atombios stuck executing 4EC4 (len 74, WS 0, PS 8) @ 0x4EDC
[   24.095753] amdgpu 0000:00:06.0: amdgpu: gpu post error!
[   24.095905] amdgpu 0000:00:06.0: amdgpu: Fatal error during GPU init
[   24.096112] amdgpu 0000:00:06.0: amdgpu: amdgpu: finishing device.
[   24.096302] amdgpu: probe of 0000:00:06.0 failed with error -22

看起来驱动初始化异常,可能原因(可能性从高到低):

我看到Reddit上的一个帖子 Mi50 32gb (Working config, weirdness and performance) 可以正常使用ROCm和AMDGPU驱动(非虚拟机)

  • 这个方法已经验证没有解决我的问题 PROXMOX论坛帖子 AMD GPU firmware/bios missing? amdgpu fatal error 提出了通过安装 firmware-amd-graphics 来解决。不过这个firmware是私有软件,我直接在Ubuntu中执行 apt install firmware-amd-graphics 显示不存在(PROXMOX提供的虚拟机可能已经内置提供了软件仓库)

上述帖子提供了手工下载Firmware的方法: 在 debian firmware-nonfree 提供下载:

手工安装 firmware-amd-graphics
# Firmware download, extract and copy
wget http://ftp.debian.org/debian/pool/non-free-firmware/f/firmware-nonfree/firmware-amd-graphics_20250708-1_all.deb
dpkg -x firmware-amd-graphics_20250708-1_all.deb firmware-amd-graphics
cp -r firmware-amd-graphics/usr/lib/firmware/* /lib/firmware/

# Update "initramfs"
update-initramfs -k all -u

# Reboot
reboot

警告

我发现上述手工安装的 firmware 实际上在之前安装 amdgpu driver 已经安装在 /lib/firmware/amdgpu 目录下了

但是比较奇怪,在 /lib/firmware/amdgpu 目录下似乎是 .zst 后缀的压缩文件,例如 yellow_carp_vcn.bin.zst ; 而 firmware-amd-graphics/usr/lib/firmware/amdgpu/ 目录下是解压缩的文件,例如 yellow_carp_vcn.bin

我尝试了上述方法,没有解决问题,报错依旧