- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- QEMUアーキテクチャ
- TCG: Tiny Code Generator
- Block Layer: ストレージ管理
- デバイスエミュレーションとVirtIO
- ネットワークバックエンド
- KVM統合: ハードウェアアクセラレーション仮想化
- GPUパススルー(VFIO)
- 実践的なVM作成例
- ユースケース
はじめに
QEMU(Quick Emulator)はオープンソースのマシンエミュレータおよび仮想化ツールです。単独ではソフトウェアエミュレーションを、KVMと組み合わせるとハードウェアアクセラレーション仮想化を提供します。OpenStack、Proxmox、libvirtなど主要クラウドプラットフォームの中核エンジンです。
QEMUアーキテクチャ
システムエミュレーション vs ユーザーモードエミュレーション
QEMUは2つの実行モードを提供します。
[System Emulation] [User-mode Emulation]
+-------------------+ +-------------------+
| Guest OS | | Guest Binary |
| (Full System) | | (Single Process) |
+-------------------+ +-------------------+
| Virtual Hardware | | Syscall変換レイヤー|
| CPU, RAM, Disk, | | (Linux-user / |
| NIC, GPU, USB | | BSD-user) |
+-------------------+ +-------------------+
| QEMU Engine | | QEMU Engine |
+-------------------+ +-------------------+
| Host OS / HW | | Host OS / HW |
+-------------------+ +-------------------+
システムエミュレーション(qemu-system-*):
- コンピュータシステム全体をエミュレーション
- CPU、メモリ、ディスク、ネットワークなどすべてのハードウェアを仮想化
- 異なるアーキテクチャのOSを実行可能(例:x86上でARM Linuxを実行)
ユーザーモードエミュレーション(qemu-*):
- 単一バイナリのみエミュレーション
- 異なるアーキテクチャ用プログラムを現在のシステムで実行
- システムコールをホストOSのシステムコールに変換
# システムエミュレーション例: ARMシステムの起動
qemu-system-aarch64 \
-M virt -cpu cortex-a72 \
-m 2G -nographic \
-kernel Image -append "console=ttyAMA0"
# ユーザーモードエミュレーション例: ARMバイナリをx86で実行
qemu-aarch64 ./arm-binary
TCG: Tiny Code Generator
KVMなしで動作する場合、QEMUはTCG(Tiny Code Generator)というJITコンパイラを使用します。
TCGの動作フロー
Guest Code (例: ARM)
|
v
[Frontend] ゲスト命令をデコード
|
v
TCG IR (Intermediate Representation)
|
v
[Backend] ホスト命令に変換 (例: x86)
|
v
Translation Block (TB) をキャッシュ
|
v
Host CPUで実行
Translation Block(TB):
- ゲストコードの基本ブロック(分岐点まで)を単位として変換
- 変換されたTBはキャッシュに保存して再利用
- TBチェイニングで頻繁に実行されるパスを最適化
- TCGは純粋なソフトウェア方式のためKVMより10〜100倍遅い
[TCG Translation Blockキャッシュ]
Guest PC 0x1000 --> TB #1 (Host code at 0x7f001000)
Guest PC 0x1040 --> TB #2 (Host code at 0x7f001200)
Guest PC 0x1080 --> TB #3 (Host code at 0x7f001400)
...
TB #1 --> TB #2 --> TB #3 (チェイニングで直接ジャンプ)
Block Layer: ストレージ管理
ディスクイメージフォーマット
| フォーマット | 特徴 | 用途 |
|---|---|---|
| qcow2 | Copy-on-Write、スナップショット、圧縮、暗号化 | QEMUデフォルト、プロダクション |
| raw | オーバーヘッドなし、最高のI/O性能 | パフォーマンス重視 |
| vmdk | VMware互換 | VMwareからの移行 |
| vdi | VirtualBox互換 | VirtualBoxからの移行 |
| vpc/vhdx | Hyper-V互換 | Hyper-Vからの移行 |
# qcow2イメージの作成(シンプロビジョニング)
qemu-img create -f qcow2 disk.qcow2 100G
# スナップショットの作成
qemu-img snapshot -c snap1 disk.qcow2
# スナップショット一覧の確認
qemu-img snapshot -l disk.qcow2
# イメージフォーマットの変換
qemu-img convert -f vmdk -O qcow2 source.vmdk target.qcow2
# イメージ情報の確認
qemu-img info disk.qcow2
外部ストレージバックエンド
+------------------+
| Guest VM |
+------------------+
| VirtIO-blk/SCSI |
+------------------+
| QEMU Block Layer|
+--+--+--+--+--+--+
| | | | |
v v v v v
File NBD iSCSI Ceph GlusterFS
RBD
- NBD(Network Block Device): リモートディスク共有
- Ceph RBD: 分散ストレージベースのブロックデバイス
- GlusterFS: 分散ファイルシステムベースのボリューム
- iSCSI: IPネットワークベースのブロックストレージ
デバイスエミュレーションとVirtIO
エミュレーション vs 準仮想化
[従来のエミュレーション] [VirtIO準仮想化]
Guest OS Guest OS
| |
v v
エミュレートされたe1000 NIC VirtIO-netドライバ
| |
v v
QEMUが全レジスタ 共有メモリリングバッファ
アクセスを処理(多数のVM Exit) (最小限のVM Exit)
| |
v v
Host NIC Host NIC
VirtIOデバイスの種類:
| VirtIOデバイス | 機能 | パフォーマンス向上 |
|---|---|---|
| virtio-net | ネットワーク | 10倍以上(e1000比) |
| virtio-blk | ブロックストレージ | 2〜5倍(IDEエミュレーション比) |
| virtio-scsi | SCSIストレージ | 多数のディスクに最適 |
| virtio-gpu | グラフィックス | 3Dアクセラレーション(virgl) |
| virtio-fs | ファイル共有 | ホスト-ゲストファイルシステム共有 |
| virtio-balloon | メモリ | 動的メモリ調整 |
ネットワークバックエンド
+--------+ +--------+ +--------+
| VM 1 | | VM 2 | | VM 3 |
| virtio | | virtio | | virtio |
+---+----+ +---+----+ +---+----+
| | |
+---+-------------+-------------+---+
| Linux Bridge |
| (virbr0) |
+----------------+-------------------+
|
Physical NIC
(eth0)
| バックエンド | 説明 | ユースケース |
|---|---|---|
| SLIRP (user) | ユーザーモードNAT、設定簡単 | 開発/テスト |
| TAP/TUN | カーネルレベル仮想NIC | プロダクション |
| Bridge | TAPをブリッジに接続 | VM間通信、外部アクセス |
| macvtap | macvlan + TAP結合 | シンプルなL2接続 |
| vhost-net | カーネル内VirtIO処理 | 高パフォーマンスネットワーキング |
# TAP + Bridgeネットワーク設定
sudo ip link add br0 type bridge
sudo ip link set eth0 master br0
sudo ip link set br0 up
# QEMUでTAPネットワークを使用
qemu-system-x86_64 \
-netdev tap,id=net0,ifname=tap0,script=no \
-device virtio-net-pci,netdev=net0
KVM統合: ハードウェアアクセラレーション仮想化
KVM_RUN ioctlフロー
QEMU Process (User Space)
|
| ioctl(KVM_RUN)
v
KVM Module (Kernel Space)
|
| VMLAUNCH / VMRESUME
v
Guest Mode (VMX non-root)
|
| VM Exit発生
v
KVM Module (Kernel Space)
|
| KVMが処理可能 -> 直接処理
| 不可能 -> QEMUに返却
v
QEMU Process (User Space)
|
| デバイスエミュレーション等を処理
| 再度 ioctl(KVM_RUN)
v
... (繰り返し)
KVMが処理するVM Exit:
- ほとんどのMSRアクセス
- 単純なI/Oポートアクセス
- EPT違反(メモリマッピング)
- 外部割り込み
QEMUに転送されるVM Exit:
- 複雑なデバイスI/O
- MMIO(Memory-Mapped I/O)アクセス
- 一部のCPUIDリクエスト
QEMU + KVMパフォーマンス
[パフォーマンス比較 (相対値, ネイティブ = 100)]
CPU演算 (整数/浮動小数点):
Native: ████████████████████████████████████████ 100%
QEMU+KVM: ███████████████████████████████████████ 98%
QEMU(TCG): ██████████ 25%
ディスクI/O (VirtIO):
Native: ████████████████████████████████████████ 100%
QEMU+KVM: ████████████████████████████████████ 90%
QEMU(TCG): ████████████ 30%
ネットワーク (vhost-net):
Native: ████████████████████████████████████████ 100%
QEMU+KVM: ██████████████████████████████████████ 95%
QEMU(TCG): ██████████ 25%
GPUパススルー(VFIO)
GPUをVMに直接接続してネイティブに近いグラフィックス性能を提供します。
セットアップ手順
# 1. IOMMUの有効化(GRUBで)
# Intel: intel_iommu=on iommu=pt
# AMD: amd_iommu=on iommu=pt
# 2. IOMMUグループの確認
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=$(basename "$d")
echo "IOMMU Group $(basename $(dirname $(dirname "$d"))): $n $(lspci -nns "$n")"
done
# 3. GPUをvfio-pciにバインド
# GPUのベンダー:デバイスIDを確認
lspci -nn | grep -i nvidia
# 出力例: 01:00.0 VGA ... [10de:2484]
# 出力例: 01:00.1 Audio ... [10de:228b]
# vfio-pciにバインド
echo "10de 2484" > /sys/bus/pci/drivers/vfio-pci/new_id
echo "10de 228b" > /sys/bus/pci/drivers/vfio-pci/new_id
# 4. QEMUでGPUパススルーを実行
qemu-system-x86_64 \
-enable-kvm \
-m 16G \
-cpu host \
-smp 8 \
-device vfio-pci,host=01:00.0,multifunction=on \
-device vfio-pci,host=01:00.1 \
-drive if=pflash,format=raw,readonly=on,file=OVMF_CODE.fd \
-drive if=pflash,format=raw,file=OVMF_VARS.fd \
-drive file=vm-disk.qcow2,format=qcow2,if=virtio
VFIOアーキテクチャ
+-------------------+
| Guest VM |
| (GPUドライバ) |
+-------------------+
| VFIO-PCI |
| (パススルー層) |
+-------------------+
| IOMMU |
| (DMAリマッピング) |
+-------------------+
| Physical GPU |
| (NVIDIA/AMD) |
+-------------------+
- IOMMUがDMAリクエストをリマッピングしてVM間のメモリ分離を保証
- 同じIOMMUグループのすべてのデバイスを一緒にパススルーする必要がある
- OVMF(UEFIファームウェア)でGPU BIOSを初期化
- GPU1台は1つのVMにのみ独占割り当て
実践的なVM作成例
# 基本的なVMの作成と実行
qemu-system-x86_64 \
-enable-kvm \
-name "ubuntu-server" \
-m 4G \
-smp cores=4 \
-cpu host \
-drive file=ubuntu.qcow2,format=qcow2,if=virtio \
-cdrom ubuntu-22.04-server.iso \
-boot d \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-vnc :1 \
-monitor stdio
# SSH接続(ホストから)
ssh -p 2222 user@localhost
# ライブマイグレーション(ソースから)
# 宛先ホストで同じVM設定に -incoming tcp:0:4444 オプションを追加して起動後
# ソースで実行(QEMUモニター):
# migrate tcp:dest-host:4444
ユースケース
| ユースケース | 説明 |
|---|---|
| OpenStack | Nova computeでlibvirt+QEMU/KVMをデフォルトハイパーバイザーとして使用 |
| Proxmox VE | Web UIベースのKVM仮想化 + LXCコンテナ統合管理 |
| 開発環境 | クロスアーキテクチャ開発(x86上でARMなど) |
| セキュリティ研究 | マルウェア分析、脆弱性調査のための隔離環境 |
| CI/CD | クリーンなテスト環境を素早く作成/削除 |
| 組み込み開発 | QEMUで様々なボードをエミュレーション |
クイズ: QEMU/KVM理解度チェック
Q1. QEMUのシステムエミュレーションとユーザーモードエミュレーションの違いは何ですか?
システムエミュレーションはコンピュータシステム全体(CPU、メモリ、ディスクなど)をエミュレートして完全なOSを実行します。ユーザーモードエミュレーションは単一バイナリのみをエミュレートし、システムコールをホストOSに変換します。
Q2. TCGがKVMより遅い理由は何ですか?
TCGはゲスト命令をIR(中間表現)に変換した後、ホスト命令に再変換するソフトウェアJITコンパイル方式です。KVMはハードウェア仮想化拡張(VT-x/AMD-V)を活用してゲストコードをCPUで直接実行するため、はるかに高速です。
Q3. VirtIOがエミュレートされたe1000 NICより速い理由は?
エミュレートされたe1000はすべてのレジスタアクセスでVM Exitが発生します。VirtIOは共有メモリリングバッファを使用して大量のデータを最小限のVM Exitで転送するため、オーバーヘッドが大幅に削減されます。
Q4. GPUパススルーでIOMMUグループが重要な理由は?
同じIOMMUグループのデバイスはDMAを通じて互いのメモリにアクセスできます。セキュリティのため、同じグループのすべてのデバイスを1つのVMに一緒に割り当てるか、すべて隔離する必要があります。
Q5. qcow2フォーマットの利点は何ですか?
Copy-on-Writeによるシンプロビジョニングをサポートし、スナップショット、圧縮、暗号化機能を内蔵しています。100GBのディスクを作成しても、実際に書き込まれたデータ分のみホストストレージを消費します。