手当たり次第に書くんだ

飽きっぽいのは本能

Ubuntu 22.04 KVM PCI パススルー – IOMMU / VFIO で GPU と USB コントローラーを割り当てる

Ubuntu 22.04 の KVM / QEMU で PCI パススルーを使う場合、中心になるのは IOMMU、IOMMU グループ、VFIO、libvirt の hostdev です。GPU や USB コントローラーをゲストへ渡す構成は便利ですが、ホストからデバイスを切り離すため、戻れる管理経路を確保してから進めます。

この記事は、Ubuntu 22.04 の既存環境で KVM PCI パススルー設定を読み直すための記事です。新規構築では Ubuntu 26.04 側の記事を優先しつつ、22.04 環境の設定確認や古い構築記録の読み替えに使ってください。

関連する記事
この記事で確認すること
  • PCI パススルーでホストとゲストのどちらがデバイスを持つか
  • IOMMU と IOMMU グループの確認
  • 対象デバイスを vfio-pci に割り当てる流れ
  • libvirt で PCI Host Device として追加する考え方
  • 画面喪失や起動失敗を避けるための注意点
参考
書籍
参考書籍

作って理解する仮想化技術 – ハイパーバイザを実装しながら仕組みを学ぶ

KVM、QEMU、仮想デバイス、I/O 仮想化、ハイパーバイザの仕組みを低レイヤから理解したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

PCI パススルーは、VM に物理デバイスを少し貸す設定ではありません。IOMMU で隔離できるデバイスの所有権を、ホストからゲストへ移す設計として扱います。

PCI パススルーで何をしているのか

KVM の PCI パススルーでは、ホスト OS が通常のドライバで使っている PCI デバイスを切り離し、vfio-pci に束ねてから、QEMU / libvirt 経由でゲスト OS に渡します。

要素役割
IOMMUデバイスの DMA を隔離し、ゲストに渡すデバイスがホストの任意メモリへ触れないようにする
IOMMU グループ安全に分離できる最小単位
VFIO / vfio-pciPCI デバイスをユーザー空間の VM へ渡す Linux 側の仕組み
libvirt / virt-managerVM 定義に PCI Host Device として対象デバイスを追加する管理層

重要なのは、PCI パススルーはデバイス単体を気軽に貸す機能ではなく、IOMMU で隔離できる単位をゲストへ所有させる構成だという点です。

作業前の前提を確認する

まず、CPU と BIOS / UEFI が仮想化支援と IOMMU を有効にできることを確認します。Intel では VT-x / VT-d、AMD では AMD-V / AMD-Vi が関係します。

コマンド
egrep -wo 'vmx|svm' /proc/cpuinfo | sort -u
sudo apt update
sudo apt install -y cpu-checker
kvm-ok

ホストで使っている唯一の GPU をいきなりゲストへ渡すと、ホスト側の画面を失うことがあります。ホスト用 GPU とゲスト用 GPU を分ける、SSH でホストへ戻れるようにする、GRUB 設定を戻せるようにする、という準備を先に行います。

KVM と virt-manager をインストールする

Ubuntu 22.04 に KVM / libvirt / virt-manager をインストールします。

コマンド
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients virtinst virt-manager ovmf
sudo usermod -aG libvirt "$USER"
id "$USER"

libvirt グループ追加の反映には、ログアウトまたは再ログインが必要です。

IOMMU を有効化する

BIOS / UEFI で VT-d または AMD-Vi を有効化したうえで、Linux カーネルの起動パラメータに IOMMU の指定を追加します。既存のパラメータがある場合は消さずに追記します。

Intel CPU の例
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"
AMD CPU の例
GRUB_CMDLINE_LINUX="amd_iommu=on iommu=pt"

変更前にバックアップを取ってから、GRUB を更新して再起動します。

コマンド
sudo cp /etc/default/grub /etc/default/grub.bak.$(date +%Y%m%d%H%M%S)
sudo update-grub
sudo reboot

IOMMU の有効化を確認する

再起動後、カーネルログで IOMMU が有効になっているか確認します。Intel 環境では DMAR、AMD 環境では AMD-Vi が出ることがあります。

コマンド
sudo dmesg | grep -Ei 'DMAR|IOMMU|AMD-Vi'
find /sys/kernel/iommu_groups/ -mindepth 1 -maxdepth 1 -type d | sort -V

IOMMU グループを確認する

対象の GPU や USB コントローラーが、どの IOMMU グループに属しているかを確認します。PCI パススルーでは、この確認が非常に重要です。

コマンド
for group in /sys/kernel/iommu_groups/*; do
  echo "IOMMU group ${group##*/}"
  for device in "$group"/devices/*; do
    lspci -nn -s "${device##*/}"
  done
done

同じ IOMMU グループに複数のデバイスがある場合、そのグループ全体が分離単位になります。GPU 本体と HDMI audio function が同じグループにいる程度なら一緒に渡せますが、ホストで使う SATA、NIC、USB controller などが同じグループに混ざる場合は注意が必要です。

対象デバイスの ID を確認する

パススルーしたいデバイスの vendor ID と device ID を確認します。

コマンド
lspci -nnk

GPU と GPU の audio function を渡す場合、次のような ID を控えます。この例では、10de:1f8210de:10favfio-pci に渡す ID です。

出力例
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU117 [10de:1f82]
01:00.1 Audio device [0403]: NVIDIA Corporation Device [10de:10fa]

vfio-pci に割り当てる

対象デバイスをホスト側の通常ドライバではなく vfio-pci で掴むように設定します。ID は実際の環境に合わせて変更します。

コマンド
sudo tee /etc/modules-load.d/vfio.conf >/dev/null <<'EOF'
vfio
vfio_iommu_type1
vfio_pci
EOF
sudo tee /etc/modprobe.d/vfio.conf >/dev/null <<'EOF'
options vfio-pci ids=10de:1f82,10de:10fa
EOF
sudo update-initramfs -u
sudo reboot

再起動後、対象デバイスの Kernel driver が vfio-pci になっているか確認します。

コマンド
lspci -nnk -s 01:00.0
lspci -nnk -s 01:00.1

VM に PCI デバイスを追加する

virt-manager で対象 VM を開き、詳細画面から Add Hardware を選び、PCI Host Device として対象デバイスを追加します。GPU を渡す場合は、GPU 本体だけでなく、同じカード上の audio function も一緒に渡すことが多いです。

libvirt の XML では、PCI デバイスは hostdev として表現されます。managed='yes' の場合、libvirt がゲスト起動時にホストからデバイスを切り離し、ゲスト停止後に戻す動作を担当します。

XML 例
<hostdev mode='subsystem' type='pci' managed='yes'>
  <source>
    <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
  </source>
</hostdev>

Windows ゲストで確認する

Windows ゲストを起動し、デバイスマネージャーで GPU や USB コントローラーが認識されているか確認します。GPU の場合は、ドライバを入れるまでは基本ディスプレイアダプターとして見えることがあります。

  • デバイスマネージャーで対象デバイスが見えるか
  • ドライバを入れた後にエラーコードが出ていないか
  • GPU 出力に接続したディスプレイへ画面が出るか
  • USB コントローラー配下の機器がゲスト側で認識されるか

よくある失敗ポイント

症状確認すること
IOMMU グループが出ないBIOS / UEFI の VT-d / AMD-Vi、GRUB パラメータ、再起動の有無
vfio-pci で掴めないvendor ID / device ID、initramfs 更新、既存ドライバが先に掴んでいないか
ホスト画面が消えるホストが使用中の GPU を vfio-pci に渡していないか
VM が起動しない同じ IOMMU グループ内の必要デバイスをまとめて渡しているか
ゲスト再起動後に GPU が戻らないGPU の reset 問題、ホスト再起動の必要性、対象 GPU の相性
USB 機器が不安定USB デバイス単体ではなく USB コントローラー単位で渡しているか

まとめ

Ubuntu 22.04 の KVM で PCI パススルーを使う場合、中心になるのは IOMMU、IOMMU グループ、VFIO、libvirt の hostdev です。成功すると Windows ゲストから GPU や USB コントローラーを直接扱えますが、ホストからデバイスを切り離す構成であることを忘れないようにします。

22.04 の既存環境を見直すときは、IOMMU グループ、対象デバイス ID、vfio-pci の割り当て、ホストへ戻る管理経路を分けて確認します。手順通りに進めるだけでなく、失敗時に画面や入力を失わない構成にしてから作業します。

関連する記事
Ubuntu 22.04 KVM PCI パススルー – IOMMU / VFIO で GPU と USB コントローラーを割り当てる

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る