KVM環境でIntel iGPUグラフィックを仮想マシンにパススルー(というか共有)する
表題の通り。今回はIntel GVT-g、いわゆるvGPUな仕組みを使う。
vGPUとは、GPUを仮想化し、複数のゲスト インスタンスから一つの物理GPUを共用できるようにする仕組み。つまり複数のゲストOSにGPUを提供できる。
物理端子は一つしかないので、ゲストOSからの映像出力はサポートしないが、ゲストOSでGPUが使えるとリモデとかが軽くなるし、たぶんQSVとかも動くはず。(この機能、ESXi向けにも提供してほしい)
ついでに言うと、ホスト向けのGPU出力を殺さずので、普段の鯖管理で画面が出てねぇ!みたいな事態を避けられる。
ホストOSとして使ったのは Rocky Linux 9.0 + Cockpit(管理ツール)。
KVM自体の設定はこのあたりを参考に済ませる。ついでにゲストOSも作成しておく。
- QEMU、KVM、libvirtの基礎知識まとめ - えんでぃの技術ブログ (hatenablog.jp)
- KVMの初期設定、及びvirsh, virt-installによるVM作成 - えんでぃの技術ブログ (hatenablog.jp)
- Cockpit GUI によるKVM操作 - えんでぃの技術ブログ (hatenablog.jp)
大まかな手順は以下。事前にVT-x/VT-dをBIOS上で有効化しておくこと。
- Rocky Linux 8 : KVM : GPU パススルー : Server World (server-world.info) (IOMMUの付近)
- Tutorial: Passing an Intel GPU to a Linux/KVM Virtual Machine – Interesting things (tmm.cx) (仮想マシンの構成xml以外のところ)
RHEL系だけど、KVMの設定さえしてしまえば、ディストリビューション間でやる事は大差なさそう。(どちらかというと Cockpit で作成した仮想マシンに若干癖あり、他のマネージャー使った場合と勝手が違うかもしれない。)
- 上記の手順では、ゲスト構成で既存の仮想GPUを完全に置換しているが、そちらは残しつつ追記。(WebConsoleから見えなくなるのはつらい)
- パススルーして見せる先のPCIのバス位置は既存と被るので適当に変更。
手元の環境では、仮想マシンの構成XMLは /etc/libvirt/qemu に存在した。
<graphics type='egl-headless'>
<gl rendernode='/dev/dri/by-path/pci-0000:00:02.0-render'/>
</graphics>
<hostdev mode='subsystem' type='mdev' managed='no' model='vfio-pci' display='on'>
<source>
<address uuid='a0d7bae4-45bf-47c2-a13b-9a6fa4dd08d0'/>
</source>
<address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
</hostdev>
xml編集後はきちんと反映する。
# virsh define Windows10.xml
複数ゲストにiGPUを共有したい場合、サービスを複数個作成する、またはサービス内でcreateを複数叩くなりするとよい。以下サンプル。
[Unit]
Description=Setup GVT[Service]
Type=oneshot
ExecStartPre=/usr/bin/bash -c 'echo a0d7bae4-45bf-47c2-a13b-9a6fa4dd08d0 > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_8/create'
ExecStart=/usr/bin/bash -c 'echo 58e3b221-8a07-4e02-bad5-b70404769969 > /sys/devices/pci0000:00/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_8/create'[Install]
WantedBy=multi-user.target
あとCockpitのWeb管理画面から作ったVMにPCIパススルーを設定すると、仮想ディスク イメージのバージョンが古いって怒られた気がする。ディスクイメージを変換するだけで、もし起動時に怒られたときはコマンド叩いて適当に変換する。
ゲストOS向けに、Intel HD Graphics ドライバを入手してインストール。
導入するドライバはホストと同じものでOK。
例えばSkylake世代のWindows 10向けの場合は以下が適合する。
もし準仮想化ドライバが未導入の場合、ついでに入れておく。
【画面が真っ暗になった場合】
Intel HD Graphics が有効化されると、その時点でプライマリ ディスプレイが Intel HD Graphics に取られてしまい、Web コンソールが見えなくなることがある。
画面出力は必要ないので、スタートアップにショートカットなどを仕込んで、ディスプレイを切り替えるようにすることで回避可能。
- スタートアップ ディレクトリは「shell:start menu」→プログラム→スタートアップ の辺りにある。
- ディスプレイの切り替えには「DisplaySwitch.exe /internal」(1台目のみ)、「DisplaySwitch.exe /external」(2台目のみ)、「DisplaySwitch.exe /clone」(1台目と2台目の両方に複製出力 ※GPUを跨ぐ為、対応GPUかつWin10限定) などが標準コマンドで使える。(Win8.1で確認済)
- 仕込みの際はセーフモードに切り替える必要あり。
セーフモードの起動には「詳細な起動オプション」を呼び出す必要がある。事前に「bcdedit /set {default} advancedoptions yes」などでオプションを有効にすることで呼び出し可能。 - 何をするにしてもコマンドが叩けなくて詰む場合、一度iGPUのパススルーを無効にして作業すべし。とりあえずセーフモードが有効にできれば何とかなる。
- 色々仕込んだ後、ログイン操作も困難になると思うので、「DevicePasswordLessBuildVersion」とか「netplwiz」でググって自動ログインを仕込んでおくとよい。
- ログイン後に何が起きてるのか知りたい場合、リモート デスクトップを仕込んでおくと良いかもしれない。
一通りの設定が終わったら、仮想マシンからGPUが見えるようになるはず。
ちなみに、この状態だとOSからGPU自体は見えるが、物理端子へゲストOSの映像は出力されず、ホストのコンソールがそのまま出力される。
(物理端子も込みでゲストにGPUを見せたい場合は完全にPCIパススルーをする必要があるが、手元の環境では映像出力に一度も成功していない‥)
【追記 - 2022/11/20】
その後もProxmox VE 6.2 等と比較しながら試用してみたけど、どうにもGPUパススルーすると安定せず。残念ながらKVM自体の使用を断念し、ESXiに切り替えましたとさ。