DMAとIOMMUの原理 ─ デバイス転送とアドレス保護
デバイスがCPUを介さず直接メモリを読み書きできるのはなぜか。DMAとIOMMUの内部を押さえれば、仮想化のパススルーや「不正なDMAでメモリが壊される」リスクの正体が腑に落ちます。
- 1.DMAはCPUを介さずデバイスが直接メインメモリへ転送する仕組みで、ディスクリプタリングにより複数の転送要求をキューイングし割り込み1回で大量データを処理する。
- 2.IOMMU(Intel VT-d/Arm SMMU)はデバイスが出すIOVAを物理アドレスへページテーブルで変換し、デバイスごとに到達範囲を限定して不正DMAやバグからメモリを保護する。
- 3.DMAリマッピングと割り込みリマッピングにより、ゲストやデバイスを互いに分離しつつ、SR-IOVでデバイスを仮想機能(VF)に分割して低オーバーヘッドのパススルーを実現する。
なぜDMAが要るのか ─ CPUをコピーから解放する
NICが受信したパケットやSSDから読んだブロックを、CPUが1ワードずつレジスタ経由でメモリへ運んでいたら(PIO、プログラムドI/O)、データ量に比例してCPU時間を食い潰します。10GbEで毎秒1GB超を運ぶのに、転送のたびCPUが介在しては話になりません。
そこでDMA(Direct Memory Access)は、デバイス自身がメインメモリへ直接読み書きできるようにします。CPUは「どこへ何バイト転送せよ」とデバイスに指示するだけで、実際のデータ移動はデバイス側のDMAエンジンが担い、完了したら割り込みでCPUへ知らせます。CPUは転送中、別の処理を回せます。
| 観点 | PIO(CPUが運ぶ) | DMA(デバイスが運ぶ) |
|---|---|---|
| データ移動の主体 | CPUコア | デバイスのDMAエンジン |
| CPU占有 | 転送量に比例して占有 | 指示と完了処理のみ |
| 割り込み頻度 | 細かく多発しがち | 転送単位でまとめて1回 |
| 向くケース | 数バイトのレジスタ操作 | 大容量・連続転送 |
ディスクリプタリング ─ 転送要求をキューに積む
高速デバイスでは1回の転送ごとにCPUへ指示を仰いでいては遅延が支配的になります。そこでディスクリプタリング(リングバッファ)を使います。
ディスクリプタとは「転送元/転送先のアドレス・長さ・フラグ」を記述した小さな構造体です。これをメモリ上の環状配列に並べ、ドライバとデバイスが生産者・消費者の関係で共有します。
ディスクリプタリング(受信の例)
+---------+---------+---------+---------+
| desc[0] | desc[1] | desc[2] | desc[3] | ... 環状
+---------+---------+---------+---------+
^tail(デバイスが書き込む先) ^head(ドライバが回収する先)
ドライバ : 空きバッファのアドレスをディスクリプタに書きtailを進める
デバイス : 受信データを該当バッファへDMAし、完了ビットを立てる
完了割り込み: 複数ディスクリプタ分をまとめて1回通知(割り込み合体)
ドライバはバッファのアドレスを並べておくだけ、デバイスは空いているディスクリプタを順に消費してDMAする。両者はリングのインデックス(head/tail)を更新するだけで同期し、転送ごとのCPU介在を排除します。完了通知も1ディスクリプタごとに割り込まず、**割り込み合体(interrupt coalescing)**で束ねることでCPU負荷を下げます。これがNVMeのサブミッション/コンプリーションキューや、NICのRx/Txリングの基本構造です。
DMAエンジンはCPUのMMU(仮想記憶)を通りません。ディスクリプタに書かれたアドレスをそのままメモリへ発行します。つまり保護機構がなければ、デバイス(やそのドライバのバグ、悪意あるファームウェア、Thunderbolt経由で挿された外部機器)は任意の物理アドレスを読み書きできてしまいます。カーネル領域も他プロセスのメモリも素通しです。この「デバイスは物理メモリ全体に手が届く」問題を解くのがIOMMUです。
IOMMU ─ デバイス側のMMU
CPUのコアには仮想アドレスを物理アドレスへ変換するMMUがあります。IOMMU(I/O MMU)は、同じ発想をデバイスからのメモリアクセス経路に置いたものです。IntelではVT-d、ArmではSMMU、AMDではAMD-Viと呼ばれます。
デバイスが発行するアドレスを**IOVA(I/O Virtual Address、デバイス仮想アドレス)**と呼びます。IOMMUはIOVAを受け取り、デバイスごとのページテーブルを引いて物理アドレスへ変換し、その結果でメモリへアクセスします。
DMAアクセスの経路(IOMMUあり)
デバイス --IOVA--> [ IOMMU ] --物理アドレス--> メインメモリ
| デバイスごとのページテーブルで変換
| 権限(R/W)・到達範囲をチェック
+-> 範囲外なら fault を上げて遮断
ここで重要なのは、変換テーブルがデバイス単位(正確にはPCIeのBus/Device/Functionで識別される単位)に分かれている点です。各デバイスには専用のアドレス空間が割り当てられ、テーブルにマッピングされていない物理ページにはそもそも到達できません。これが「分離(isolation)」です。
| 観点 | MMU(CPU側) | IOMMU(デバイス側) |
|---|---|---|
| 変換の主体 | CPUコアのメモリアクセス | デバイスのDMA/割り込み |
| 入力アドレス | プロセスの仮想アドレス | IOVA(デバイス仮想アドレス) |
| 分離の単位 | プロセス(ページテーブル) | デバイス(BDFごとのテーブル) |
| 主目的 | プロセス保護と仮想記憶 | デバイス分離・DMA保護・仮想化 |
DMAリマッピングと割り込みリマッピング
IOMMUが行う変換は大きく2系統あります。
DMAリマッピングは前述のIOVAから物理アドレスへの変換そのものです。これにより3つの効果が同時に得られます。
- 保護: デバイスはマッピングされた範囲しか触れない。ドライバのバグや悪性デバイスによる任意メモリ破壊を封じる。
- 連続化: 物理的に飛び飛びのページ群を、デバイスから見て連続したIOVA空間に見せられる(散在バッファをまとめてDMAできる)。
- アドレス拡張: 32ビットDMAしかできない古いデバイスでも、IOVAをマップし直せば64ビット空間の任意の物理ページへ届かせられる(バウンスバッファ不要化)。
割り込みリマッピングは、デバイスが発行するMSI/MSI-X割り込みを変換テーブル経由でルーティングする仕組みです。割り込みも本質は「特定アドレスへの書き込み」なので、リマッピングがないと偽装した割り込みで他CPUへ不正なベクタを注入できてしまいます。割り込みリマッピングは割り込みエントリを検証・変換し、どのデバイスがどの割り込みを上げてよいかを制限します。仮想化では、これによりゲストへ割り込みを安全に転送できます。
DMAのたびにページテーブルをメモリから歩いて(page walk)いては遅延が増え、せっかくのDMAの利点が削がれます。そこでIOMMUは変換結果を**IOTLB(I/O TLB)にキャッシュします。CPUのTLBと同じ発想です。マッピングを解除(unmap)したら対応するIOTLBエントリを無効化(invalidate)**しなければならず、これを怠ると解放済みページへの古い変換が残り保護が破れます。高頻度のmap/unmapではこの無効化コストが性能のボトルネックになり得ます。
保護モデルとパススルー ─ そしてSR-IOV
IOMMUの使い方には対極的な2つのモードがあります。
保護モード(translate) : IOVA -> ページテーブル -> 物理アドレス(変換・検査あり)
パススルー(passthrough): IOVA = 物理アドレス(変換せず素通し、保護なし)
パススルーは変換オーバーヘッドゼロで最速ですが保護を捨てます。信頼できるデバイスで性能最優先のとき選ばれます。一方、仮想マシンへデバイスを直接渡すデバイスパススルーでは、保護モードのIOMMUが不可欠です。ゲストが見るゲスト物理アドレスを、IOMMUがホスト物理アドレスへ変換することで、ゲストのDMAをそのVMの割り当てメモリ内に閉じ込められるからです。IOMMUなしのパススルーは、ゲストがホスト全体を破壊できることを意味します。
ただしデバイスを丸ごと1台のVMに占有させるのは非効率です。そこでSR-IOV(Single Root I/O Virtualization)が登場します。1つの物理デバイス(PF: 物理機能)を、ハードウェア的に複数の軽量なVF: 仮想機能へ分割し、各VFを独立したPCIeデバイス(独自のBDFを持つ)として個別のVMへパススルーします。
SR-IOV
物理NIC
├─ PF(物理機能) ... ホスト/管理用、VFを設定
├─ VF0 -> VM A へパススルー(独自BDF、独自キュー)
├─ VF1 -> VM B へパススルー
└─ VF2 -> VM C へパススルー
各VFはIOMMUで別テーブルにマップ -> 相互分離 + ホスト分離
各VFは固有のBDFを持つため、IOMMUはVFごとに別の変換テーブルを割り当てられます。結果として、ハイパーバイザのソフトウェア介在(仮想スイッチや準仮想化ドライバ)を経ずにVMが直接ハードウェアキューを叩け、ベアメタルに近い性能とVM間・ホスト間の分離を両立します。これはPCIeのトポロジと識別子の上に成り立つ機能です。
「DMAはCPUを介さずデバイスが物理メモリへ直接転送、ディスクリプタリングで要求をキューイングし割り込み合体で通知」「IOMMU(VT-d/SMMU)はIOVAを物理アドレスへ変換しデバイス単位で分離・保護、IOTLBで変換をキャッシュ」「DMAリマッピング=アドレス変換と保護、割り込みリマッピング=MSIの検証とルーティング」「SR-IOVはPFを複数VFに分割し各VFをIOMMUで分離してパススルー」の4点が核心です。「IOMMUなしのパススルーはゲストがホスト全体を破壊し得る」という保護と性能のトレードオフも頻出です。
まとめ
- DMAはCPUを介さずデバイスが直接メインメモリへ転送する仕組みで、ディスクリプタリングで複数要求をキューに積み、割り込み合体でCPU負荷を抑える。
- DMAは物理アドレスを直接叩くため、保護機構がなければデバイスは任意メモリを破壊できる。これを解くのがIOMMUで、デバイスが出すIOVAをデバイス単位のページテーブルで物理アドレスへ変換し、到達範囲を限定する。
- DMAリマッピングは変換と保護・連続化・アドレス拡張を、割り込みリマッピングはMSIの検証とルーティングを担い、変換結果はIOTLBにキャッシュされる。
- SR-IOVは物理機能(PF)を複数の仮想機能(VF)へ分割し、各VFをIOMMUで分離して低オーバーヘッドのパススルーを実現する。保護モードのIOMMUがあって初めて安全な仮想化が成立する。
同じ「変換と分離」の発想はCPU側のキャッシュとメモリ階層や、デバイス接続を担うPCIeのアーキテクチャ、コヒーレンシを越えてアクセラレータを繋ぐCXLとも地続きです。データがどこを通り、誰の権限で動くかを押さえると、I/Oと仮想化の全体像が見通せます。
CPU/メモリ/ディスク Article
DMAとIOMMUの原理 ─ デバイス転送とアドレス保護を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
DMA
比較で見る軸
難易度: advanced / カテゴリ: CPU/メモリ/ディスク / タグ数: 6
導入後に効く点
IOMMU(Intel VT-d/Arm SMMU)はデバイスが出すIOVAを物理アドレスへページテーブルで変換し、デバイスごとに到達範囲を限定して不正DMAやバグからメモリを保護する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- CPU/メモリ/ディスク
- タグ数
- 6
判断チェックリスト
- 自社の用途が「DMA / IOMMU」に近いか確認する。
- 強みである「DMAはCPUを介さずデバイスが直接メインメモリへ転送する仕組みで、ディスクリプタリングにより複数の転送要求をキューイングし割り込み1回で大量データを処理する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。