概要
お久しぶりです。えぢぢーんです。
適当な気持ちでandroidアプリを作ろうとしたら、
すごく難しかったので、息抜きでUbuntuをいじってました。
本日やるとことはUbuntuのKVMで仮想環境を作り、そこにIntel GVT-gを使ってiGPU(仮想GPU)を割り当てることです。
ユースケースとしてはどうしても仮想環境にgpuを割り当てたいけど、GPUパススルーは嫌だ(そんな人いる?)そんな人に向けた記事です。
ちょっと説明
おそらくこういうことをやるならほんとはNVIDIAのGPUを仮想化することがゴールになると思いますが、現状NVIDIAのGPU仮想化はサーバー用のGPUに限られており、基本的にはコンシューマ版のGPUの仮想化は対応していません。(なんか有志が作ったパッチを当てると動くとかなんとか)
じゃぁしょうがないからIntel GVT-gを使って仮想上でGPUを有効にするか!ただ3D アクセラレーションとかは有効にできるから3Dゲームとかやれるよ!という記事
環境
- ホストOS : Ubuntu 24.04 LTS Desktop
- ホストCPU : Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
- ゲストOS : Windows 7 Pro
- 仮想環境 : kvm + qemu + virtio
今回はintel GVT-gを使うのでそれに対応したCPU
第6世代以降(Skylake以降)が必要になります
KVMインストール
まずはkvmと必要パッケージをインストール
sudo apt-get install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst libosinfo-bin virt-manager
以下を打つと仮想マシンマネージャが立ち上がる
sudo virt-manager
カーネル設定(IOMMU・GVT有効化)
まずカーネルってなんやってなったんですけど
以下検索AIくんより
Linuxカーネルとは、Linuxオペレーティングシステム(OS)の中核部分で、コンピューターのハードウェアとプロセスの間で通信しながらリソースを管理するソフトウェアです
だそうです。
なんとなくOSの大事な処理をするところだなぁくらいにしか理解してません。
で、今からカーネルをいじるのはIOMMUを有効化するためで
IOMMUはInput-Output Memory Management Unitの略で、メモリを管理する機能です
仮想環境を建てるときはホストと仮想のメモリ領域を完全に分離する必要があります(仮想からの不正アクセスを防ぐため)
この機能にIOMMUが使われていて、更にGPUは物理アドレスを参照する設計になっているのでIOMMUを使わないとそいつらがわからんとなるわけです
(自分の理解なので間違ってたらごめんなさい)
で今回はintelのcpuに内蔵されたgpu仮想化をしたいので
- i915.eneble_gvt=1(intelのgvt機能の有効化)
- i915.enable_guc=0(なんかgvt機能と競合する?)
- intel_iommu=on(intelのiommu機能の有効化)
3つを行う必要がありますんで以下行をgrubの設定ファイルの以下部分を
GRUB_CMDLINE_LINUX=""
こんな感じに追記
GRUB_CMDLINE_LINUX="i915.enable_gvt=1 i915.enable_guc=0 intel_iommu=on"
grubはブート時にカーネルロードとかを担当する機能です
ここに上記コマンドを書いとくと反映されます
もう一個kvmgt, vfio-iommu-type1, mdevを有効にする?
(ここは理解できてないです)
kvmgt
このファイルを作らないとうまく行かなかったので作っときましょ
以上終わったら再起動
update-grub
reboot
再起動完了したらカーネル設定がうまく行ったか以下で確認
dmesg | grep iommu
うまく行ってなかったら
BIOSの設定でVt-dの設定とか見直すと良い
仮想GPUの確保
先程のgrubの設定を確認するために
まずはPCIデバイスを確認する
sudo lspci | grep VGA
VGAがついてるPCIデバイスを確認すると
以下が出てきた(自分の環境では2つ)
00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630]
01:00.0 VGA compatible controller: NVIDIA Corporation TU106 [GeForce RTX 2070] (rev a1)
片方はNVIDIAのGPUなので、今回はIntelの00:02.0が欲しかったID
このIDはこのあとも使うので変数化して
(0000:を頭につけてね)
PCI_ID="0000:00:02.0"
以下で対応するGVTの種類を確かめます
ls /sys/devices/pci0000\:00/$PCI_ID/mdev_supported_types/
なんか出力がでてきたら成功
i915-GVTg_V5_4 i915-GVTg_V5_8
これの内訳は以下のようになっていて
プロファイル | VRAM容量 | 最大解像度 |
---|---|---|
i915-GVTg_V5_1 |
最大512MB | 1920x1200 |
i915-GVTg_V5_2 |
最大256MB | 1920x1200 |
i915-GVTg_V5_4 |
最大128MB | 1920x1200 |
i915-GVTg_V5_8 |
最大64MB | 1024x768 |
数字をが小さければよい性能を引き出せるけど
CPUによってメモリの最大値が決められてるので
並列数は減るらしいのでトレードオフの関係
で、以下を叩くと仮想GPUを確保できる
GVT_ID=$(uuidgen)
GVT_TYPE=i915-GVTg_V5_4
echo $GVT_ID > /sys/devices/pci0000\:00/$PCI_ID/mdev_supported_types/$GVT_TYPE/create
GVT_IDは仮想GPUのuuidを作成していて
このIDを使って仮想マネージャなどに登録する
あとでも使うので以下で確認
echo $GVT_ID
念の為GPUが確保できたかも以下で確認
ls /sys/devices/pci0000\:00/$PCI_ID/
フォルダの中にGVT_IDが名前になったフォルダができていれば問題ない
で、取得したGPUは電源ON/OFFで消えちゃうので
サービス化して自動で取得するようにしたほうが勝手が良い
(QEMUのhook機能を使っても良いです)
自分はわかりやすいのでサービス化する手順をやってます
[Unit]
Description=Create intel vGPU
[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo '<GVT_IDの値>' > /sys/devices/pci0000:00/<PCI_IDの値>/mdev_supported_types/i915-GVTg_V5_4/create"
ExecStop=/bin/sh -c "echo '1' > /sys/devices/pci0000:00/<PCI_IDの値>/<GVT_IDの値>/remove"
RemainAfterExit=yes
[Install]
WantedBy=graphical.target
これを作ってsystem起動しておけば
ubuntuを起動するたび特定のuuidで仮想GPUを確保してくれます
(getvgpu.serviceの名前はなんでもいいです)
sudo systemctl enable getvgpu
これで自動確保まで完了です
うまくサービス化できてるか確認するために
再起動して以下で自動的にvgpuが取られているか確認しましょう
ls /sys/devices/pci0000\:00/<PCI_ID>/
自動でvgpuが生成されていれば成功です
仮想GPUの確保
ここまできたらあと少し
次はKVMで実際に仮想PCを立ち上げますが
virtioという準仮想環境を使います
以下からstable版のvirtio-win ISOをダウンロードします
WindowsのISOは各自調達してください
- virtio-winのISO
- windowsのISO
両方用意できたら新しい仮想マシンから
ISOを選択
メモリ指定(値はご自由に)
ディスク容量(ご自由に)
インストールのカスタマイズをONに!!
ディスクをSATAからSCSIへ変更
先程ダウンロードしたvirtioをCD-ROMとして追加
NICをvirtioへ変更
ディスプレイのリッスンをなしへ変更
OpenGLにチェック
SCSIコントローラを追加
最後に作成した仮想GPUを割り当て
ここでmdevデバイスが見えない場合手順にミスがありますので見返してください
また適用ボタンを押さないと適用されないので
一度見返してみてください
それが終わったらインストール開始
インストール開始するとこのようにディスクが見えません
(ディスクをSCSIに指定したのでドライバがない)
ドライバを当てると見えるようになります
ドライバの読み込みからvirio isoが入ってるドライブを選択して以下のドライバを当ててください
- vioscsi: scsiのvertioドライバ
- NetKVM: networkのvertioドライバ
- Balloon: メモリのvertioドライバ
- qxl: ディスプレイのドライバ <*>
※windows8以上はqxlではなくqxldodを使う
※windows7はqxlを使い一回目インストールをミスするけど2回めで通るので根気よく頑張る
全部ドライバがあたったらインストールして放置
適当に寝て待ちましょう
立ち上がったらデバイスマネージャから謎のディスプレイデバイスが追加されてるはずなのでホスト側で使ってるcpuのドライバ(だいたいIntelのHD Graphics)を入れましょう
windows10用のドライバしかないって?
よくわからないけど皆さんこちらに行きますね(三店方式)
ttps://archive.org/download/inteluhd-win7
無事ドライバがあたったら一度仮想の電源を落とします
グラフィックドライバが2個存在していると
追加した仮想GPUが有効化できないので
いらないグラフィックドライバをぶちのめします
mdev上のxmlから
display="off"
以下へ変更
display="on"
次
ビデオをnoneへ変更
最後
mdev(仮想GPU)の有効化をしたい
qemu(仮想化システム)でcommmadlineによる設定が必要
毎回commandlineを叩くのは面倒なので
xml上でqemuのcommandを直書きしたいが
何故か仮想マシンマネージャからは適用できない・・・・・
さまよっていたら以下の情報を発見
sudo virt-xml <仮想pcの名前> --edit --confirm --qemu-commandline="test"
このコマンドでとりあえず無理やりxmlドメインにqemuコマンドラインのパススルーを書き込むことに成功
(こんなことでええんか?)
そしたらxmlの最後に以下のようなコマンドが追加されていると思うので
<qemu:commandline>
<qemu:arg value="test"/>
</qemu:commandline>
これを消して以下を追加
<qemu:override>
<qemu:device alias="hostdev0">
<qemu:frontend>
<qemu:property name="x-igd-opregion" type="bool" value="true"/>
<qemu:property name="driver" type="string" value="vfio-pci-nohotplug"/>
<qemu:property name="ramfb" type="bool" value="true"/>
</qemu:frontend>
</qemu:device>
</qemu:override>
色々探してみた結果、現在は他のブログで書かれてるようなcommandlineからの入力は廃止されてoverrideの書き方が有効らしい(詳しくはわからない・・・)
これで再度仮想マシンを起動します
割と長い時間この画面になりますが、
待つと立ち上がってくるので立ち上がったら
dxdiagでディスプレイ情報を確認
仮想のwindows7で3Dアクセラレータが使用可能であることを確認しました。
参考にした方々
めちゃくちゃわかりやすくお世話になりました
最小手順でやっている方
詳細に説明してくれている方
おわり
今回は先人の方々の情報を大分参考にしました
本当に文書化してくれる人たちに感謝です
ただ最新のバージョンだとフォルダ構成や使えない構文などもあり、最新版に翻訳したくらいの仕事はできたとおもいます
次こそは開発中androidアプリの話をします!!