ProxmoxVEでVMからGPUにアクセスする


やること

ProxmoxVEで仮想マシンを構築し、NVIDIAのグラボが使えるようにする。

Part1 BIOSの設定

BIOS画面からCPUの仮想化オプションを有効化する。
IntelならVT-d、AMDならIOMMUという名前の項目があるはず。

Part2 GRUBオプションの編集

/etc/default/grub を編集する

#Before
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
#After(Intelの場合)
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"
#After(AMDの場合)
GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=on iommu=pt video=efifb:off"

オプションの狙いについては以下の表を参照

オプション名 効果 重要度
amd_iommu=on AMDのCPUでIOMMUを有効化 必須
intel_iommu=on IntelのCPUでIOMMUを有効化 必須
iommu=pt ホスト側のLinuxからGPUにアクセスしない 推奨
video=efifb:off WindowsゲストのError43問題対策 推奨

Error43問題とはNvidiaのドライバーが仮想環境のWindowsで正常に動作しないというもの。
Windowsのデバイスマネージャでグラボを見るとError43と表示されている。念の為に設定することにする。

変更した設定を反映する

$ update-grub

なお、この変更後に再起動すると以後モニタに何も表示されなくなる。Webの管理画面からコマンド操作を行う。

PART3 モジュール系

/etc/modules 必要なモジュールを追加

vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd

/etc/modprobe.d/blacklist.conf 読み込まないモジュールを記述

blacklist pcspkr
blacklist radeon
blacklist nvidia
blacklist nvidiafb
blacklist nouveau
blacklist amdgpu
blacklist vfio

この辺で一旦サーバーを再起動

PART4 設定ファイル系

/etc/modprobe.d/kvm.conf に以下オプションを記述

#MSRという特殊なレジスタへゲストからアクセスをしない
options kvm ignore_msrs=1

追記)以下については古い情報。
nptのバグは修正され、設定しない方がパフォーマンスがよい
https://wiki.archlinux.jp/index.php/OVMF_%E3%81%AB%E3%82%88%E3%82%8B_PCI_%E3%83%91%E3%82%B9%E3%82%B9%E3%83%AB%E3%83%BC#AMD_CPU_.E3.81.A7.E3.83.91.E3.83.95.E3.82.A9.E3.83.BC.E3.83.9E.E3.83.B3.E3.82.B9.E3.82.92.E6.94.B9.E5.96.84.E3.81.99.E3.82.8B

以前追記したオプションの行を削除したところ、画面のカクツキが解消されました。

/etc/modprobe.d/kvm_amd.conf にAMDの場合以下オプションを記述

#AMDでNPTを無効化するとパフォーマンスが改善される
options kvm_amd npt=0

/etc/modprobe.d/iommu_unsafe_interrupts.conf に以下記述

#ハードウェア割り込みの再マッピングをサポートしていないためにパススルーが失敗する場合があるので念の為
options vfio_iommu_type1 allow_unsafe_interrupts=1

デバイスIDを調査

$ dmesg | grep -i vfio
[151588.420384] VFIO - User Level meta-driver version: 0.3
[151588.422724] vfio-pci 0000:26:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=none
[151588.446167] vfio_pci: add [10de:1c82[ffffffff:ffffffff]] class 0x000000/00000000
[151588.446178] vfio_pci: add [10de:0fb9[ffffffff:ffffffff]] class 0x000000/00000000
[151593.438821] vfio-pci 0000:26:00.0: vfio_ecap_init: hiding ecap 0x19@0x900
[156099.312136] vfio-pci 0000:26:00.0: vfio_ecap_init: hiding ecap 0x19@0x900

10de:1c82と10de:0fb9が欲しい部分。/etc/modprobe.d/vfio.conf に以下記述

options vfio-pci ids=10de:1c82,10de:0fb9 disable_vga=1

PART5 グラボからROMの吸出し(RyzenなどCPU内蔵GPUがない場合のみ)

※かつてはNVIDIA Tesla, Quadro等にGPUの仮想化を限定していたようで、ハードウェアを精密に偽装する必要があったが、現在はGeForceもBetaではあるがサポートするようになった。Nvidia DriverのバージョンがR465以降であれば下記をしなくても動作するとのこと。
引用(https://nvidia.custhelp.com/app/answers/detail/a_id/5173/~/geforce-gpu-passthrough-for-windows-virtual-machine-%28beta%29)

プライマリーのGPUのROMはホスト側が起動時にロックしてしまうので、仮想マシンから読むことができなくなる。Intel+Nvidiaの構成ならばCPUの内蔵GPUがプライマリで、Nvidiaがセカンダリなので問題ないが、RyzenのようにCPUに内蔵GPUがない場合はNvidiaのグラボがプライマリーとなりROMが読めなくなる。
具体的な問題として、Nvidiaのドライバのインストールに失敗する(Error43問題)
どうしたかというとGPUを2枚刺しにして、ROMをファイルとして控えておき仮想マシンに渡すという処理をしている。

$ lspci |grep NVIDIA
26:00.0 VGA compatible controller: NVIDIA Corporation GP107 [GeForce GTX 1050 Ti] (rev a1)
26:00.1 Audio device: NVIDIA Corporation GP107GL High Definition Audio Controller (rev a1)

26:00.0と26:00.1の番号を後々使うので控えておく

cd /sys/bus/pci/devices/0000:26:00.0/
echo 1 > rom
cat rom > /usr/share/kvm/Z_1050Ti.rom
echo 0 > rom

※GTX10XX系は更にVFIOパススルーできるようにROMにパッチを当てないとうまく行かなかった。
https://github.com/Matoking/NVIDIA-vBIOS-VFIO-Patcher

今回はWindowsでパッチをあてて、/usr/share/kvm/ のなかにZ_1050Ti_MOD.romの名前で保存

PART6 仮想マシンの作成

ようやくVMを作り始める。普通のWindows設定

「システム」で注視点がいくつかある

  • グラフィックカードは「none」
  • QEMUエージェントを有効に
  • BIOSをOVFM(UEFI)に(超重要)
  • AddEFIでEFIディスクを追加
  • 形式はrawがパフォーマンス良いかも
  • SCSIコントローラはVirtIO SCSI single
  • Machineはq35

BIOSのタイプはOSのインストール後に変更することはできないと思っていい。GPU-Passthroughするつもりなら必ずインストール前に「OVFM」を選択すること。


ディスクは「SATA」を選ぶ

ディスクの設定についてはCrystalDiskMarkによるベンチを取ってみました。
ProxmoxVE 設定とベンチマーク結果まとめ(ディスク編)


CPUは「host」を選ぶ。host以外だとNvidiaのドライバのインストールでコケることがある。


BallooningDeviceはオフに。若干パフォーマンスが良いらしい。


ネットワークは「VirtIO」を選ぶ


オプションをいじる。UseTabletPointerをオフにするとパフォーマンスがよい。


ハードウェアをいくつか追加。まずRNG。


そしてグラフィックボード。


一覧からGTXを選ぶ


全部チェックで


Windowsのディスクとは別にドライバーを入れるためのCDを追加する
ISOイメージは以下から入手。安定版の「Stable」か最新版の「Latest」かはお好みで。


USBも全部つける。キーボードやマウスが使えるようになる。

PART7 設定ファイルの追加修正

GUIで設定した内容はテキストで保存されている。GUI上にはない項目もあるので直接編集する
/etc/pve/qemu-server/111.conf 「111」はマシン番号。

行追加。必須なのは「host」「hv_vendor_id=whatever」「kvm=off」。これがないとNvidiaのドライバのインストールでコケることがある。その他はCPUのパフォーマンスに関するものなので、お好みで。

args: -cpu 'host,+kvm_pv_unhalt,+kvm_pv_eoi,hv_vendor_id=whatever,kvm=off,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time,smep=off,-pcid,-spec-ctrl,-ssbd,-hv-evmcs,+aes'

Ryzen等AMDのCPUでハイパースレッディングを有効化するには、設定の追加(topoext=onの追記)が必要。topoextはデフォルトではoff

args: -cpu 'host,topoext=on,〜〜

マシンタイプを変更。q35でとりあえずPassthroughできるが、音声の再生時に酷い音割れとパフォーマンス低下が見られたためこの設定を行った。管理画面からは「pc-q35-3.1」は選べないので、設定ファイルに直接記入する。

#before
machine: q35
#after
machine: pc-q35-3.1

※Proxmox VE 6.4からGUIで設定できるようになりました

PCIの項目の後ろに追加(Ryzenの場合のみ)

#before
hostpci0: 26:00,pcie=1,x-vga=1
#after
hostpci0: 26:00,pcie=1,x-vga=1,romfile=Z_1050Ti_Mod.rom

あとはVMを起動すればモニタが映って、いつものキーボードとマウスが使えるはず。「Please any Key boot from DVD...」が表示されるのですかさずEnterを押す。以後Windowsのインストール作業。
CDドライブに入ったVirtIOのドライバのインストーラ実行やNvidiaのドライバのインストールもあるが、話が長くなったので一旦ここでおしまい。