設定 - KVMのGPUパススルー
概要
ここでは、Linuxホスト上にlibvirtd + QEMUで仮想マシンを構築して、グラフィックボードやUSBポートを物理PCと同様に使用できるように設定する。
Linuxの欠点の1つは、利用できるソフトウェアがそれほど多くないことである。
最近では、多くのソフトウェアがLinuxに移植されたのは事実であるが、まだまだWindows専用に開発されたソフトウェアが多い。
Linuxでは、これらのWindows専用ソフトウェアを使用するために、以下に示す4つの方法がある。
- Wineを使用する。
- ただし、Wineは、古いソフトウェアなら機能する場合が多い。
- デュアルブートセットアップを使用して、Windows専用ソフトウェアを使用するたびにWindowsをブートする。
- ただし、手間が掛かる。
- ホストOS型の仮想化ソフトウェアにWindowsの仮想マシンを構築する。
- ただし、グラフィック性能が活かせない。
- GPUパススルーを備えたWindowsの仮想マシンを使用する。
- ハードウェアの前提条件がいくつかある (特定のCPUとGPUでのみ機能する) が、適切なハードウェアがあれば可能である。
基本的な設定の流れは、次のようになる。
- CPUの仮想化支援機能(Intel VT-xまたはAMD-Vi)を有効にする
- グラフィックボードのパススルー設定
- IOMMUの有効化
- Linuxホストのグラフィックボード無効化
- KVM / QEMUのインストール
- ゲストOS作成
- 仮想マシンのチューニングを行った後に仮想マシンをインストールする。
- グラフィックボードのパススルー
- USBデバイスのパススルー設定を行う。
または、SynergyあるいはBarrier (開発停止) を使用する。
Synergyのインストールは、インストール - マウス・キーボード共有ソフトウェアのページを参照すること。
ここでは、実際に設定を行うPCの環境は、以下の通りである。
- CPU
- Ryzen 3900X
- M/B
- GIGABYTE X570 UD(BIOS F37e)
- GPU 1
- 玄人志向 Radeon RX550 LP
- GPU 2
- GIGABYTE GeForce GT1030
- OS
- SLE (Linuxカーネル 5.14.21)
前提条件
- 2枚以上のグラフィックボード(マザーボード内蔵でも可)が必要である
- 1つはLinuxホストで使用され、もう1つはWindowsを実行している仮想マシン(以降、VMという)で使用される。
- また、VMにIntel統合GPU(Intel UHD等)を使用することはできない。ATI製またはnVidia製のみ使用できる。
- ただし、LinuxホストにIntel統合GPUを使用することはできる。
- グラフィックボードがUEFIに対応していること。
こちらのWebサイトに記載されているグラフィックボードであればよい。 - CPUの機能において、Intel VT-DまたはAMD-Viをサポートするマザーボードが必要である。
- リストの一部はこのWebサイトにある。BIOS上で有効にする必要がある。
- PCIのルートポートは、VMで使用するGPUと同じIOMMUグループの一部であってはならない。(詳細は後述)
- VMが使用するプライマリディスプレイの空き入力ポートまたはセカンダリディスプレイの空き入力ポートがあること。
BIOSの設定
まず最初に、BIOSの設定画面を表示して、以下の項目の設定を変更する。
なお、以下の項目はマザーボードがGIGABYTE X570UDのものである。
F12までのBIOS
- AMD-Viの有効化
- [M.I.T.] - [高度な周波数設定] - [Advanced CPU Settings] - [SVM Mode]を[Enable]に変更する。
- IOMMUの有効化
- [チップセット] - [IOMMU]を[Enable]に変更する。
- ACSの有効化
- [周辺機器] - [AMD CBS] - [ACS Enable]を[Enable]に変更する。
- AER Capの有効化
- [周辺機器] - [AMD CBS] - [Enable AER Cap]を[Enable]に変更する。
F12より新しいBIOS
- AMD-Viの有効化
- [M.I.T.] - [高度な周波数設定] - [Advanced CPU Settings] - [SVM Mode]を[Enable]に変更する。
- IOMMUの有効化
- [チップセット] - [IOMMU]を[Enable]に変更する。
- IOMMUの有効化
- [周辺機器] - [AMD CBS] - [NBIO Common Options] - [IOMMU]を[Enable]に変更する。
- ACSの有効化
- [周辺機器] - [AMD CBS] - [NBIO Common Options] - [ACS Enable]を[Enable]に変更する。
- AER Capの有効化
- [周辺機器] - [AMD CBS] - [NBIO Common Options] - [Enable AER Cap]を[Enable]に変更する。
GPUパススルーの自動設定
もし、下記のセクションの手動設定が面倒と考える場合、以下の自動設定を行うシェルスクリプトをダウンロードする。
ファイル:GPU-PassThrough.zip
まず、gpu-passthrough.shをスーパーユーザ権限で実行する。
これは、必要なソフトウェアをインストールして、GPUパススルーに必要な設定を行った後、initrdを再構築するシェルスクリプトである。
sudo ./gpu-passthrough.sh
SUSEを再起動する。
次に、分離するGPU(VMで使用するGPU)を確認する。
Kernel driver in use:と記載されいている箇所を探す。正常に分離されていれば、vfio-pci
と記載される。
sudo lspci -nnk
KVMを起動して、[QEMU/KVM]にフォーカスを当てて[編集]メニュー - [接続の詳細]を選択する。
[接続の詳細]画面が起動するので、[仮想ネットワーク]タブを選択して、[Autostart:]項目の[On Boot]チェックボックスにチェックを入力する。
後は、下記の[ゲストOSの作成]セクションに移動して、VMの作成および設定を行う。
なお、この手順は以下に示す動画を参考にしている。
KVM / QEMUのインストール
KVM / QEMUおよび依存関係のライブラリをインストールする。
- SLES / openSUSE
sudo zypper install libvirt libvirt-client libvirt-daemon virt-manager virt-install virt-viewer \
qemu qemu-kvm qemu-ovmf-x86_64 qemu-tools \
biosdevname
- SLED
- ソースコードからKVMとQEMUをインストールする場合、インストール - KVM#ソースコードからインストールを参照する。
- または、以下のパッケージをダウンロードして、~/.profileファイル等に環境変数PATHおよびLD_LIBRARY_PATHを追記する。
- libvirt : https://software.opensuse.org/package/libvirt
- libvirt-client : https://software.opensuse.org/package/libvirt-client
- libvirt-daemon : https://software.opensuse.org/package/libvirt-daemon
- virt-manager : https://software.opensuse.org/package/virt-manager
- virt-install : https://software.opensuse.org/package/virt-install
- virt-viewer : https://software.opensuse.org/package/virt-viewer?search_term=virt-viewer
- qemu : https://software.opensuse.org/package/qemu
- qemu-kvm : https://software.opensuse.org/package/qemu-kvm
- qemu-ovmf-x86_64 : https://software.opensuse.org/package/qemu-ovmf-x86_64
- qemu-tools : https://software.opensuse.org/package/qemu-tools?search_term=qemu-tools
こちらのWebサイトから、VirtIOドライバをダウンロードする。
ラップトップPC上のdGPUを通過させるための手順
この手順は、ACPIの呼び出しを使用してdGPUファームウェアを読み込まないラップトップPCにのみ適用される。
dGPUファームウェアを読み込むためにACPIの呼び出しを使用するラップトップPCについては、u/jscinoz'sのoptimus-vfio-docsを参照すること。
現状、ACPIの呼び出しでdGPUがファームウェアを読み込むかどうかを確認する方法は不明である。
最近の多くのOptimusなラップトップPCはMUXレス方式を採用しているが、
HP/Thinkpad/Dellモバイルワークステーション、Clevo P650、Alienwareの一部等はMUXed方式を採用している。
Optimusソリューションが登場する前の時代には、グラフィックスカードを切り替えるために再起動が必要で、1度に1つしか使用できない古いMUXed方式があったが、
最新のMUXed方式では、OptimusとdGPUのみを切り替えることができ、Optimus使用時にはディスプレイ出力ポートをdGPUに直接接続することもできる。(一部のラップトップPCにのみ適用)
MUXレス方式でCode 43(エラーコード)に遭遇したPCは、(ゲストOSでdGPUを見ることができ、NVIDIAドライバも問題なくインストールできるにもかかわらず)
ACPIの呼び出しがdGPUファームウェアの読み込みに失敗したためである。
これは、NVIDIAドライバがvfio-pciを通して提供されたROMを使用する代わりに、UEFIからdGPUのROMを読み込もうとしているからである。
このような問題が発生した場合は、u/jscinozのoptimus-vfio-docsを参照すること。
MUXレスの成功報告があるラップトップPCを以下に示す。
- MSI GS60-040XFR
- MSI GS60 2PC
- ASUS G751JM
この手順で可能になる事柄を以下に示す。
- Bumblebeeを使用することにより、オンデマンドでNVIDIA dGPUの電源オン / オフすることが可能である。
- ホストPCにNVIDIA dGPUが不要の場合は、ゲストOSにNVIDIA dGPUを渡すことができる。
- ゲストOSのシャットダウン時にdGPUを戻すことができる。
- dGPUのバインド / アンバインドプロセス中に再起動する必要はない。
- 外部ディスプレイは必須ではない。(ハードウェアとVMが実行しているWindowsのバージョンに依存する)
- また、外部ディスプレイを直接ゲストOSに接続することができる。
使用しているNVIDIAグラフィックスカード (dGPU) がMUXedまたはMUXlessかどうかを確認する。
BIOS/UEFIオプションにおいて、integrated graphics / PCI graphicsが選択できる場合、MUXedである。
選択できない場合はMUXレスである。
MUXedの場合は、https://gist.github.com/Misairu-G/616f7b2756c488148b7309addc940b28 を参照すること。
MUXレスの場合、https://github.com/jscinoz/optimus-vfio-docs を参照すること。
IOMMUの有効化
Intel VT-xとAMD-Viは、一般的にIOMMUと呼ばれる。
IOMMUを有効にするには、/etc/default/grubファイル(ブートローダファイル)にあるGRUB_CMDLINE_LINUX_DEFAULTセクションに以下の設定を追記する。
iommu=pt
は、カーネルにDMA変換をメモリにバイパスするように指示する。これにより、パフォーマンスが向上する場合がある。
# Intel CPU intel_iommu=on iommu=pt # AMD CPU amd_iommu=on iommu=pt
grubを再構築するために、以下のコマンドを実行する。
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Linuxを再起動する。
再起動後、IOMMUが有効になっているか確認するため、以下のコマンドを実行する。
# Intel CPU dmesg | grep -e DMAR -e IOMMU # AMD CPU dmesg | grep AMD-Vi
有効化されている場合は、以下のようなメッセージが出力される。
# Intel CPU DMAR: IOMMU enabled ・ ・ ・ # AMD CPU [ 1.643621] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported [ 1.645069] pci 0000:00:00.2: AMD-Vi: Found IOMMU cap 0x40 [ 1.645069] pci 0000:00:00.2: AMD-Vi: Extended features (0x58f77ef22294ade): [ 1.645071] AMD-Vi: Interrupt remapping enabled [ 1.645072] AMD-Vi: Virtual APIC enabled [ 1.645072] AMD-Vi: X2APIC enabled [ 1.645153] AMD-Vi: Lazy IO/TLB flushing enabled [ 2.486602] AMD-Vi: AMD IOMMUv2 driver by Joerg Roedel <jroedel@suse.de>
次に、IOMMUグループが有効であることを確認する。
以下のシェルスクリプトを作成して実行する。(ここでは、シェルスクリプトのファイル名をlsIOMMU.shとする)
#!/bin/bash
shopt -s nullglob
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done;
# 実行 chmod u+x lsIOMMU.sh sudo ./lsIOMMU.sh
出力結果は下図のようになる。この図から、2つのことが分かる。
VMで使用するデバイスがどのIOMMUグループであるか(下図の場合は、グループ11)およびそのベンダー/モデルID(下図の場合は、1002:683fおよび1002:aab0)である。
この出力結果は、IOMMUグループ内で(関連付けられているオーディオデバイスを無視して)単独のデバイスに対してのみ機能する。
複数のGPUの分離
2つ以上のGPUを分離する必要がある。
これは、異なるメーカーのGPUが2つある場合(ここでは、VMで使用するGPUをブラックリストに登録するだけ)は非常に簡単であるが、
両方のGPUが同じベンダーのものである場合は少し複雑になる。
また、両方のGPUが同じモデルの場合、さらに複雑になる。
GPUが同じベンダーのものであったとしても、両方のGPUが完全に同じモデルでない限り、この設定に従うことができる。
また、グラフィックカードのHDMIオーディオデバイスもパススルーすること。
ただし、この設定では、2つの全く同一のGPUでは機能しないので注意すること。(Radeon RX550が2枚など)
2つのグラフィックボードがそれぞれ異なる場合(nVidia製とATI製)
/lib/modprobe.d/50-blacklist.confファイル、または、/etc/modprobe.d/50-blacklist.confファイルを編集して、以下の内容を追記する。
# SUSE 15.4以降の場合 sudo vi /lib/modprobe.d/50-blacklist.conf # SUSE 15.3以前の場合 sudo vi /etc/modprobe.d/50-blacklist.conf
# LinuxホストにATI製グラフィックボード、VMにnVidia製グラフィックボードを使用する場合 blacklist nouveau blacklist nvidia # LinuxホストにnVidia製グラフィックボード、VMにATI製グラフィックボードを使用する場合 blacklist amdgpu blacklist radeon
2つのグラフィックボードが同じ場合(両方ともnVidia製または両方ともATI製)
まず、/lib/modprobe.d/gpu-passthrough.confファイル、または、/etc/modprobe.d/gpu-passthrough.confファイルを作成して、以下のように編集する。
ここで、<VMで使用するGPUのベンダー>と<VMで使用するGPUのモデルID>は、上記セクションで実行したlsIOMMU.shの出力結果に記載されている。
# SUSE 15.4以降の場合 sudo vi /lib/modprobe.d/gpu-passthrough.conf # SUSE 15.3以前の場合 sudo vi /etc/modprobe.d/gpu-passthrough.conf
# /lib/modprobe.d/gpu-passthrough.confファイル または /etc/modprobe.d/gpu-passthrough.confファイル options vfio-pci ids=<VMで使用するGPUのベンダー>,<VMで使用するGPUのモデルID>
例えば、上記セクションの結果から、以下のように記述する。
また、options vfio-pci disable_vga=1
は、ホストPCがLinuxカーネル 4.1以降、かつ、ゲストOSがUEFIの場合のみ有効である。
VGAアービトレーションがホストデバイスに干渉するのを防ぐのに役立つ。
# /lib/modprobe.d/gpu-passthrough.confファイル # または # /etc/modprobe.d/gpu-passthrough.confファイル options vfio-pci ids=10de:1d01,10de:0fb8 options vfio-pci disable_vga=1
また、Windows10 1803以降をインストールする場合は、以下の設定も追記する。
しかし、Linuxカーネル 5.9.1以降はこのオプションが問題を引き起こすという報告がある。
個人的には、kvm.ignore_msrs=1
オプションを付加して、問題が発生する場合は当オプションを削除する方法を推奨する。
# SUSE 15.4以降の場合 sudo vi /lib/modprobe.d/gpu-passthrough.conf # SUSE 15.3以前の場合 sudo vi /etc/modprobe.d/gpu-passthrough.conf
# /lib/modprobe.d/gpu-passthrough.confファイル または /etc/modprobe.d/gpu-passthrough.confファイル options kvm ignore_msrs=1
自動ロードするモジュールのリストにドライバを追加するため、/etc/modules-load.d/vfio-pci.confファイルを作成して、以下の内容を記述する。
sudo vi /etc/modules-load.d/vfio-pci.conf
# /etc/modules-load.d/vfio-pci.confファイル # Intel CPUの場合 pci_stub vfio vfio_iommu_type1 vfio_pci kvm kvm_intel # AMD CPUの場合 pci_stub vfio vfio_iommu_type1 vfio_pci kvm kvm_amd
次に、/etc/default/grubファイルを開く。
vfio-pciをパススルーするGPUにバインドするため、GRUB_CMDLINE_LINUX_DEFAULTにrd.driver.pre=vfio-pci
を追記する。
# /etc/default/grubファイル GRUB_CMDLINE_LINUX_DEFAULT="〜 rd.driver.pre=vfio-pci"
vfio-pciドライバの先読み設定
vfio-pciドライバの先読み設定を行う。
SUSEおよびRedHat系は、/etc/sysconfig/kernelファイルを作成して設定する。
Ubuntuでは、/etc/dracut.conf.d/gpu-passthrough.confファイルを作成して設定する。
ただし、SUSEでは、上記のどちらの手順でも正常にvfio-pciドライバの先読み設定を行うことができた。
※調査中
pci_stub
オプションは不要の可能性がある。
sudo vi /etc/dracut.conf.d/gpu-passthrough.conf
# /etc/dracut.conf.d/gpu-passthrough.confファイル # Intel CPUの場合 add_drivers+=" pci_stub vfio vfio_iommu_type1 vfio_pci vfio_virqfd kvm kvm_intel " # AMD CPUの場合 add_drivers+=" pci_stub vfio vfio_iommu_type1 vfio_pci vfio_virqfd kvm kvm_amd " # または # Intel CPUの場合 add_drivers+=" vfio vfio_iommu_type1 vfio_pci vfio_virqfd " # AMD CPUの場合 add_drivers+=" vfio vfio_iommu_type1 vfio_pci vfio_virqfd "
上記の設定を有効化するため、initrdを再構築する。
sudo dracut -f /boot/initrd $(uname -r)
initrdの再構築の完了後、Linuxホストを再起動する。
設定ミスで失敗すると、Linuxホストが起動できなくなる可能性があるので注意すること。
GPUが分離されていることを確認
GPUが分離されているか確認する。
以下のコマンドを実行して、使用中のカーネルドライバーを探す。
sudo lspci -nnv
分離するGPU(VMで使用するGPU)を確認するには、Kernel driver in use:と記載されいている箇所を探す。
正常に分離されていれば、vfio-pciと記載される。
03:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP108 [GeForce GT 1030] [10de:1d01] (rev a1) Subsystem: Gigabyte Technology Co., Ltd Device [1458:375d] Kernel driver in use: vfio-pci Kernel modules: nouveau 03:00.1 Audio device [0403]: NVIDIA Corporation GP108 High Definition Audio Controller [10de:0fb8] (rev a1) Subsystem: Gigabyte Technology Co., Ltd Device [1458:375d] Kernel driver in use: vfio-pci Kernel modules: snd_hda_intel
QEMUのアクセス権限の付与
別のHDD / SSDに仮想マシンを配置する場合、初期設定ではアクセス権限エラーになる。
そこで、/etc/libvirt/qemu.confファイルに以下の設定を追記する。
# /etc/libvirt/qemu.confファイル ・ ・ ・ user = "root" group = "root"
また、別のHDD / SSDに仮想マシンを配置する時は、配置先のディレクトリで以下のコマンドを実行する。
以下では、<仮想マシン名>.qcow2ファイルを最大100[GB]の領域で仮想マシンを作成している。
qemu-img create -f qcow2 <仮想マシン名>.qcow2 100G
X11の設定
上記の設定の状態では、PC起動時においてパススルーしたGPUを先に読み込むため、ホストOSの画面が表示されない。
ホストOS向けのGPUを先に読む込む必要があるため、/etc/X11/xorg.conf.installファイルに以下の設定を追記する。
sudo vi /etc/X11/xorg.conf.install
# /etc/X11/xorg.conf.installファイル # ...略 # 以下の設定を追記 Section "Device" Identifier "amdgpu" Driver "amdgpu" EndSection # 以下の設定を追記 Section "Screen" Identifier "amdgpu" Device "amdgpu" EndSection # Screen "amdgpu"を追記 Section "ServerLayout" # ...略 Screen "amdgpu" # 追加 EndSection
ゲストOSの作成
あらかじめ、Microsoftの公式Webサイトで、Windows10のisoファイルをダウンロードする。
併せて、virtio-winのGithubまたはFedoraの公式Webサイトにアクセスして、virtio-win-<バージョン>.isoファイルもダウンロードする。
Windows 10 / 11 / Linuxの場合
- まず、SUSE 15.1を使用している場合は、
/etc/libvirt/qemu.conf
ファイルを開いて、nvramセクションを以下のように編集する。nvram = ["/usr/share/qemu/ovmf-x86_64.bin:/usr/share/qemu/ovmf-x86_64-code.bin"]
- libvirtデーモンを再起動する。
sudo systemctl restart libvirtd
- 必要であれば、以下のように、libvirtdを自動起動するように設定する。
sudo systemctl enable libvirtd
- Virtual Machine Managerを起動して、新しいVMを作成する。
[Architecture Option]画面では、[Local Install Media]と[x86_64]を選択する。 - [Use ISO Imege]項目を選択して、Windows10のISOファイルを選択する。
- VMに割り当てるメモリ容量とCPUのコア数を選択する。
- VMのディスクイメージを作成する。(既に定義されている場合は選択する。また、ディスク全体でも構わない。パスをそこに配置して、ホストにマウントされていないことを確認する)
- VMに名前を付けて、[Customize configuration before install]チェックボックスにチェックが入力されていることを確認して、[Finish]ボタンを押下する。
- VM構成画面(以降、メイン画面という)に移動する。
メイン画面左の[Overview]を選択して、[Chipset:]プルダウンおよび[Firmware:]プルダウンを以下の値に設定する。- ホストOSがSUSE 15.1の場合
- [Chipset:] : i440FX
- [Firmware:] : BIOS または UEFI
- ホストOSがSUSE 15.2以降かつゲストOSがWindows XPの場合
- [Chipset:] : i440FX
- [Firmware:] : BIOS または UEFI
- ホストOSがSUSE 15.2以降かつゲストOSがWindows 7の場合
- [Chipset:] : Q35
- [Firmware:]は、以下のいずれかを選択する。
- [Firmware:] : UEFI X86_64: ovmf-x86_64-smm-code.bin
- [Firmware:] : UEFI X86_64: ovmf-x86_64-code.bin
- [Firmware:] : UEFI X86_64: ovmf-x86_64-4m-code.bin
- ホストOSがSUSE 15.2以降かつ上記以外のゲストOSの場合
- [Chipset:] : Q35
- [Firmware:]は、以下のいずれかを選択する。
- [Firmware:] : UEFI X86_64: ovmf-x86_64-smm-ms-code.bin
- [Firmware:] : UEFI X86_64: ovmf-x86_64-opensuse-code.bin
- メイン画面左の[CPUs]で、[Configuration]項目の[Model: ]プルダウンから、[host-passthrough]を選択する。(プルダウンに存在しない場合は、
host-passthrough
と入力する) - メイン画面左下の[Add Hardware]ボタンを押下すると、[Add New Virtual Hardware]画面が表示される。
この画面左の[Controller]を選択して、[Type: ]項目にSCSI、[Model: ]項目にVirtIO SCSIと入力する。
(パフォーマンスを向上させるために、タイプを必ずVirtIO SCSIに変更する) - メイン画面左の[SCSI Disk 1]を選択して、[Advanced Options]項目の[Disk bus]項目にSCSIを選択する。
- [Add New Virtual Hardware]画面左の[Storage]を選択して、[管理]ボタンを押下して、
"KVM / QEMUのインストール"セクションでダウンロードしたvirtio-win-<バージョン名>.isoファイルを選択する。
[デバイスの種類]項目には、[CD-ROMデバイス]を選択する。 - [Add New Virtual Hardware]画面左の[PCI Host Device]を選択して、分離されたGPUとサウンドカード(ここでは、PCIデバイス02:00.0とPCIデバイス02:00.1)を追加する。
- [Add New Virtual Hardware]画面左の[USB Host Device]を選択して、キーボードとマウスを追加する。
- Windows 10 / 11の場合、[Add New Virtual Hardware]画面左の[TPM]を選択して、
[種類]プルダウンから[Emulated]、[モデル]プルダウンから[TIS]、[バージョン]プルダウンから[2.0]を選択して、追加する。 - 同様に、不要なデバイス(タブレット、ディスプレイスパイス、シリアル、コンソール、チャンネルスパイス等)を全て削除する。
RHELやSLE等の場合は、Synergy / Barrierの動作に支障があるため、ビデオQXLを有効にして、ディスプレイSpiceおよびビデオは削除しない。
ディスプレイにサウンド出力がない場合またはVGA経由で接続する場合は、サウンドカードが必要である。
1000円程度の安価なUSBサウンドカードを購入してPCに取り付けた場合、キーボードとマウスを追加した際と同様にして追加する。 - VMに割り当てたばかりのグラフィックボードをディスプレイに接続し、[Begin Installation]ボタンを押下する。
全て正しく設定されていれば、そのディスプレイにVMが起動していることがわかる。 - Windows10をインストール画面の手順に従ってインストールする。
インストール完了後、Windows10のデバイスマネージャーを起動して、マウントされているvirtio-win-<バージョン名>.isoファイルから各種ドライバをインストールする。
Windows 7の場合
- Virtual Machine Managerを起動して、新しいVMを作成する。
[Architecture Option]画面では、[Local Install Media]と[x86_64]を選択する。 - [Use ISO Imege]項目を選択して、Windows 7のISOファイルを選択する。
- VMに割り当てるメモリ容量とCPUのコア数を選択する。
この時、CPUの割り当てを1
にする。 - VMのディスクイメージを作成する。(既に定義されている場合は選択する。また、ディスク全体でも構わない。パスをそこに配置して、ホストにマウントされていないことを確認する)
- VMに名前を付けて、[Customize configuration before install]チェックボックスにチェックが入力されていることを確認して、[Finish]ボタンを押下する。
- VM構成画面(以降、メイン画面という)に移動する。
メイン画面左の[Overview]を選択して、[Chipset:]プルダウンおよび[Firmware:]プルダウンを以下の値に設定する。- ホストOSがSUSE 15.1の場合
- [Chipset:] : i440FX
- [Firmware:] : UEFI
- ホストOSがSUSE 15.2以降かつゲストOSがWindows 7の場合
- [Chipset:] : Q35
- [Firmware:]は、以下のいずれかを選択する。
- [Firmware:] : UEFI X86_64: ovmf-x86_64-smm-ms-code.bin
- [Firmware:] : UEFI X86_64: ovmf-x86_64-smm-code.bin
- メイン画面左の[CPUs]で、[Configuration]項目の[Model: ]プルダウンから、[host-passthrough]を選択する。(プルダウンに存在しない場合は、
host-passthrough
と入力する) - メイン画面左の[NIC 〜]で、[デバイスのモデル]プルダウンから[ハイパーバイザーのデフォルト]を選択する。
- [Add New Virtual Hardware]画面左の[Storage]を選択して、[管理]ボタンを押下して、
"KVM / QEMUのインストール"セクションでダウンロードしたvirtio-win-<バージョン名>.isoファイルを選択する。
[デバイスの種類]項目には、[CD-ROMデバイス]を選択する。 - [Add New Virtual Hardware]画面左の[USB Host Device]を選択して、キーボードとマウスを追加する。
- 分離されたGPUとサウンドカード(下図では、PCIデバイス03:00.0とPCIデバイス03:00.1)は追加しないことに注意する。
- ここまでの設定を行うことにより、下図のようになる。
- [Begin Installation]ボタンを押下して、ゲストOSを起動する。
- UEFIシェル(仮想マシンのブート設定画面)を起動して、[Device Manager] - [Secure Boot Configuration] - [Attempt Secure Boot]チェックボックスのチェックを外して、セキュアブートを無効にする。
- 設定を保存した後、すぐに仮想マシンをシャットダウンする。
※まだ、Windows 7はインストールしないことに注意する。 - 仮想マシンの設定ファイル(XML拡張子)を、以下に示すように編集する。
sudo virsh edit <仮想マシン名>
- # 最初の行を変更する
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
- または
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
- # ファイルの最下行にある
</devices>
と</domain>
の間に追記する - # (
host=03:00.0
の箇所は、必要に応じてユーザの環境に合わせること) <qemu:commandline>
<qemu:arg value='-device'/>
<qemu:arg value='vfio-pci,host=03:00.0,id=hostpci0.0,bus=pcie.0,addr=0x10.0,multifunction=on'/>
<qemu:arg value='-device'/>
<qemu:arg value='vfio-pci,host=03:00.1,id=hostpci0.1,bus=pcie.0,addr=0x10.1'/>
<qemu:arg value='-cpu'/>
<qemu:arg value='host,kvm=off,hv_vendor_id=null'/>
<qemu:arg value='-machine'/>
<qemu:arg value='q35,kernel_irqchip=on'/>
</qemu:commandline>
- 次に、libvirtdおよびQEMUの設定ファイル(/etc/libvirt/qemu.confファイル)の最下行に、以下に示す設定を追記する。
sudo vi /etc/libvirt/qemu.conf
cgroup_device_acl = [
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm",
"/dev/vfio/20", "/dev/vfio/vfio"
# /dev/vfio/20ファイルは、使用している環境により、数値の部分が異なる場合があることに注意する]
- libvirtdデーモンを再起動する。
sudo systemctl restart libvirtd
- VMに割り当てるGPUをディスプレイに接続し、仮想マシンを起動する。
- UEFIシェル(仮想マシンのブート設定画面)のブートセレクションからWindows 7インストーラがあるストレージを選択して、Windows 7をインストールする。
インストール完了後、Windows 7のデバイスマネージャーを起動して、マウントされているvirtio-win-<バージョン名>.isoファイルから各種ドライバをインストールする。 - Windowsアップデートを行う。
Windowsアップデート行う前に、下記の※注意2を参照して、いくつかのパッチをインストールする必要があることに注意する。 - NVidiaのGPUドライバをインストールする。
NVidiaのGPUドライバは、公式Webサイトからダウンロードすること。 - 仮想マシンをシャットダウンして、 [仮想CPU 割り当て]項目から、VMに割り当てるCPUのコア数を設定する。
ただし、[トポロジー] - [CPUトポロジーの手動設定]は設定しないこと。(UEFIシェル画面でハングするため) - 不要であれば、使用しないデバイス(タブレット、ディスプレイスパイス、コンソール、チャンネルスパイス、ビデオQXL等)を全て削除する。
※注意 1
仮想マシンを実行する時、以下に示すようなエラーが出力される場合がある。
audio: Could not init spice' audio driver
この問題を解決するには、Virt-Managerを起動して、画面左ペインにある[概要]から[XML]タブを選択して、オーディオの種類をspice以外のものに変更する必要がある。
# 編集前
<audio id='1' type='spice'/>
# 編集後
<audio id='1' type='none'/>
※注意 2
2023/03現在、Windows 7を新規インストールした場合は、Windowsアップデートができない。
そのため、Microsoftの公式Webサイトから、いくつかのWindows 7の更新プログラムを直接ダウンロードおよびインストールする必要がある。
以下のURLでは、Windows 7 x64向けであることに注意する。
- Windowsアップデートが動作しない場合
- Windows 7 用更新プログラム (KB3138612)をインストールする。
- https://www.microsoft.com/ja-jp/download/details.aspx?id=51208
- または
- https://www.catalog.update.microsoft.com/Search.aspx?q=KB3138612
- Windows7の更新プログラムのインストールがいくつか失敗するものがある場合
- 2019-03 x64ベースシステム用Windows 7 サービススタック更新プログラム (KB4490628)をインストールして、サービススタックを更新する。
- https://www.catalog.update.microsoft.com/search.aspx?q=kb4490628
必要であれば、以下に示す更新プログラムもインストールする。
- windows6.1-kb2533552-x64_0ba5ac38d4e1c9588a1e53ad390d23c1e4ecd04d.msu
- windows6.1-kb3020369-x64_5393066469758e619f21731fc31ff2d109595445.msu
- windows6.1-kb3125574-v4-x64_2dafb1d203c8964239af3048b5dd4b1264cd93b9.msu
- windows6.1-kb976932-x64_74865ef2562006e51d7f9333b4a8d45b7a749dab.exe
※ SP1をインストールしていない場合のみ
Windows XPの場合
- Virtual Machine Managerを起動して、新しいVMを作成する。
[Architecture Option]画面では、[Local Install Media]と[x86_64]を選択する。 - [Use ISO Imege]項目を選択して、Windows XPのISOファイルを選択する。
- VMに割り当てるメモリ容量とCPUのコア数を選択する。
この時、CPUの割り当てを2
にする。 - VMのディスクイメージを作成する。(既に定義されている場合は選択する。また、ディスク全体でも構わない。パスをそこに配置して、ホストにマウントされていないことを確認する)
- VMに名前を付けて、[Customize configuration before install]チェックボックスにチェックが入力されていることを確認して、[Finish]ボタンを押下する。
- VM構成画面(以降、メイン画面という)に移動する。
メイン画面左の[Overview]を選択して、[Chipset:]プルダウンおよび[Firmware:]プルダウンを以下の値に設定する。- [Chipset:] : i440FX
- [Firmware:] : BIOS
- メイン画面左の[CPUs]で、[Configuration]項目の[Model: ]プルダウンから、[host-passthrough]を選択する。(プルダウンに存在しない場合は、
host-passthrough
と入力する) - メイン画面左の[NIC 〜]で、[デバイスのモデル]プルダウンから[ハイパーバイザーのデフォルト]を選択する。
- [Add New Virtual Hardware]画面左の[Storage]を選択して、[管理]ボタンを押下して、
"KVM / QEMUのインストール"セクションでダウンロードしたvirtio-win-<バージョン名>.isoファイルを選択する。
[デバイスの種類]項目には、[CD-ROMデバイス]を選択する。 - [Add New Virtual Hardware]画面左の[PCI Host Device]を選択して、分離されたGPUとサウンドカード(ここでは、PCIデバイス02:00.0とPCIデバイス02:00.1)を追加する。
- [Add New Virtual Hardware]画面左の[USB Host Device]を選択して、キーボードとマウスを追加する。
- VMに割り当てたばかりのグラフィックボードをディスプレイに接続し、[Begin Installation]ボタンを押下する。
全て正しく設定されていれば、そのディスプレイにVMが起動していることがわかる。 - Windows XPをインストール画面の手順に従ってインストールする。
インストール完了後、Windows XPのデバイスマネージャーを起動して、マウントされているvirtio-win-<バージョン名>.isoファイルから各種ドライバをインストールする。
仮想マシンの設定
ゲストOSがopenSUSEの場合
ゲストOSがopenSUSEの場合、/etc/default/grubファイルのGRUB_CMDLINE_LINUX_DEFAULT
項目に、pci=noaer
オプションを追記する。
GRUB_CMDLINE_LINUX_DEFAULT="... pci=noaer"
AMD CPUのパフォーマンスの改善
以前、AMD CPUでは、Nested Page Tables(NPT)を無効化することでKVMのGPU性能を引き上げることができた。
これは、バグが原因で、トレードオフとしてCPUの性能が落ちて、がたつきが発生することがあった。
Linuxカーネル 4.9以降からこの問題を解決するカーネルパッチがマージされている。
LinuxカーネルまたはLinux-LTSカーネルを使用している場合、パッチは既に適用されている。
※注意
QEMU 3.1以降、TOPOEXTフラグは標準で無効化されており、
AMD CPUでハイパースレッディングを使用するには、以下のように、手動で有効にする必要がある。
cache passthroughの設定は、実際のCPUキャッシュ情報を仮想マシンに渡す。
<!-- ゲストOSがWindows 10 / 11またはSUSEの場合 -->
<cpu mode="host-passthrough" check="none">
<topology sockets="1" cores="4" threads="2"/>
<cache mode="passthrough"/>
<feature policy="require" name="topoext"/>
</cpu>
<!-- ゲストOSがWindows 7の場合 -->
<cpu mode="host-passthrough" check="none">
<topology sockets="1" cores="4" threads="2"/>
<cache mode="passthrough"/>
<feature policy='disable' name='hypervisor'/>
</cpu>
<!-- ゲストOSがWindows XPの場合 -->
<cpu mode="host-passthrough" check='none'>
<topology sockets='1' cores='2' threads='2'/>
<feature policy='require' name='topoext'/> <!-- ←この設定は不要の可能性あり -->
</cpu>
更にパフォーマンスを向上させるため、<features>
タグ内に<hyperv>
タグとそのエレメントを設定する。
<!-- ゲストOSがWindows 10 / 11の場合 -->
<hyperv>
<relaxed state="on"/>
<vapic state="on"/>
<spinlocks state="on" retries="8191"/>
<vendor_id state="on" value="0123456789ab"/>
<vpindex state="on"/>
<synic state="on"/>
<stimer state="on"/>
<frequencies state="on"/>
</hyperv>
<!-- ゲストOSがopenSUSEの場合 -->
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='0123456789ab'/>
</hyperv>
<!-- ゲストOSがWindows 7の場合 -->
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='0123456789ab'/>
</hyperv>
<!-- ゲストOSがWindows XPの場合 -->
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='none'/>
</hyperv>
GPUがNVIDIA Geforceの場合 (error code 43)
仮想マシンのデバイスマネージャでグラフィックボードを確認すると、"エラー43:ドライバーの読み込みに失敗しました"と表示されて、正常に機能しない場合がある。
この問題は、NVidia GeForceシリーズのみ起こり(QuadroやTeslaにはこの問題は無い)、ユーザが仮想マシンでそれらを使用しようとすると、機能を意図的に無効化する。
理由としては、仮想マシンでグラフィックカードを実行できるようになると、自社の製品の売上に悪影響を与える可能性があるからである。
GeforceのGPUパススルーを正常に動作させるには、ハイパーバイザがその存在を隠すことで出来る。
具体的な手順は以下の通りである。
手動での設定
まず、KVMを開始する。
sudo systemctl start libvirtd
GPUパススルーを行う仮想マシンのxmlファイルを編集する。
sudo EDITOR=nano virsh edit <仮想マシン名>
<hyperv>
タグ内にvendor_id
タグを記述する。
この時、value
属性はどのような値でもよい。
ただし、vendor_idタグの設定は、Quadro 2000以降のQuadroカードでは不要である。
<features>
...略
<hyperv>
...略
<vendor_id state="on" value="123456789ab"/>
</hyperv>
...略
</features>
次に、状態を非表示にするようにKVMに指示するため、<hyperv>
タグ外の直下に、kvm
タグとhidden
タグを記述する。
ただし、hiddenタグの設定も、Quadro 2000以降のQuadroカードでは不要である。
<features>
...略
<hyperv>
...略
</hyperv>
...略
<kvm>
<hidden state='on'/>
</kvm>
</features>
QEMU 4.0以降で仮想マシンにQ35チップセットを使用する場合、features
タグ内にioapic
タグを記述する。
<features>
...略
<ioapic driver="kvm"/>
</features>
最後に、KVMを再起動する。
sudo systemctl restart libvirtd
自動での設定
GitHubにあるvirsh-patcherパッケージは、簡単に上記の方法を行うことができる。
git clone https://github.com/PassthroughPOST/virsh-patcher virsh-patcher
以下のコマンドを実行して修正を適用する。
sudo virshpatcher --error43 --vendor-id 123456789ab <仮想マシン名>
SynergyまたはBarrierのインストール
ゲストOSのインストールが完了した後、Synergy(有償ソフトウェア)またはBarrierをインストールすることを推奨する。
これらは、物理的なKVM (Keyboard-Video-Mouse) スイッチなしで、複数のPCで同じキーボードとマウスを使用できる。
SynergyおよびBarrierの概要およびインストール手順を知りたい場合は、インストール - マウス・キーボード共有ソフトウェアのページを参照すること。
エラー時の対処方法
ネットワーク
VM起動時に下記のエラーが出力されて、VMが起動できないことがある。
ERROR Requested operation is not valid: network 'default' is not active
まず、以下のコマンドを実行する。
この時、以下のメッセージが出力された場合は、sudo virsh net-start default
を実行する。
今後、このネットワークを自動起動するには、sudo virsh net-autostart --network default
を実行する。
# 実行 sudo virsh net-list --all # 出力 名前 状態 自動起動 永続 ------------------------------------------------ default 停止状態 いいえ (no) はい (yes)
また、以下のようにネットワークが表示されない場合がある。
Name State Autostart Persistent ----------------------------------------------------------
その時は、/run/libvirt/network/default.xmlファイルを作成して、以下に示す内容を記述する。(デフォルトネットワークを作成する)
# /run/libvirt/network/default.xmlファイル <networkstatus> <class_id bitmap='0-2'/> <floor sum='0'/> <network> <name>default</name> <uuid>e8a9f86b-1c3a-4fa5-ab03-1fb563b12b84</uuid> <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> <bridge name='virbr0' stp='on' delay='0'/> <mac address='52:54:00:a3:0d:b0'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network> </networkstatus>
次に、そのネットワークをKVMホストに永続的に追加するには、以下のコマンドを実行する。
sudo virsh net-define --file default.xml
ファイアーウォール
VM起動時に下記のエラーが出力されて、VMが起動できないことがある。
error: Failed to start network default error: internal error: Failed to initialize a valid firewall backend
この時、ファイアーウォールサービスをインストールする。
sudo zypper install firewalld
サービスを有効にして、ネットワークを再び機能させるために、次のコマンドを実行する。
sudo systemctl enable --now firewalld sudo systemctl restart libvirtd
DNSマスカレード
VM起動時に下記のエラーが出力されて、VMが起動できないことがある。
error: Failed to start network default error: Cannot check dnsmasq binary /usr/sbin/dnsmasq: No such file or directory
この時、DNSマスカレードをインストールする。
sudo zypper install dnsmasq