openSUSE Tumbleweed上のKVM仮想マシンでIntel iGPUを共有する(GVT-g)その1

openSUSE Tumbleweed上のKVM仮想マシンでIntel iGPUを共有する(GVT-g)その1

KVMやXenといったLinuxハイバーバイザ上のVMでGPUを使用する場合、GPUパススルーを用いてVM一つにGPUをまるごと渡してしまうのが個人ユースでは一般的です

GPUパススルーを用いた場合、VM一つがGPUを専有してしまうため、使用できるVMの数に制約があったり、そもそもノートPCのように物理的にGPUが増設できない環境が存在したりと制約が多いのが難点でした

これまでも一部のエンタープライズ向けGPUではGPUの共有機能はサポートされていましたが、最近のカーネル(実用レベルになってきたのは4.18ぐらいから)ではIntel GVT-gと呼ばれるIntel iGPUの共有機能が使えるようになってきました。

今回はopenSUSE Tumbleweedを用いてGVT-gによる複数VMでのGPU共有を行ってみます

テスト環境

現時点のカーネル(4.20)ではGVT-gはBroadwell〜KabyLakeまでのGPUしかサポートされていません

カーネル4.21(仮)でCoffeeLakeに対応する予定(Intelがプルリク投げている)です

ということで、SkyLake世代のノートPCでテストしてみました

大須のPCコンフルの初売りで29800円でしたが、SkyLake世代の中古PCも値頃になってきましたね

  • DELL Latitude E5470
    • CPU: Intel Core i5 6200U
    • GPU: Intel UHD Graphics 520
    • Mem: 8GB
    • OS: openSUSE Tumbleweed x86_64
    • qemu: 3.1.0

とりあえずYaSTなりでvirt-manager経由でVMの制御が行えていることを前提とします

initramfsへのモジュール展開

まずはGVT-gを使うために必要なカーネルモジュールの準備をします。

ブート時点で関連モジュールが必要になるため、dracut.confに必要なモジュールを列挙してinitramfsに突っ込んでおきます

1
2
# echo "drivers+=\"kvmgt vfio-iommu-type1 vfio-mdev\"" > /etc/dracut.conf.d/98-gvtg.conf
# mkinitrd

kvmgtとvfio-mdevが今回のキーモジュールです

カーネルパラーメータの設定

YaST > システム > ブートローダーを呼び出し、カーネルパラメータに

1
i915.enable_gvt=1 kvm_ignore_msrs=1 intel_iommu=1

を追加し、GVT-gを有効にします

screenshot

設定後、再起動して

1
2
3
4
5
6
$sudo lspci
00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (rev 08)
00:02.0 VGA compatible controller: Intel Corporation Skylake GT2 [HD Graphics 520] (rev 07)
00:04.0 Signal processing controller: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (rev 08)
00:14.0 USB controller: Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller (rev 21)
〜以下略〜

でGPUのPCIアドレスを確認したら

1
ls /sys/device/[GPUのPCIアドレス]/mdev_supported_types/

で使える共有GPUの一覧が取れたら成功です

1
2
$ ls /sys/devices/pci0000\:00/0000\:00\:02.0/mdev_supported_types/
i915-GVTg_V5_4 i915-GVTg_V5_8

1
cat /sys/device/[GPUのPCIアドレス]/mdev_supported_types/[出てきた共有GPU]/description

で共有GPUの詳細を確認できますので確認しておきます

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /sys/devices/pci0000\:00/0000\:00\:02.0/mdev_supported_types/i915-GVTg_V5_4/description 
low_gm_size: 128MB
high_gm_size: 512MB
fence: 4
resolution: 1920x1200
weight: 4

$ cat /sys/devices/pci0000\:00/0000\:00\:02.0/mdev_supported_types/i915-GVTg_V5_8/description
low_gm_size: 64MB
high_gm_size: 384MB
fence: 4
resolution: 1024x768
weight: 2

fenceとweightに注目してください

  • fence = この環境で使える最大共有GPU枠
  • weight = この共有GPU一つで専有する共有GPU枠

なので、今回の環境では1920x1080、VRAM128MB〜512MBが1枚、もしくは1024x768、VRAM64MB〜384MBが2枚取れることがわかります

共有GPUの確保と開放

共有GPUを確保するためには

1
echo '[任意のUUID]' > /sys/devices/[GPUのPCIアドレス]/mdev_supported_types/[共有GPU]/create

を行います。成功すれば

1
ls /sys/device/[GPUのPCIアドレス]/

でデバイスディレクトリ下に与えたUUIDのディレクトリが登場します。

1
2
3
4
5
6
7
8
9
$ ls -l /sys/devices/pci0000\:00/0000\:00\:02.0/
合計 0
drwxr-xr-x 4 root root 0 1月 23 04:14 ab8c3af8-8366-449d-8489-fe9254e44621 ←こいつ
-r--r--r-- 1 root root 4096 1月 23 04:14 ari_enabled
-r--r--r-- 1 root root 4096 1月 23 04:14 boot_vga
-rw-r--r-- 1 root root 4096 1月 23 04:14 broken_parity_status
-r--r--r-- 1 root root 4096 1月 23 04:14 class
-rw-r--r-- 1 root root 4096 1月 23 04:14 config
〜以下略〜

確保した共有GPUを開放するには

1
echo '1' > /sys/devices/[GPUのPCIアドレス]/[確保の時使ったUUID]/remove

を行います

UUIDはuuidgenなりで適当に決めてください

サービス化

システム起動時に共有GPUを自動で確保できるようにsystemdサービスを作ります

/usr/lib/systemd/systemの下に任意のサービス名でserviceファイルを作ります

今回はgvtgpu.serviceということで

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /usr/lib/systemd/system/gvtgpu.service 

[Unit]
Description=Create Intel GVT-g vGPU

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo 'ab8c3af8-8366-449d-8489-fe9254e44621' > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create"
ExecStop=/bin/sh -c "echo '1' > /sys/devices/pci0000:00/0000:00:02.0/ab8c3af8-8366-449d-8489-fe9254e44621/remove"
RemainAfterExit=yes

[Install]
WantedBy=graphical.target

↑のような感じで作りました

これで

1
sudo systemctl start gvtgpu

で確保され

1
sudo systemctl stop gvtgpu

で開放され

1
sudo systemctl enable gvtgpu

で起動時に自動確保されるようになります

私の場合ですが、

  • UUIDその1でi915-GVTg_V5_4を確保するgvtgpu.service
  • UUIDその1でi915-GVTg_V5_8を確保するgvtgpu2.service
  • UUIDその2でi915-GVTg_V5_8を確保するgvtgpu3.service

の3つを作り、1枚確保の時はgvtgpuを、2枚確保の時はgvtgpu2と3をenableにする。という運用を行っています

とりあえずここまでとし、実際のVMに適用してみる部分はその2にてで

(続く)

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×