QEMU 上の Windows で DirectX を使うゲームなどを起動すると DirectX の初期化に失敗しましたと表示されて起動できない。 DirectX を使うためには、以下2つがある。
- Virtio を使って DirectX を動かす (Virtio ドライバは Fedora から署名付きで公開されている)
- Intel 内蔵 GPU を QEMU で使うようにして Windows に Intel グラフィックドライバをインストールする
今回は、後者を実施したためメモする。
問題
dxdiag を起動してディスプレイタブを見ると、DirectX がすべて「利用できません」になっていた。 デバイスマネージャで確認すると、ディスプレイドライバが、標準VGAディスプレイドライバになっている。 GPU-Z を起動して GPU を見ると、GPU の情報が何も表示されない。
環境
項目 | 内容 |
---|---|
CPU | Intel Core i5-8400 |
GPU1 | Intel Core i5-8400 内蔵 |
GPU2 | Nvidia GeForce GTX 960 |
マザーボード | MSI Z370 GAMING PLUS |
ブートローダ | GRUB |
ホストOS | Arch Linux |
ゲストOS | Windows 7 (32bit版) |
注:32ビット版は、Intel ドライバがインストールできないため64bit版を使う必要がある
Intel 内蔵 GPU を QEMU と共用する
ここでは、以下の作業を行った。
- Nvidia GPU だけを使用していたので、Intel 内蔵 GPU も併用するようにした (指定したときだけ Nvidia GPU が使われる)
- Intel 内蔵 GPU の仮想 GPU を作成し、QEMU から GPU が共用できるようにした
Intel 内蔵 GPU をメインで使用する
当初、GPU としては Nvidia の外付け GPU しか使用していなかった。
$ lspci | grep VGA 02:00.0 VGA compatible controller: NVIDIA Corporation GM206 [GeForce GTX 960] (rev a1) $ xrandr --listproviders Providers: number : 1 Provider 0: id: 0x1b7 cap: 0x1, Source Output crtcs: 4 outputs: 9 associated providers: 0 name:NVIDIA-0
BIOS の設定にて、使用する GPU を PEG (PCI接続GPU) から IGD (CPU内蔵GPU) に変更した。 マザーボード上の Intel GPU に変えたため、ディスプレイケーブルを Nvidia GPU の端子からマザーボードの端子に挿し直さなければならない。
すると Intel 内蔵 GPU と Nvidia GPU が両方とも認識された。
$ spci | grep VGA 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] 02:00.0 VGA compatible controller: NVIDIA Corporation GM206 [GeForce GTX 960] (rev a1)
Intel 内蔵 GPU と Nvidia GPU を併用する
両方とも認識した状態であれば、必要なときに指定することで Nvidia GPU を適用してプログラムを動作させることができるようになる (NVIDIA Optimus)。
ただし、NVIDIA が提供するクローズドソースのドライバではなく、Nouveauドライバを使用する必要がある。そのため、クローズドソースドライバを削除した。
# pacman -Rs nvidia nvidia-utils lib32-nvidia-utils
Nouveau ドライバは、Intel 内蔵 GPU を使用するため、mesa をインストール済み。
カーネルモジュールとして nvidia を追加している場合は削除する必要がある。
/etc/mkinitcpio.conf MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm kvmgt) を MODULES=(kvmgt)
カーネルイメージを再生して再起動した。
# mkinitcpio -p linux # reboot
/usr/lib/modprobe.d/nvidia-utils.conf に blacklist Nouveau
が書いてあったけど、nvidia ドライバのアンインストール時に自動的に削除されていた。
xrandr --listproviders の出力が modesetting (Intel) と nouveau (Nvidia) になった。
$ xrandr --listproviders Providers: number : 2 Provider 0: id: 0x46 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 5 associated providers: 1 name:modesetting Provider 1: id: 0xaf cap: 0x7, Source Output, Sink Output, Source Offload crtcs: 4 outputs: 5 associated providers: 1 name:nouveau
環境変数 DRI_PRIME=1 をセットしたときだけ Nvidia のGPUを使うことができるようになる。 (指定しないと常に Intel 内蔵 GPU が使われる。)
$ glxinfo | grep "OpenGL renderer" OpenGL renderer string: Mesa Intel(R) UHD Graphics 630 (CFL GT2) $ DRI_PRIME=1 glxinfo | grep "OpenGL renderer" OpenGL renderer string: NV126
NV126 は Nouveau のコードネーム。
Intel 内蔵 GPU を QEMU で共用する
Intel 内蔵 GPU は、Intel GVT-g によって仮想マシンに仮想GPUを見せることで内蔵 GPU を共用する。
カーネルパラメータに i915.enabel_gvt=1 i915.enable_guc=0 gvt=1 intel_iommu=on を追加する。
/etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT="その他の設定 i915.enable_guc=0 i915.enable_gvt=1 intel_iommu=on"
# grub-mkconfig -o /boot/grub/grub.cfg # reboot
$ lspci | grep VGA 00:02.0 VGA compatible controller: Intel Corporation CoffeeLake-S GT2 [UHD Graphics 630] 02:00.0 VGA compatible controller: NVIDIA Corporation GM206 [GeForce GTX 960] (rev a1)
ここでは、0000:00:02.0 がアドレスになる。
作成できる仮想 GPU (vGPU) のタイプを確認する。
# GVT_PCI=0000\:00\:02.0 # ls /sys/bus/pci/devices/$GVT_PCI/mdev_supported_types/ i915-GVTg_V5_4 i915-GVTg_V5_8
各タイプの意味は description の中に書かれている。
# sudo cat /sys/bus/pci/devices/$GVT_PCI/mdev_supported_types/i915-GVTg_V5_4/description low_gm_size: 128MB high_gm_size: 512MB fence: 4 resolution: 1920x1200 weight: 4
vGUI の GUID を uuidgen コマンドで生成し、環境変数 GVT_GUID にセットする。vGPU のタイプも GVT_TYPE にセットしておく。
GVT_PCI=0000\:00\:02.0 GVT_GUID=$(uuidgen) GVT_TYPE=i915-GVTg_V5_4
vGPU を作成する。ただ、この操作は sudo ではできず、su で root にならないとパーミッションがないと言われた。
# echo "$GVT_GUID" > "/sys/bus/pci/devices/$GVT_PCI/mdev_supported_types/$GVT_TYPE/create"
後述のオプションをつけて qemu を起動すると、 failed to open /dev/vfio/11: Permission denied
と言われたので、読み書き可能にした。
# chmod 666 /dev/vfio/11
-device vfio-pci,sysfsdev=/sys/bus/pci/devices/0000:00:02.0/17562a86-9d15-4a38-9217-a1c66809eb8d,rombar=0
をつけて qemu を起動した。環境変数は毎回セットするのが面倒なので、絶対パスにした。
$ qemu-system-x86_64 -enable-kvm -m 3G -net nic -net user -drive file=/mnt/QEMU/Win7,format=raw,index=0,media=disk -cpu host,hv-time,hv-relaxed,hv-vapic,hv-spinlocks=0x1fff,hv-runtime -machine accel=kvm -device vfio-pci,sysfsdev=/sys/bus/pci/devices/0000:00:02.0/17562a86-9d15-4a38-9217-a1c66809eb8d,rombar=0 -display sdl,gl=on
QEMU 上で GPU-Z を起動すると、無事に Intel 内蔵 GPU が読み込まれていることを確認できた。(32ビットOSだったので、Intel グラフィックドライバはインストールできなかった…。)
付録 (Vertio で対処する)
当初、Vertio で Direct Xを動かそうとしていた。 しかし、Fedora のドライバでは、今日時点ではすでに Windows 8 以降でないとインストールできない。 そのため、Windows 7 での Virtio の適用はやめ、GTX-d 共用を実施することとした。