概要
KVM で PCI passthrough をするために必要な host 側の設定について説明する。要点は次の2つ:
- IOMMU を有効化し、PCI device からホストへの Direct Memory Access を VM 上のメモリアクセスにマップできるようにする
- 仮想ドライバ VFIO を有効化し、ホスト上の PCI device driver ではなく、ゲスト上の PCI device driver にマップできるようにする
- 図左:設定前。デフォルト、PCI Device がホスト側 driver にバインドされた状態
- 図右:設定後。IOMMU および VFIO の設定が完了した状態
本記事では、ホスト OS を Rocky Linux 9.4 を使用する。対象の PCI デバイス Intel Iris Xe (GPU) を例として説明する。
本記事の例では、host GPU の PCI Passthrough 設定を行う。この場合、ホスト側から GPU へのアクセスが遮断されるため、設定が成功するとディスプレイに何も映らなくなる可能性がある。したがって、事前にホストにリモートログインできるようにしておき、別マシンから SSH 経由で設定を行うようにする。
PCI Passthrough の有効化
Prerequisites
ホスト側に次のソフトウェアをインストールしておく:
# sudo dnf install pciutils driverctl
-
pciutils
... PCI 情報の閲覧のため -
driverctl
... VFIO に関する設定のため
IOMMU の有効化
Intel VT-d (IOMMU) を有効化する:
# grubby --args="intel_iommu=on iommu_pt" --update-kernel DEFAULT
Kernel Option に intel_iommu=on
および iommu_pt
が追加されたことを確認する:
# grubby --info=DEFAULT | grep iommu
ホストを再起動して設定を反映する:
# reboot
VFIO の有効化
PCI Device の情報から PCI device address (ex: 0000:00:02.0
) を確認する:
# lspci -Dnnk | grep -A 4 -E "Iris"
0000:00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [Iris Xe Graphics] [8086:a7a0] (rev 04)
DeviceName: Onboard - Video
Subsystem: Intel Corporation Device [8086:3037]
Kernel driver in use: i915
Kernel modules: i915
Intel Iris Xe 0000:00:02.0
にバインドされるドライバが i915
(Interl GUI Driver) ではなく vfio-pci
になるよう設定する:
# driverctl set-override 0000:00:02.0 vfio-pci
再度 PCI Device の情報を確認し、kernel driver in use
key の値が vfio-pci
になっていることを確認する:
# lspci -Dnnk | grep -A 4 -E "Iris"
0000:00:02.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [Iris Xe Graphics] [8086:a7a0] (rev 04)
DeviceName: Onboard - Video
Subsystem: Intel Corporation Device [8086:3037]
Kernel driver in use: vfio-pci
Kernel modules: i915
仮想マシンに VFIO デバイスを割り当てる
PCIe デバイスを passthrough する場合、qemu machine type は q35
である必要がある。
PCI device 情報の xml を記述し、ドメインに割り当てる。<address>
タグの各属性は PCI device address の形式 <domain>:<bus>:<slot>.<function>
から読み取る。例えば、さきほど lspci
コマンドで確認した PCI address 0000:00:02.0
の場合は次のようになる:
virsh attach-device <domain> --persistent /dev/stdin <<EOF
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</source>
</hostdev>
EOF
Guest 側から PCI デバイスを確認する
Guest にログインし、Guest 側にも pciutils
をインストール:
# sudo dnf install pciutils
Guest 側から PCI device が認識されていることを確認する:
# lspci -Dnnk | grep -A 4 -E "Iris"
0000:09:00.0 VGA compatible controller [0300]: Intel Corporation Raptor Lake-P [Iris Xe Graphics] [8086:a7a0] (rev 04)
Subsystem: Intel Corporation Device [8086:3037]
Kernel driver in use: i915
Kernel modules: i915
もとの設定の復元
上記の設定を完了すると、ホストから PCI device を利用することはできなくなる。もとに戻したい場合、以下の手順を実行する。
Kernel option を削除する:
# grubby --remove-args="intel_iommu=on iommu_pt --update-kernel DEFAULT
本記事で設定した kernel options intel_iommu=on
, iommu_pt
, pci-stub.ids
が削除されていることを確認する:
# grubby --info=DEFAULT
再起動して設定を反映する:
# reboot
デフォルトのドライバを元に戻す (例: i915
) :
# driverctl set-override 0000:00:02.0 i915
Trouboleshooting
今回の例では Intel Iris Xe の PCI Passthrough を試みたが、GPU 特有の問題に当たったので Trouble shooting を残す。
PCI デバイスの割り当て後、マシンを起動するとすぐにエラーで落ちる
virsh start <domain>
実行後、すぐに起動に失敗する場合は、OOM (Out Of Memory) Killer によって VM が kill されている可能性がある。これを確認するには、失敗した直後、ホスト上で dmesg
を実行し出力を確認する:
# dmesg
...
[ 3443.989849] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=system.slice,mems_allowed=0,global_oom,task_memcg=/machine.slice/machine-qemu\x2d9\x2dmaster0.scope/libvirt,task=qemu-kvm,pid=3563,uid=107
[ 3443.989880] Out of memory: Killed process 3563 (qemu-kvm) total-vm:34551624kB, anon-rss:31759628kB, file-rss:0kB, shmem-rss:0kB, UID:107 pgtables:62552kB oom_score_adj:0
解決策:メモリ不足の解消
上記はメモリ不足が原因なので、VM のメモリを減らすなどして対策する。
参考:Intel GVT-g: QEMU unexpectedly closed the monitor : r/VFIO
Links
手順に関する参考資料
IOMMU, VFIO のアーキテクチャ関連の参考資料