TL

ハードウェア仮想化拡張の内部(VT-x/AMD-V)

ゲストを無改変・高速に走らせる仕組みを、CPUの動作モードから解き明かします。VMX root/non-rootとVMCS、VM exitの遷移、EPT/NPTの二段変換まで原理で押さえ、仮想化の性能勘所を掴めます。

応用仮想化VT-xAMD-VVMCSEPT最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.VT-x/AMD-VはCPUにVMX root(ハイパーバイザ)とnon-root(ゲスト)の二つの動作モードを追加し、ゲストは特権命令を含めてそのまま走り、介入が要る事象でだけVM exitする。
  • 2.ゲストとホストの状態はVMCS/VMCBという制御構造に保存され、VM entry/VM exitはこの構造をハードウェアが一括退避・復元することで成立する。
  • 3.EPT/NPTはゲスト物理→ホスト物理の二段目をハードウェアで変換し、シャドウページテーブルの維持コストとVM exitを激減させる。

なぜ専用の動作モードが要るのか

OS仮想化技術の系統で触れたとおり、x86 は素朴な trap-and-emulate では仮想化できませんでした。POPF のように、ユーザーモードで実行しても トラップせず黙って別挙動になる sensitive 命令があり、ハイパーバイザが介入点を捕まえられないからです。バイナリ変換や準仮想化はこれを迂回する手段でしたが、変換コストやゲスト改変という代償を伴いました。

2005年前後の Intel VT-x と AMD AMD-V は、この問題を CPU の動作モードそのものを増やすことで解きました。従来のカーネルモードとユーザーモード(リング0〜3)はそのまま残し、それと 直交する新しい軸 を追加したのが核心です。

従来の特権軸(リング)はそのまま:
  ring0(カーネル) … ring3(ユーザー)

VT-x が追加した直交軸:
  VMX root モード     … ハイパーバイザが動く(ring0〜3を内包)
  VMX non-root モード … ゲストが動く(ring0〜3を内包)

ゲストは non-root モードの ring0 で 自分が物理 CPU を握っていると信じたまま カーネルを動かします。特権命令も基本はそのまま実行され、ハイパーバイザの介入が必要な事象が起きたときだけ root モードへ落ちる。この「落ちる」遷移が VM exit です。

root/non-rootとリングは別の軸

VMX root/non-root はリング保護とは独立した軸です。ゲストは non-root の ring0 でカーネルを、ring3 でアプリを動かせます。つまり「ゲストカーネルは ring0 のまま」で、特権降格(リング圧縮)に頼っていた旧来方式と違い、ゲスト OS の前提を崩しません。

VMCS/VMCB:モード境界をまたぐ状態の器

二つのモードを行き来するには、切り替えのたびに CPU の状態(レジスタ、制御レジスタ、セグメント、割り込み状態など)をまるごと退避・復元する必要があります。それを担う制御構造が VMCS(Intel: Virtual Machine Control Structure)、AMD では VMCB(Virtual Machine Control Block) です。物理メモリ上の1ページ程度の領域で、論理 CPU ごとに割り当てます。

VMCS は概念的に次の領域を持ちます。

VMCS(概念構成)
 ├─ Guest-state    : VM entry でロードされ、VM exit で保存されるゲストの状態
 ├─ Host-state     : VM exit でロードされるハイパーバイザの状態
 ├─ VM-execution   : non-root 中に何を VM exit させるかの制御ビット群
 ├─ VM-exit/entry  : 出入りの挙動制御(自動退避するMSRリスト等)
 └─ VM-exit info   : なぜ exit したか(理由コード+付随情報)

ハイパーバイザは VMCS を直接メモリ読み書きするのではなく、専用命令 VMREADVMWRITE でフィールドにアクセスします(CPU が内部最適化された形式で持つため)。VM-execution 制御こそが性能の要で、たとえば「HLT で exit するか」「外部割り込みで exit するか」「特定の MSR や I/O ポートへのアクセスで exit するか」をビット単位で指定できます。何を exit させるかを絞ること が、そのままオーバーヘッド削減になります。

VM entry/VM exit の遷移

ハイパーバイザがゲストを走らせるループは、原理的にはこうです。

ハイパーバイザ(root モード):
  VMWRITE で VMCS を構成
loop:
  VMLAUNCH(初回)/ VMRESUME(2回目以降)   ← VM entry
      → CPU が Guest-state をロードし non-root へ
      → ゲストが走る(特権命令もそのまま実行)
      → 介入が要る事象が発生
  ── VM exit ──                              ← root へ復帰
      → CPU が Guest-state を VMCS に保存し Host-state をロード
      → ハイパーバイザが exit reason を VMREAD で読む
      → 理由に応じてエミュレート/反映
  goto loop

VM entry は VMLAUNCH(初回)と VMRESUME(継続)で起こし、CPU が Guest-state を一括ロードして non-root へ移ります。逆に VM exit では、CPU が現在のゲスト状態を VMCS に保存し、Host-state を復元して root へ戻します。この退避・復元をハードウェアが一括で行う 点が、ソフトウェアで状態を保存していた旧来方式との決定的な差です。

VM exit を起こした理由は exit reason として VMCS に記録され、ハイパーバイザはそれを読んで分岐します。理由には大きく、ゲストの操作起因(CPUID、特権命令、I/O、EPT 違反など)と、外部要因(外部割り込み、HLT、プリエンプションタイマ満了など)があります。

VM exitは安価ではない

VM entry/exit は1回あたり数百〜千サイクル規模のコストを伴い、TLB やパイプラインへの副作用もあります。仮想化の性能問題の大半は「VM exit が多すぎる」ことに起因します。設計の主眼は機能の有無より、いかに exit を減らすか にあります。

トラップとエミュレートの最適化

VT-x で trap-and-emulate は CPU が支援するようになりましたが、exit が高コストである以上、頻発する操作を exit させずに済ませる 工夫が積み重ねられてきました。代表的な軸を整理します。

最適化狙い効果
VM-execution制御の絞り込み本当に介入が要る事象だけ exit させる不要な exit を根元から消す
EPT/NPT(後述)ゲストのページ操作で exit させないメモリ起因の exit を激減
APICv / AVIC割り込み配送・EOIをHWで仮想化割り込みごとの exit を回避
posted-interrupt他コアからの割り込みを exit なしで注入I/O割り込みの exit を削減
VMCS shadowingネスト仮想化のVMREAD/WRITEをHW処理入れ子のVMM由来 exit を削減

考え方は一貫しています。頻度の高い操作ほどハードウェアで完結させ、root への往復をなくす こと。たとえば割り込みは本来コントローラ(APIC)操作のたびに exit を招きますが、APICv/AVIC は割り込みの配送・優先度評価・EOI をハードウェアでゲストに代行させ、exit を起こしません。残った「どうしてもエミュレートが要る操作」だけが exit としてハイパーバイザに届く、という分業です。

EPT/NPT:二段アドレス変換

最後の難所が メモリ仮想化 でした。ゲストは「ゲスト仮想(GVA)→ゲスト物理(GPA)」を変換していると信じていますが、GPA は本物の物理メモリ(HPA)ではありません。ハードウェア支援以前は、ハイパーバイザが シャドウページテーブル を維持して「GVA→HPA」を一段で引けるよう裏で同期し、ゲストがページテーブルを書き換えるたびに VM exit して追従していました。これがメモリ起因の exit の主因でした。

EPT(Intel: Extended Page Tables)/NPT(AMD: Nested Page Tables) は二段目をハードウェアに肩代わりさせます。CPU は2組のページテーブルを持ち、ゲストの通常ページテーブルで「GVA→GPA」を、EPT/NPT で「GPA→HPA」を変換します。

二段変換(CPUが自動でたどる):
  GVA --[ゲストのページテーブル]--> GPA --[EPT / NPT]--> HPA

注意すべきはコストの形です。ゲストのページテーブルが N 段、EPT が M 段だとすると、ゲスト側の各段アクセスは GPA で表現されるため それ自体を EPT でたどり直す 必要があります。結果、最悪のページウォークは単純な N+M ではなく、おおむね (N+1)×(M+1) - 1 回のメモリ参照になります(x86-64 で 4段×4段なら24回規模)。だからこそ、変換結果を最終段でキャッシュするTLBと、途中を覆うヒュージページが、二段変換では一段のとき以上に効いてきます。多段テーブルの段構成そのものは多段ページテーブルで扱ったとおりです。

EPTはシャドウの何を消したか

EPT の本質は速さより VM exit の削減 です。シャドウ方式はゲストのページ操作ごとに exit が要りましたが、EPT ではゲストは自分のページテーブルを自由に書き換えられ、ハイパーバイザは介入しません。exit が必要なのは GPA→HPA の写像が無い/権限違反のとき(EPT violation)だけで、頻度が桁違いに下がります。

支援機構の対応を一行で

VT-x/AMD-V=特権命令とモードの仮想化(VMX root/non-root、VMCS/VMCB、VM entry/exit)。EPT/NPT=メモリの二段アドレス変換(GPA→HPA をHWで、シャドウページテーブルを置換)。前者が x86 のトラップ問題を、後者がシャドウ維持コストを消した、と二点で押さえると混同しません。

まとめ

  • VT-x/AMD-V はリングと直交する VMX root/non-root モードを追加し、ゲストを無改変・特権命令ごと走らせ、介入が要る事象でだけ VM exit させる。
  • ゲスト/ホストの状態は VMCS/VMCB に保持され、VM entry/exit でハードウェアが一括退避・復元する。何を exit させるかは VM-execution 制御で絞れる。
  • VM exit は高コストなため、APICv・posted-interrupt・VMCS shadowing など exit を減らす最適化 が性能設計の中心になる。
  • EPT/NPT は GPA→HPA の二段目をハードウェアで変換し、シャドウページテーブルの維持と関連する VM exit を激減させる。ただしページウォークは段数の積に膨らむため、TLB とヒュージページの効きが大きい。

OS Article

ハードウェア仮想化拡張の内部(VT-x/AMD-V)を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

仮想化

比較で見る軸

難易度: advanced / カテゴリ: OS / タグ数: 5

導入後に効く点

ゲストとホストの状態はVMCS/VMCBという制御構造に保存され、VM entry/VM exitはこの構造をハードウェアが一括退避・復元することで成立する。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
OS
タグ数
5

判断チェックリスト

  • 自社の用途が「仮想化 / VT-x」に近いか確認する。
  • 強みである「VT-x/AMD-VはCPUにVMX root(ハイパーバイザ)とnon-root(ゲスト)の二つの動作モードを追加し、ゲストは特権命令を含めてそのまま走り、介入が要る事象でだけVM exitする。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

仮想化VT-xAMD-VVMCSEPT仮想化VT-xAMD-V