このページは、最終的に通った手順と検証方法をまとめた「成功編」。どの設定で何が起きたか、失敗の見分け方は試行錯誤編に分けてある。
全体像:パススルーの準備は「起動の早い段階でiGPUをホストに掴ませず、vfio-pciに預ける」ことに尽きる。具体的には (1) カーネルコマンドラインでIOMMUを有効化し簡易フレームバッファを止める、(2) /etc/modules でvfio関連を先に読む、(3) blacklistとvfio-pciのidsでGPU・オーディオを固定する、の3点を揃える。
私の場合の原因はVMのWin11の再起動、終了時にデバイスがうまく切り離せておらず例のcode43が頻発。
1か月悩んだ。
謎の悩みに長きにわたって付き合ってくれた@ggrks氏、@zeriyoshi氏に感謝。
改めてこのページに倣って修正を入れたらいろんな手法の組み合わせで出来るように。
https://github.com/xiongyw/docs/blob/master/pve-8.4-1_minisforum-um880pro/pve-8.4-1_minisforum-um880pro.md
以降で使用するDeviceID,VendorIDを確認。
# lspci -nnk
c7:00.0 Display controller [0380]: Advanced Micro Devices, Inc. [AMD/ATI] Strix [Radeon 880M / 890M] [1002:150e] (rev d1)
Subsystem: Device [1f4c:b020]
Kernel driver in use: vfio-pci
Kernel modules: amdgpu
c7:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Radeon High Definition Audio Controller [Rembrandt/Strix] [1002:1640]
Subsystem: Device [1f4c:b020]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel
c7:00.2 Encryption controller [1080]: Advanced Micro Devices, Inc. [AMD] Strix/Krackan/Strix Halo CCP/ASP [1022:17e0]
Subsystem: Advanced Micro Devices, Inc. [AMD] Strix/Krackan/Strix Halo CCP/ASP [1022:17e0]
Kernel driver in use: ccp
Kernel modules: ccp
c7:00.4 USB controller [0c03]: Advanced Micro Devices, Inc. [AMD] Device [1022:151e]
Subsystem: Advanced Micro Devices, Inc. [AMD] Device [1022:15b9]
Kernel driver in use: xhci_hcd
Kernel modules: xhci_pci
c7:00.6 Audio device [0403]: Advanced Micro Devices, Inc. [AMD] Family 17h/19h/1ah HD Audio Controller [1022:15e3]
DeviceName: Realtek ALC245
Subsystem: Advanced Micro Devices, Inc. [AMD] Device [1022:d808]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel
c7:00.7 Signal processing controller [1180]: Advanced Micro Devices, Inc. [AMD] Sensor Fusion Hub [1022:164a]
Subsystem: Advanced Micro Devices, Inc. [AMD] Sensor Fusion Hub [1022:164a]
Kernel driver in use: pcie_mp2_amd
Kernel modules: amd_sfh
この中で関係あるのは
c7:00.0 Display controller [0380]: Advanced Micro Devices, Inc. [AMD/ATI] Strix [Radeon 880M / 890M] [1002:150e] (rev d1)
Subsystem: Device [1f4c:b020]
Kernel driver in use: vfio-pci
Kernel modules: amdgpu
c7:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Radeon High Definition Audio Controller [Rembrandt/Strix] [1002:1640]
Subsystem: Device [1f4c:b020]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel
c7:00.6 Audio device [0403]: Advanced Micro Devices, Inc. [AMD] Family 17h/19h/1ah HD Audio Controller [1022:15e3]
DeviceName: Realtek ALC245
Subsystem: Advanced Micro Devices, Inc. [AMD] Device [1022:d808]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel
GPU c7:00.0 / [1002:150e] , Audio c7:00.1 / [1002:1640] , Audio c7:00.6 / [1022:15e3]
渡す3つのデバイスと役割
c7:00.0(1002:150e)… Radeon 890M本体。これをVMに渡すのが主目的。c7:00.1(1002:1640)… GPU内蔵のHDオーディオ(HDMI/DPから音を出す用)。GPUと同じIOMMUグループに入るのでセットで渡す。c7:00.6(1022:15e3)… マザーボード側のRealtek ALC245。これは音を出すためではなく、RadeonResetBugFixを効かせるために渡す(試行錯誤編で「無いとResetBugFixが効かない気がする」と書いたもの)。1002 がAMD/ATI、1022 がAMD(マザーボードASIC)。lspci -nn の [ベンダ:デバイス] がそのままvfioのidsになる。1022:15e3 を渡すとホスト側のオンボード音は使えなくなる。ホストにも音を残したい場合はこのデバイスを渡さない構成も検討する。ext4の場合は/etc/default/grubに
GRUB_CMDLINE_LINUX_DEFAULT="quiet iommu=pt initcall_blacklist=sysfb_init"
zfsの場合は/etc/kernel/cmdlineに
root=ZFS=rpool/ROOT/pve-1 boot=zfs quiet iommu=pt initcall_blacklist=sysfb_init
/etc/modulesにモジュールを追記
vfio はパススルー全体の枠組み、vfio_iommu_type1 はAMDのIOMMUで渡すための変換層、vfio_pci は先述のスタブドライバ、vfio_virqfd はゲストの割り込みをホストへ中継する役割。4行とも起動時に読み込ませる。
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
/etc/modprobe.d/passthrough.confにブラックリストを追加(多分いらないのもあるけど削るの大変w)
/etc/modprobe.d/passthrough.confにブラックリストを追加(多分いらないのもあるけど削るの大変w)
# don't load driver for iGPU and sound devices
blacklist amdgpu
blacklist radeon
blacklist snd_sof_amd_acp63
blacklist snd_sof_amd_vangogh
blacklist snd_sof_amd_rembrandt
blacklist snd_sof_amd_renoir
blacklist snd_sof_amd_acp
blacklist snd_sof_pci
blacklist snd_sof_xtensa_dsp
blacklist snd_sof
blacklist snd_sof_utils
blacklist snd_soc_core
blacklist snd_hda_intel
blacklist snd_compress
blacklist snd_intel_dspcfg
blacklist snd_pcm_dmaengine
blacklist snd_intel_sdw_acpi
blacklist snd_pci_ps
blacklist snd_rpl_pci_acp6x
blacklist snd_hda_codec
blacklist snd_acp_pci
blacklist snd_acp_legacy_common
blacklist snd_hda_core
blacklist snd_pci_acp6x
blacklist snd_hwdep
blacklist snd_pci_acp5x
blacklist snd_pcm
blacklist snd_rn_pci_acp3x
blacklist snd_timer
blacklist snd_acp_config
blacklist snd_soc_acpi
blacklist snd_pci_acp3x
# load vfio-pci driver instead
options vfio-pci ids=1002:150e,1002:1640,1022:15e3
有効化、再起動
blacklistとvfio-pci idsの関係
blacklist amdgpu / radeon … ホストがiGPU用ドライバを読まないようにする。これをしないとvfio-pciより先にamdgpuへ掴まれる。blacklist snd_* の大量の行 … AMDサウンドまわり(SOF関連)が先にデバイスを取らないように潰している。実際は代表的なものだけでも動くが、取りこぼし防止で網羅してある。options vfio-pci ids=1002:150e,1002:1640,1022:15e3 … この3つ(GPU・GPUオーディオ・オンボードオーディオ)をvfio-pciに固定する。準備の節で確認した3つのDeviceIDと一致しているか確認する。ここで一度 検証:再起動後に lspci -nnk を叩き、c7:00.0 c7:00.1 c7:00.6 の Kernel driver in use が vfio-pci か確認する。amdgpu / snd_hda_intel のままならblacklistかidsの書き漏れだ。ホストのHDMIがブートローダー以降映らなくなっていれば、ホストがiGPUを手放せている。
# update-initramfs -u -k all
# reboot
VMの設定はこんな感じ(コピペは動かないので駄目)
agent: 1
args: -cpu host,hv_passthrough,+hypervisor,+svm
balloon: 0
bios: ovmf
boot: order=scsi0;ide2;ide0;net0
cores: 8
cpu: host
efidisk0: local-lvm:vm-100-disk-0,efitype=4m,pre-enrolled-keys=1,size=4M
hookscript: local:snippets/gpu-hookscript.sh
hostpci0: 0000:c7:00.0,pcie=1,romfile=vbios_1002_150e.bin
hostpci1: 0000:c7:00.1,pcie=1,romfile=AMDGopDriver.rom
hostpci2: 0000:c7:00.6,pcie=1
ide0: local:iso/virtio-win-0.1.266.iso,media=cdrom,size=707456K
ide2: local:iso/Win11_24H2_Japanese_x64.iso,media=cdrom,size=5616576K
machine: pc-q35-10.0+pve1,viommu=virtio
memory: 16384
meta: creation-qemu=10.0.2,ctime=1758699031
name: Win11
net0: virtio=BC:24:11:52:AB:6D,bridge=vmbr0,firewall=1
numa: 0
ostype: win11
scsi0: local-lvm:vm-100-disk-1,discard=on,iothread=1,size=256G,ssd=1
scsihw: virtio-scsi-single
smbios1: uuid=4a9c4dce-31c6-4c6d-ba14-7f5cecb717a6
sockets: 1
tpmstate0: local-lvm:vm-100-disk-2,size=4M,version=v2.0
usb0: host=17ef:60ee
usb1: host=359f:3302,usb3=1
vga: none
vmgenid: ea4b6e24-a2ef-4877-89d0-d0403f39c869
上記confで主な変更点はここ。
args: -cpu host,hv_passthrough,+hypervisor,+svm
hookscript: local:snippets/gpu-hookscript.sh
hostpci0: 0000:c7:00.0,pcie=1,romfile=vbios_1002_150e.bin
hostpci1: 0000:c7:00.1,pcie=1,romfile=AMDGopDriver.rom
hostpci2: 0000:c7:00.6,pcie=1
特に悩む必要はないという結果に至っているが、PCI Deviceのパススルーは上記2台が必須。
重要なのはWin11の場合、vbiosとAMDGopDriverの指定が必要。
vbiosの抜き方はこちら。isc30/ryzen-gpu-passthrough-proxmox
AMDGopDriverの抜き方はこちら。elandwg commented on Mar 1, 2024
AMDGopDriverはryzen-gpu-passthrough-proxmoxのサイトに落ちているが、これではだめだったので自分で再作成する必要があるが、超面倒なので2つのファイルを置いておく。
vbios_1002_150e_and_AMDGopDriver.zip
さらにコード43エラーを避けるためにinga-lovinde/RadeonResetBugFix: Radeon Reset Bug fixを使用する可能性が高い。その場合は0000:c6:00.6のオーディオを追加。
これはカーネル側の設定に加える必要はなく存在してればよさそう。
無いとResetBugFixが効かない気がする。


とりあえず動作確認できているDevcon
https://github.com/Drawbackz/DevCon-Installer


gpedit.mscでスタートアップ、シャットダウンスクリプトにそれぞれ登録。
起動時(disable後enableしないとうちの環境だとcode43だった)
devcon.exe disable "PCI\VEN_1002&DEV_150E*"
devcon.exe disable "HDAUDIO\FUNC_01&VEN_1002&DEV_AA01*"
devcon.exe enable "PCI\VEN_1002&DEV_150E*"
devcon.exe enable "HDAUDIO\FUNC_01&VEN_1002&DEV_AA01*"
終了時
devcon.exe disable "PCI\VEN_1002&DEV_150E*"
devcon.exe disable "HDAUDIO\FUNC_01&VEN_1002&DEV_AA01*"
Proxmox上のHook script
# nano /var/lib/vz/snippets/gpu-hookscript.sh
#!/usr/bin/bash
# ref: https://gist.github.com/kiler129/215e2c8de853209ca429ad5ed40ce128
set -e -o errexit -o pipefail -o nounset
# Do not modify these variables (set by Proxmox when calling the script)
vmId="$1"
runPhase="$2"
echo ">>> Entering $runPhase on VM=$vmId" > /dev/kmsg
case "$runPhase" in
pre-start)
echo "### rescan pcie bus..." > /dev/kmsg
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.0/remove
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.1/remove
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.6/remove
echo 1 > /sys/bus/pci/rescan
sleep 2
;;
post-start)
;;
pre-stop)
echo "### remove gpu/snd devices..." > /dev/kmsg
GFX_PATH=$(dirname $(grep -l "PCI_ID=1002:150e" /sys/bus/pci/devices/*/uevent))
SND_PATH=$(dirname $(grep -l "PCI_ID=1002:1640" /sys/bus/pci/devices/*/uevent))
echo 1 > ${GFX_PATH}/remove
sleep 1
echo 1 > ${SND_PATH}/remove
sleep 1
;;
post-stop)
echo "### rescan pcie bus..." > /dev/kmsg
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.0/remove
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.1/remove
echo 1 > /sys/bus/pci/devices/0000\:c7\:00.6/remove
echo 1 > /sys/bus/pci/rescan
sleep 2
;;
*)
echo "### Unknown run phase \"$runPhase\"!" > /dev/kmsg
;;
esac
echo "<<< Leaving $runPhase on VM=$vmId" > /dev/kmsg
このスクリプトを実行できるようにし、VMに登録する
hookscriptの4フェーズと役割
pre-start … VM起動前に3デバイスをremove→rescan。ホストから一度切り離してやり直す。pre-stop … VM停止前にデバイスをremove。ゲストが解放しそこねた状態を残さない。post-stop … 停止後に再度remove→rescanし、次の起動に備える。post-start は何もしない。chmod +x して qm set 100 --hookscript local:snippets/gpu-hookscript.sh。VM起動時にdmesgへ Entering pre-start などが出れば呼ばれている。$ chmod +x /var/lib/vz/snippets/gpu-hookscript.sh
$ qm set 100 --hookscript local:snippets/gpu-hookscript.sh
VM起動時にエラーが出るが問題なさそう。

これも入れとくと良いかも。
上から順に確認すると、どこで嵌まっているか切り分けられる。
lspci -nnk で3デバイスが Kernel driver in use: vfio-pci になっている。dmesg | grep -i vfio に enabling device と reset done が出る。IO_PAGE_FAULT が大量に出るならリセット不具合を疑う。※ 本ページのAmazonリンクにはアフィリエイトタグ(toobf6-22)が付いている。
🤖 このページにはAIエージェント(ノア)による編集・加筆が含まれます。内容の正確性は保証できないため、重要な判断は一次情報でご確認ください。