設定 - KVMのGPUパススルー
概要
前提条件
- 2枚以上のグラフィックボード(マザーボード内蔵でも可)が必要である
- 1つはLinuxホストで使用され、もう1つはWindowsを実行している仮想マシン(以降、VMという)で使用される。
- また、VMにIntel統合GPU(Intel UHD等)を使用することはできない。ATI製またはnVidia製のみ使用できる。
- ただし、LinuxホストにIntel統合GPUを使用することはできる。
- CPUの機能において、Intel VT-DまたはAMD-Viをサポートするマザーボードが必要である。
- リストはここにある。BIOS上で有効にする必要がある。
- PCIのルートポートは、VMで使用するGPUと同じIOMMUグループの一部であってはならない。(詳細は後述)
- VMが使用するプライマリディスプレイの空き入力ポートまたはセカンダリディスプレイの空き入力ポートがあること。
KVM / QEMUのインストール
KVM / QEMUおよび依存関係のライブラリをインストールする。
# SUSE sudo zypper innstall libvirt libvirt-client libvirt-daemon virt-manager virt-install virt-viewer qemu qemu-kvm ovmf qemu-ovmf-x86_64 qemu-tools
こちらのWebサイトから、VirtIOドライバをダウンロードする。
IOMMUの有効化
Intel VT-xとAMD-Viは、一般的にIOMMUと呼ばれる。
IOMMUを有効にするには、/etc/default/grubファイル(ブートローダファイル)にあるGRUB_CMDLINE_LINUX_DEFAULTセクションに以下の設定を追記する。
# Intel CPU intel_iommu=on intel_iommu=pt # AMD CPU amd_iommu=on iommu=pt
※調査中
また、調査中ではあるが、vfio-pciをデバイスにバインドするには、
GRUB_CMDLINE_LINUX_DEFAULTにrd.driver.pre=vfio-pciを追記する必要があるかもしれない。
grubを再構築するために、以下のコマンドを実行する。
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 [ 3.697093] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported [ 3.702890] pci 0000:00:00.2: AMD-Vi: Found IOMMU cap 0x40 [ 3.702890] pci 0000:00:00.2: AMD-Vi: Extended features (0x58f77ef22294ade): [ 3.702892] AMD-Vi: Interrupt remapping enabled [ 3.702893] AMD-Vi: Virtual APIC enabled [ 3.702893] AMD-Vi: X2APIC enabled [ 3.702983] AMD-Vi: Lazy IO/TLB flushing enabled
次に、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では機能しないので注意すること。
2つのグラフィックボードがそれぞれ異なる場合(nVidia製とATI製)
/etc/modprobe.d/50-blacklist.confファイルを編集して、以下の内容を追記する。
# LinuxホストにATI製グラフィックボード、VMにnVidia製グラフィックボードを使用する場合 blacklist amdgpu # LinuxホストにnVidia製グラフィックボード、VMにATI製グラフィックボードを使用する場合 blacklist nouveau blacklist nvidia
2つのグラフィックボードが同じ場合(両方ともnVidia製または両方ともATI製)
まず、/etc/modprobe.d/gpu-passthrough.confファイルを作成して、以下のように編集する。
ここで、<VMで使用するGPUのベンダー>と<VMで使用するGPUのモデルID>は、上記セクションで実行したlsIOMMU.shの出力結果に記載されている。
options vfio-pci ids=<VMで使用するGPUのベンダー>,<VMで使用するGPUのモデルID>
例えば、上記セクションの結果から、以下のように記述する。
options vfio-pci ids=1002:683f,1002:aab0
次に、/etc/default/grubファイルのGRUB_CMDLINE_LINUX_DEFAULTセクションに以下を追記する。
rd.driver.pre=vfio-pci
initrdの再構築
必要な全てのモジュールを含めるには、initrdを再構築する必要がある。
/etc/dracut.conf.d/gpu-passthrough.confファイルを作成して、以下のように編集する。
(先頭と末尾にスペースが必要なので注意すること)
add_drivers+=" pci_stub vfio vfio_iommu_type1 vfio_pci vfio_virqfd kvm kvm_intel "
initrdを再構築するために、以下のコマンドを実行する。
dracut -f /boot/initrd $(uname -r)
initrdの再構築の完了後、Linuxホストを再起動する。
設定ミスで失敗すると、Linuxホストが起動できなくなる可能性があるので注意すること。
GPUが分離されていることを確認
GPUが分離されているか確認する。
以下のコマンドを実行して、使用中のカーネルドライバーを探す。
lspci -k
分離するGPU(VMで使用するGPU)を探す。vfio-pciと記載されている。
02:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] Subsystem: PC Partner Limited / Sapphire Technology Device a001 Kernel driver in use: vfio-pci Kernel modules: radeon 02:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] Subsystem: PC Partner Limited / Sapphire Technology Device aab0 Kernel driver in use: vfio-pci Kernel modules: snd_hda_intel
ゲストOSの作成
- まず、/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
- Virtual Machine Managerを起動して、新しいVMを作成する。
Architecture Optionには、Local Install Mediaとx86_64を選択する。 - Use ISO Imegeを選択して、WindowsのISOファイルを選択する。
- VMに割り当てるメモリとCPUコアの数を選択します。
- VMのディスクイメージを作成する。(既にに定義されている場合は選択する。また、ディスク全体でも構わない。パスをそこに配置して、ホストにマウントされていないことを確認する)
- VMに名前を付けて、Customize configuration before installがチェックされていることを確認して、Finishボタンを押下する。
- VM構成画面(以降、メイン画面とする)に移動する。画面左の[Overview]で、UEFIファームウェアとi440FXチップセットを選択する。
- メイン画面左の[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を選択する。
- メイン画面左の[PCI Host Device]を選択して、分離されたGPUを追加する。
サウンドデバイスがあり、ディスプレイに(HDMIまたはディスプレイポート経由で)サウンド出力がある場合は、サウンドカード(ここでは、PCIデバイス02:00.1)も追加する。 - メイン画面左の[USB Host Device]を選択して、キーボードとマウスを追加する。追加のペアがある場合は、VMが起動すると入力が取得されるため、より適切である。
- 同様に、不要なデバイス(タブレット、ディスプレイスパイス、コンソール、チャンネルスパイス、ビデオQXL等)を全て削除する。
ディスプレイにサウンド出力がない場合またはVGA経由で接続する場合は、サウンドカードが必要である。
1000円程度の安価なUSBサウンドカードを購入してPCに取り付けた場合、キーボードとマウスを追加したように追加する。 - VMに割り当てたばかりのグラフィックボードをディスプレイに接続し、[Begin Installation]ボタンを押下する。
全て正しく設定されていれば、そのディスプレイにVMが起動していることがわかる。 - Windowsをインストールする。
上記(2)でダウンロードしたVirtIOドライバーが必要である。(vioscsiディレクトリの下に存在する) - Windowsのインストール完了後、Synergy(有償ソフトウェア)をインストールできる。
これは、物理的なKVM(Keyboard-Video-Mouse)スイッチなしで、複数のPCで同じキーボードとマウスを使用できる。