【実務・中級編】 PCIパススルー(Intel VT-d / AMD-Vi)とIOMMU(Input-Output Memory Management Unit)の動作 – クラウドインフラと仮想化ネットワーク実践ガイド

仮想化の「聖域」に触れる:PCIパススルーとIOMMUが支える極限のI/Oパフォーマンス

「仮想マシン(VM)なのに、なぜかネットワークレイテンシが物理マシンと変わらない」。そんな魔法のような構成を支えているのが、今回深掘りするPCIパススルーと、その守護神であるIOMMUの世界です。

クラウドのハイパーバイザー上で、単なる「仮想化された仮想NIC」ではなく、物理NICやGPUをゲストOSに直接握らせる。この荒業を安全かつ高速に実現するためのハードウェア支援機能について、現場の泥臭い知見を交えて解説します。

—

なぜ「仮想化の皮」を脱ぐ必要があるのか

通常、VMがネットワーク通信を行う際、パケットは「ゲストOSのドライバ」→「ハイパーバイザー(VMM)」→「物理NIC」という長い旅路を通ります。この間、何度もCPUが割り込み処理に介在し、コンテキストスイッチが発生する。高負荷なWeb APIサーバーや、マイクロ秒を争う金融取引システムにおいて、このオーバーヘッドは致命的です。

そこで登場するのが、物理PCIデバイスをVMへ直接マッピングするPCIパススルーです。しかし、ここで一つ大きな問題が生じます。

制御不能な「DMAの暴走」をどう止めるか

物理デバイスは、CPUを介さずにメモリへ直接書き込む DMA (Direct Memory Access) を多用します。もし、悪意ある(あるいはバグを含んだ)VMが、物理デバイスのDMAを操作して、ハイパーバイザーのメモリ領域を書き換えたらどうなるか。システムは即座にパニック(クラッシュ)します。

この「野放しなDMA」を、仮想メモリ空間と同じように制御し、安全に保護するための境界線が IOMMU (Input-Output Memory Management Unit) です。Intelでは VT-d、AMDでは AMD-Vi と呼ばれる技術ですね。

—

IOMMUの「通信フロー」のリアル

IOMMUの役割は、PCIデバイスが要求する「物理アドレス」を、IOMMUが管理する「IOページテーブル」を使って、VMが許可された物理メモリ領域へ変換(リマップ)することです。

1. Device Request: 物理デバイスが「アドレス 0x1234… にデータを書き込め」と要求。
2. IOMMU Intercept: IOMMUがそのリクエストを横取り。
3. Address Translation: デバイスに割り当てられたIOページテーブルを参照し、「0x1234…」を「VMが所有する安全な物理アドレス」に書き換える。
4. Memory Access: 安全な領域に対してDMA実行。

この仕組みがあるおかげで、VMは「自分は物理デバイスを直接触っている」と信じ込めるし、ホスト側は「VMが他を破壊するのを防げる」わけです。

—

実践:IOMMUを有効化し、デバイスをパススルーする手順

現場でこの設定を行う際は、BIOS/UEFIレベルでの有効化(VT-d 設定)が必須です。その上で、Linuxホスト(KVM/QEMU環境)ではカーネルパラメータに以下の記述を追加します。

1. カーネルパラメータの追加 (/etc/default/grub)

# IOMMUを有効化し、PCIデバイスのグループ化をサポートする
GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on iommu=pt"
  • intel_iommu=on: IOMMU機能を有効化。
  • iommu=pt (Pass-Through): パススルー対象外のデバイスにはIOMMUを使わず、オーバーヘッドを最小化する設定。これがないと、全デバイスのDMAが重くなります。

2. デバイスIDの特定

対象の物理デバイス(例:NIC)のIDを調べます。

# ベンダーIDとデバイスIDを確認する
lspci -nn | grep -i ethernet
# 出力例: 01:00.0 Ethernet controller [0200]: Intel Corporation Ethernet 10G [8086:154c]

この 8086:154c が、VMに渡すべきデバイスIDです。

—

運用上の落とし穴:IOMMUグループの呪い

ここが現場で最もハマるポイントです。PCIデバイスは「IOMMUグループ」という単位でしか分離できません。

もし、物理NICと別の重要なデバイス(USBコントローラーなど)が同じIOMMUグループに属している場合、一方だけをVMにパススルーしようとすると、「IOMMUグループ全体を渡せ」とハイパーバイザーに拒絶されます。

デバッグ用のコマンド

どのデバイスが同じグループにいるかは、以下のスクリプトで可視化できます。

#!/bin/bash
# IOMMUグループごとのデバイス一覧を表示するシェルスクリプト
for d in /sys/kernel/iommu_groups/*/devices/*; do
    n=${d#*/iommu_groups/*}; n=${n%%/*}
    printf 'IOMMU Group %s ' "$n"
    lspci -nns "${d##*/}"
done

もしグループが重なっていたら、PCIeスロットを物理的に差し替えるか、BIOSの設定で「PCIe ACS Override」を有効にするという荒業が必要になることもあります。

—

最後に:クラウドの裏側を理解するということ

Web APIのレスポンスが遅いとき、私たちはついアプリケーションコードやデータベースのクエリに目を向けがちです。しかし、その足元にある仮想化層のネットワーク処理が、IOMMUによって「物理直結」されているのか、それとも「ソフトウェアスイッチを経由したエミュレーション」なのかを知っているだけで、トラブルシューティングの解像度は劇的に変わります。

「見えないもの」を「見えるようにする」。それがクラウドエンジニアの矜持です。もし皆さんの環境で、低レイテンシが求められるワークロードがあるなら、ぜひIOMMUの構成を確認してみてください。そこには、OSの抽象化を超えた、ハードウェア本来の咆哮が聞こえるはずです。

コメント

タイトルとURLをコピーしました