- Ⅰ. はじめに
- Ⅱ. 環境
- Ⅲ. 手順
- 1. BIOS設定を変更する
- 2. UEFIを利用してUbuntuをインストールする
- 3. GRUBを編集する
- 4. GRUBの設定を反映する
- 5. 再起動する
- 6. IOMMUが有効になったか確認する
- 7. 仮想化ソフトウェアをインストールする
- 8. ユーザのグループにkvm, libvirt を追加する
- 9. QEMUの設定を変更する
- 10. libvirtの設定を変更する
- 11. libvirtdを実行する
- 12. libvirtネットワークを自動起動する
- 13. 仮想化設定確認
- 14. virtioのWindows用ドライバ(ISOファイル)をダウンロードする
- 15. virt-managerを利用して仮想マシンを設定する
- 16. Windowsをインストールする
- 17. nvflashまたはamdvbflashをダウンロードする
- 18. nvflashまたはamdvbflashを実行する
- 19. vbios.romを編集する
- 20. vbios.romを配置する
- 21. スクリプトをcloneする
- 22. 仮想マシンの設定を変更する
- 23. パススルーするPCIデバイス(GPU)を指定する
- 24. 仮想マシンの設定を変更する
- 25. パススルーするUSBデバイス(マウス、キーボードなど)を指定する
- 26. 起動順序を変更する
- 27. NICのリンク状態をアクティブにする
- 28. 実行する
- 29. virtioのドライバをインストールする
- 実行結果
- FAQ
- 参考
Ⅰ. はじめに
タイトルの通り「LinuxでGPUをパススルーして仮想マシンで利用する方法」です。
Ⅱ. 環境
ホスト | Ubuntu 22.04.3 LTS Linux Kernel 6.2.0-34-generic |
ゲスト | Windows 11 Pro 21H2 |
CPU | AMD Ryzen 9 5900X BOX |
GPU | GeForce RTX 4070 Ti |
マザーボード | ASUS TUF GAMING B550-PLUS |
Ⅲ. 手順
1. BIOS設定を変更する
CPUがAMDの場合以下3つを有効にする
1. IOMMU
2. NX mode
3. SVM mode
CPUがIntelの場合以下2つを有効にする
1. VT-d
2. VT-x
※片方しか存在しない場合は片方だけ有効にする
2. UEFIを利用してUbuntuをインストールする
3. GRUBを編集する
$ sudo vim /etc/default/grub # CPUがAMD製の場合 GRUB_CMDLINE_LINUX_DEFAULT="amd_iommu=on quiet splash" # CPUがIntel製の場合 GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on quiet splash"
4. GRUBの設定を反映する
sudo update-grub
5. 再起動する
sudo reboot
6. IOMMUが有効になったか確認する
$ sudo dmesg | grep -i -e DMAR -e IOMMU [ 0.425579] iommu: Default domain type: Passthrough (set via kernel command line)
7. 仮想化ソフトウェアをインストールする
sudo apt install qemu-system-x86 libvirt-clients libvirt-daemon-system libvirt-daemon-config-network bridge-utils virt-manager ovmf
8. ユーザのグループにkvm, libvirt を追加する
sudo usermod -a -G kvm,libvirt $(whoami) # 確認 sudo groups $(whoami)
9. QEMUの設定を変更する
$ sudo vim /etc/libvirt/qemu.conf user = "ENTER_YOUR_USERNAME" group = "ENTER_YOUR_USERNAME"
10. libvirtの設定を変更する
$ sudo vim /etc/libvirt/libvirtd.conf unix_sock_group = "libvirt" unix_sock_rw_perms = "0770" # 以下2行はファイル末尾に追記 log_filters="3:qemu 1:libvirt" log_outputs="2:file:/var/log/libvirt/libvirtd.log"
11. libvirtdを実行する
sudo systemctl enable libvirtd sudo systemctl restart libvirtd
12. libvirtネットワークを自動起動する
sudo virsh net-autostart default
13. 仮想化設定確認
virt-host-validate
14. virtioのWindows用ドライバ(ISOファイル)をダウンロードする
https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md
16. Windowsをインストールする
17. nvflashまたはamdvbflashをダウンロードする
18. nvflashまたはamdvbflashを実行する
# デフォルトターゲットを変更する sudo systemctl set-default multi-user # ディスプレイマネージャを終了する sudo systemctl stop gdm3 # Ctrl + Alt + F2でCUIを表示する # NVFlashを実行する(rmmodコマンド実行を要求された場合は従う) ./nvflash --save vbios.rom # デフォルトターゲットを変更する sudo systemctl set-default graphical # ディスプレイマネージャを起動する sudo systemctl restart gdm3
19. vbios.romを編集する
0x0 〜 0x93FF まですべて削除する
(55 AA 7E EB 4B 37 34 30 30 E9 4C 19 77 CC 56 49 44 45 4F より前を全て削除する)
20. vbios.romを配置する
sudo mkdir /usr/share/vgabios sudo cp vbios.rom /usr/share/vgabios/vbios.rom cd /usr/share/vgabios sudo chmod -R 644 vbios.rom sudo chown ENTER_YOUR_USERNAME:ENTER_YOUR_USERNAME vbios.rom
21. スクリプトをcloneする
git clone https://github.com/kagasu/single-gpu-passthrough cd single-gpu-passthrough sudo chmod +x install_hooks.sh sudo ./install_hooks.sh
22. 仮想マシンの設定を変更する
以下4つの要素を削除する
<graphics type="spice" autoport="yes"> <listen type="address"/> <gl enable="no"/> </graphics>
<audio id="1" type="none"/>
<video> <model type="bochs" vram="16384" heads="1" primary="yes"/> <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/> </video>
<channel type="spicevmc"> <target type="virtio" name="com.redhat.spice.0"/> <address type="virtio-serial" controller="0" bus="0" port="1"/> </channel>
23. パススルーするPCIデバイス(GPU)を指定する
画像の場合は2個指定する(まとめて指定できないので1個ずつ指定する)
24. 仮想マシンの設定を変更する
<rom file='/usr/share/vgabios/vbios.rom'/>
25. パススルーするUSBデバイス(マウス、キーボードなど)を指定する
26. 起動順序を変更する
27. NICのリンク状態をアクティブにする
28. 実行する
29. virtioのドライバをインストールする
実行結果
FAQ
Q. ログの出力先は?
A. 以下ファイルです
/var/log/libvirt/libvirtd.log /var/log/libvirt/qemu/win11.log
Q. 以下ログが出力されています。問題ありますか?
$ sudo cat /var/log/libvirt/libvirtd.log | grep --text error error : virNetSocketReadWire:1793 : End of file while reading data: 入力/出力エラーです
A. 問題ないと思われます。
筆者の環境でも同様のエラーが出力されていますが問題なくゲストが動作しています。
Q. プチフリ(Stutter)が発生します。解決方法は?
A. 筆者の環境では以下3点の設定を行う事で軽減しました。
完全に無くすことはできませんでした。まれにプチフリが発生します。競技レベルでのゲームプレイは難しいです。
1. Huge Pagesを設定する
https://qiita.com/disksystem/items/773cbcb4fd9b0bd2e1ee
2. XMLを編集する
<domain> <cpu mode='host-passthrough' check='none'> <topology sockets='1' cores='n' threads='m'/> + <!-- AMD製CPUでSMTを有効にする --> + <feature policy='require' name='topoext'/> + <!-- ホスト側のCPUキャッシュを仮想CPUにパススルーする --> + <cache mode='passthrough'/> </cpu> + <iothreads>2</iothreads> + <cputune> + <vcpupin vcpu='0' cpuset='1'/> + <vcpupin vcpu='1' cpuset='2'/> + <vcpupin vcpu='2' cpuset='3'/> + <vcpupin vcpu='3' cpuset='4'/> + <vcpupin vcpu='4' cpuset='5'/> + <vcpupin vcpu='5' cpuset='6'/> + <vcpupin vcpu='6' cpuset='7'/> + <vcpupin vcpu='7' cpuset='8'/> + <vcpupin vcpu='8' cpuset='9'/> + <vcpupin vcpu='9' cpuset='10'/> + <vcpupin vcpu='10' cpuset='11'/> + <vcpupin vcpu='11' cpuset='12'/> + <emulatorpin cpuset='13,14'/> + <iothreadpin iothread='1' cpuset='13'/> + <iothreadpin iothread='2' cpuset='14'/> + </cputune> + <memoryBacking> + <hugepages/> + </memoryBacking> - <memballoon model="virtio"> - <address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/> - </memballoon> + <memballoon model="none"/> </domain>
3. ゲスト側Windowsで「メモリ内のページのロック」に任意のユーザを設定する
この設定でHuge Pages(WindowsではLarge Pageと呼ぶ)に対応できる
参考
- https://wiki.archlinux.org/title/PCI_passthrough_via_OVMF
- https://www.reddit.com/r/VFIO/
- https://gitlab.com/risingprismtv/single-gpu-passthrough/-/wikis/1)-Preparations
- https://www.youtube.com/watch?v=53ZO2pKS4i0
- https://www.reddit.com/r/VFIO/comments/oriuiz/amd_ryzen_5900x_optimization_for_gaming/
- https://docs.huihoo.com/redhat/rhel7/pdf/Red_Hat_Enterprise_Linux-7-Virtualization_Tuning_and_Optimization_Guide-ja-JP.pdf
- https://libvirt.org/formatdomain.html
- https://leduccc.medium.com/improving-the-performance-of-a-windows-10-guest-on-qemu-a5b3f54d9cf5