delete from hateblo.jp where 1=1;

タイトルに意味はありません。

libvirt で GPU の仮想化を有効にしてみる

やりたいこと

libvirt仮想マシンを立てているが、GPU を使いたい

対象

インストール

0. KVM の インストールと設定

既にKVM環境を構築済みの場合はこの手順は不要です。

sudo apt install libvirt-daemon-system qemu-system

リモートからSSHで接続して virt-manager を設定できるようにする。

$ sudo vi /etc/libvirt/libvirtd.conf

# Listen for unencrypted TCP connections on the public TCP/IP port.
# ...
# This is disabled by default, uncomment this to enable it.
listen_tcp = 1

# Override the port for accepting insecure TCP connections
# This can be a port number, or service name
#
# This setting is not required or honoured if using systemd socket
# activation.
#
tcp_port = "16509"

あとは libvirt をリロードするだけ。

$ sudo systemctl reload libvirtd

Windows マシンで、 WSL2 が入っていたら、 virt-manager を使えるので、GUIで簡単に制御できる。

# WSL上で実行してください(debian系)
apt install virt-manager
# SSHキーを転送
ssh-keygen -t rsa -b 4096
ssh-copy-id example-username@example-hostname
# ログインできることを確認
ssh example-username@example-hostname
# virt-manager で接続する
virt-manager -c example-username@example-hostname

virt-manager

virt-managerGUIへ接続する場合は、 Display を VNC server と設定しないと、接続できません。(TLSを設定すればできるのですが、そこまでやっていません)

LINUX Kernel の設定

1. 環境確認

QEMUのバージョン確認(2.12以上)

$ qemu-system-x86_64 --version
QEMU emulator version 7.2.4 (Debian 1:7.2+dfsg-7+deb12u1)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
$  apt info qemu-system
Package: qemu-system
Version: 1:7.2+dfsg-7+deb12u1
Priority: optional
Section: otherosfs
Source: qemu
....

qemu が 2.12以上ならOK(最近のlinux ならほぼクリアしている)。

CPUの状態確認。

$ cat /proc/cpuinfo | grep model
model           : 94
model name      : Intel(R) Core(TM) i3-6100 CPU @ 3.70GHz

Intel 系でかつ、第5世代~第10世代であること。

2. kernel パラメータの調整 (IOMMU を有効化)

i915.enable_gvt=1 intel_iommu=on をパラメータに与える。

$ sudo vi /etc/default/grub
# GRUB_CMDLINE_LINUX=""
GRUB_CMDLINE_LINUX="i915.enable_gvt=1 i915.enable_guc=0 intel_iommu=on"

CPU が第10世代~第11世代の場合は次の資料で設定を確認して、必要に応じてオプションを追加すること。 wiki.archlinux.org

参考: オプションの種類を確認する方法

$ sudo modinfo i915 | grep -P "enable_gvt|enable_guc"
parm:           enable_guc:Enable GuC load for GuC submission and/or HuC load. Required functionality can be selected using bitmask values. (-1=auto [default], 0=disable, 1=GuC submission, 2=HuC load) (int)
parm:           enable_gvt:Enable support for Intel GVT-g graphics virtualization host support(default:false) (bool)

3. kernel モジュールのロード設定

kvmgt, vfio-iommu-type1, mdev を有効にする。

$ sudo vi /etc/modules-load.d/kvmgt.conf
# Load kvmgt, vfio-iommu-type1 and mdev
kvmgt

gvt を使っている時に出てくるエラーを無視する設定を行う。

$sudo vi  /etc/modprobe.d/kvm.conf
options kvm ignore_msrs=Y report_ignored_msrs=N

4. grub へ反映

grub の設定を行う。

※事前に /boot/grub/grub.cfg のバックアップを取得したほうが良いかも

$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.1.0-12-amd64
Found initrd image: /boot/initrd.img-6.1.0-12-amd64
Found linux image: /boot/vmlinuz-6.1.0-10-amd64
Found initrd image: /boot/initrd.img-6.1.0-10-amd64
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done

5. 再起動

再起動して、grub を反映する。

KVM の設定

6. KVM の hook 設定

必要なツールをインストール

# libxml2-utils は xmllint  のため、 uuid-runtime は uuidgen コマンドを使うため
$ apt install libxml2-utils uuid-runtime

libvirtd 用の hook を設定する。

$ sudo vi /etc/libvirt/hooks/qemu
#!/bin/sh

GVT_PCI="0000:00:02.0"
MDEV_TYPE=i915-GVTg_V5_4
GVT_GUID=`cat "/etc/libvirt/qemu/$1.xml" | xmllint --xpath 'string(/domain/devices/hostdev[@type="mdev"][@mode="subsystem"][@display][@model="vfio-pci"]/source/address/@uuid)' -`
# echo "$1 $2 $3 $GVT_GUID" >> /tmp/libvirt_gvthook
if [ $# -ge 3 ] && [ -n "$GVT_GUID" ]; then
#       echo gvt_ok >> /tmp/libvirt_gvthook
        if [ "$2" = "prepare" ] && [ "$3" = "begin" ]; then
                echo "$GVT_GUID" > "/sys/bus/pci/devices/$GVT_PCI/mdev_supported_types/$MDEV_TYPE/create"
        elif [ "$2" = "release" ] && [ "$3" = "end" ]; then
                echo 1 > "/sys/bus/pci/devices/$GVT_PCI/$GVT_GUID/remove"
        fi
fi

参考: 上記コードは以下を参考に作成しました。 wiki.archlinux.org

スティッキービットを設定して、root / root で実行されるようにする

# 念のため権限を設定
$ sudo chown root:root /etc/libvirt/hooks/qemu
# ユーザー・グループの権限で実行されるように設定
$ sudo chmod ug+s /etc/libvirt/hooks/qemu
# その他ユーザーに実行権限を付与
$ sudo chmod o+x /etc/libvirt/hooks/qemu
# 不用意に書き込み権を与えない
$ sudo chmod go-w /etc/libvirt/hooks/qemu
# 権限チェック
$ ls -l /etc/libvirt/hooks/qemu
-rwSr-Sr-x 1 root root 754 Sep 23 18:03 /etc/libvirt/hooks/qemu

VM の設定と起動

7. UEFI 起動を可能にする

ファームを適用する。

$ sudo apt install ovmf
# 設定を更新
$ sudo systemctl reload libvirtd

8. 対象の VM を設定する

次の設定で VM を設定する(必須)。

Archtecture: x86_64
Chipset: Q35
Firmware: UEFI x86_64: /usr/share/OVMF/OVMF_CODE_4M.ms.fd
  <os>
    <type arch="x86_64" machine="pc-q35-7.2">hvm</type>
    <loader readonly="yes" type="pflash">/usr/share/OVMF/OVMF_CODE_4M.ms.fd</loader>
    <nvram>/var/lib/libvirt/qemu/nvram/{VMの名前}_VARS.fd</nvram>
    <boot dev="hd"/>
  </os>

注意: 起動対象の HDD(イメージ) は gpt でセキュアブートに対応していないといけません。 セキュアブートしていない場合は、GPUを一時的に認識しますが、使えない状態になります。(デバイスマネージャで警告状態となります)

9. GPUVM に設定する

virsh で接続して、手動でXMLを追加する。

$ uuidgen
875cd399-1c1b-47f0-8d7b-9f64023c1f56
$ virsh -c qemu:///system edit win10

以下の XML に追加する。

<hostdev mode="subsystem" type="mdev" managed="no" model="vfio-pci" display="off">
  <source>
    <address uuid="{uuidgenで生成した値をここに設定する}"/>
  </source>
  <alias name="hostdev0"/>
  <address type="pci" domain="0x0000" bus="0x00" slot="0x07" function="0x0"/>
</hostdev>

10. 対象のVMを起動する

正常に起動したら、Intel HD Graphics がデバイスドライバから参照できます。 また、タスクマネージャにGPUの項目が出れば、成功です。

なお、GPUメモリの関係で1台しか割り当たらないことがあります。

参考文献