KVM: GPU Passthrough (1)

前回に引き続きopenSUSE tumbleweed/cockpitな環境でKVM環境を整えていく。当面の目標はGPU Passthroughを行うことにある。

過去の自分のメモを見るととりあえずよく使うパッケージをインストールしている。既にcockpitでVM作れるのを確認しているのでKVM関連のパッケージはインストール不要かもしれないが一応入れて置く。

# 今回環境では未インストールだった(無くても動いているようだが)
# qemu-kvm libvirt

# 今回環境ではインストール済みだった
# ovmf virt-manager

# PassthroughやKVMには関係ないけど情報取得で使うのでインストールしておく
# sysstat dstat gparted

とりあえず、一通りインストールして進めることにする。virt-managerは何故か再インストールされた。

# zypper update
# zypper dup
# zypper install ovmf virt-manager
# zypper install sysstat dstat gparted
# zypper install qemu-kvm libvirt

次はBoot Loaderを編集する。yastなら[yast]->[System]->[Boot Loader] ->[Kernel Parameters]。yast使わないなら/etc/default/grubを編集後にgrub2-mkconfigで良いはず。ただ、openSUSEはyastにIFが用意されているのでyast経由で設定変更する方が良いだろう。

# diff /etc/default/grub grub_20210214.bkup
11c11
< GRUB_CMDLINE_LINUX_DEFAULT="splash=silent quiet kvm.ignore_msrs=1 intel_iommu=on iommu=pt mitigations=auto"
---
> GRUB_CMDLINE_LINUX_DEFAULT="splash=silent quiet mitigations=auto"
# grub2-mkconfig -o /boot/grub2/grub.cfg

この段階で再起動を行い、変更後のKernel Parameterで起動させる。

Arch Wikiにあるスクリプトを実行してIOMMUの確認をする。

# cat IOMMU_Mapping.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;
IOMMU Group 1 01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GP107 [GeForce GTX 1050 Ti] [10de:1c82] (rev a1)
IOMMU Group 1 01:00.1 Audio device [0403]: NVIDIA Corporation GP107GL High Definition Audio Controller [10de:0fb9] (rev a1)

今回はGPU (GTX 1050 Ti)のPassthroughを行う。Intel CPUなのでBIOS設定を行いinternal GPU (iGPU)を使うように設定している。本番期のryzen threadripperと違ってintel cpuは楽でよい。iGPU有りでメニーコアでって一般には需要無いのでdiscreate(dGPU)が必須なthreadripperの仕様も理解するが。

GTX 1050 Ti はvfio-pciにバインドさせる。vfio-pciが先にロードされてGPUをバインドするように/etc/sysconfig/kernelに設定を記載する。

# echo "INITRD_MODULES=\"pci_stub vfio vfio_iommu_type1 vfio_pci vfio_virqfd kvm kvm_intel\"" >> /etc/sysconfig/kernel

念のためGPU driverをblacklistに入れておく。おそらくこの設定は不要である。私の場合はホストでAMD系のGPU、ゲストでnVidia系のGPUと住み分けているので、nouveauは要らない。

# echo -e "blacklist nouveau" >> /etc/modprobe.d/99-local.conf

vfio-pciでバインドするデバイスを指定する。基本的にはグループ単位でバインドすることになる。今回はGTX 1050 Tiにしているが、USBコントローラなどもPassthrough可能。

# echo 'vfio-pci' > /etc/modules-load.d/vfio-pci.conf
# echo "options vfio-pci ids=10de:1c82,10de:0fb9" >> /etc/modprobe.d/99-local.conf

設定作ったらinitrdを作成して再起動する。

# mkinitrd
# reboot

再起動後はvfioが目的のGPUをバインドできているかを確認する。

# dmesg | grep -i vfio
[    1.967824] VFIO - User Level meta-driver version: 0.3
[    1.975814] vfio-pci 0000:01:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=io+mem:owns=none
[    1.996153] vfio_pci: add [10de:1c82[ffffffff:ffffffff]] class 0x000000/00000000
[    2.016129] vfio_pci: add [10de:0fb9[ffffffff:ffffffff]] class 0x000000/00000000
[    3.165316] vfio-pci 0000:01:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=io+mem:owns=none

次回はGTX 1050 Tiをゲストに渡して動作するかを確認する。例によってWindowsで動くかが心配である。