https://naba-san.hatenablog.com/


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も作成しておく。

 

大まかな手順は以下。事前にVT-x/VT-dをBIOS上で有効化しておくこと。

RHEL系だけど、KVMの設定さえしてしまえば、ディストリビューション間でやる事は大差なさそう。(どちらかというと Cockpit で作成した仮想マシンに若干癖あり、他のマネージャー使った場合と勝手が違うかもしれない。)

 

仮想マシンの構成XMLは、手順に沿わず以下の通り設定した。

  • 上記の手順では、ゲスト構成で既存の仮想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管理画面から作ったVMPCIパススルーを設定すると、仮想ディスク  イメージのバージョンが古いって怒られた気がする。ディスクイメージを変換するだけで、もし起動時に怒られたときはコマンド叩いて適当に変換する。

 

ゲスト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が見えるようになるはず。

KVMゲスト上にiGPUを共有する様子

ちなみに、この状態だとOSからGPU自体は見えるが、物理端子へゲストOSの映像は出力されず、ホストのコンソールがそのまま出力される。
(物理端子も込みでゲストにGPUを見せたい場合は完全にPCIパススルーをする必要があるが、手元の環境では映像出力に一度も成功していない‥)

 

【追記 - 2022/11/20】

その後もProxmox VE 6.2 等と比較しながら試用してみたけど、どうにもGPUパススルーすると安定せず。残念ながらKVM自体の使用を断念し、ESXiに切り替えましたとさ。