エンジニアなら知っておきたい「仮想マシン」のしくみ (bpstudy38)

70

Click here to load reader

Upload: takeshi-hasegawa

Post on 30-Jun-2015

50.205 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

エンジニアなら知っておきたい「仮想マシン」のしくみ

BPStudy #38 (2010/10/29 EBISU303)

ネットワークシステムサービス本部ネットワーク運用・構築部

長谷川 猛 (hasegaw at sra.co.jp)

Twitter : @hasegaw

※本資料中の解説内容は、弊社としての統一的な見解を示すものではありません。

Page 2: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

2

自己紹介

所属所属

興味分野興味分野

株式会社SRAネットワークシステムサービス本部 ネットワーク運用・構築部

現在は提案支援業務に携わる

特にLinux や仮想化技術を得意とする、

雑食系システムエンジニア

主な著書主な著書『Xen 徹底入門』 初版、第二版(2007、2009年 翔泳社)共著

『LDAP Super Expert』(2006年 技術評論社)寄稿

『萌え萌えうにっくす!ネットワーク管理ガイド』(2003年 MYCOM)

氏名氏名長谷川 猛 (HASEGAWA Takeshi)

Twitter: @hasegaw

Page 3: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

3

Page 4: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

4

想定される参加者

• 想定される参加者– 仮想化技術に興味を持っている方

– Linux用仮想化技術『KVM』の仕組みを知りたい方

– KVMの内部構造を調査する”とっかかり”を掴みたい方

• 本セッションへのキャッチアップに必要なスキル※”参加条件”ではありません– IAシステムの基本知識

– C言語の読解能力

– オペレーティングシステム(OS)のしくみ

Page 5: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

5

Agenda

• 現在のx86における仮想マシンの方向性– x86 仮想マシンが提供する基本機能

– x86 仮想マシン技術のトレンド概要

• いまさら聞けない仮想マシンのしくみ– 仮想CPU – 仮想マシンのメモリ管理

– 仮想ハードウェア– virtio 仮想デバイス

• FreeBSD virtio

Page 6: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

現在のx86における

仮想マシンの方向性

Page 7: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

7

x86向けの仮想マシン技術

• そもそも「仮想マシン」とは何か

ソフトウェアによって仮想的に構築されたコンピュータ。

プログラミングにおける仮想マシンは、特定のプログラミング言語の実行コードをそのプラットフォームに適したコードに変換して実行するソフトウェアのことをいう。仮想マシンがプラットフォームによる違いを吸収してくれるため、プログラマはプラットフォームごとの違いを意識せずにソフトウェアを開発できるようになる。

http://e-words.jp/w/E4BBAEE683B3E3839EE382B7E383B3.html (IT用語辞典, 仮想マシン)より引用

Page 8: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

8

x86向けの仮想マシン技術

• 今日、対象とする「仮想マシン」– x86ハードウェアの上で動くソフトウェア(ソリューション?)– x86ハードウェアを再現する– x86ハードウェア用のソフトウェア、OSが「そのまま」動く– VMware, Hyper-V, Linux KVM, Xen各種, VirtualBox, QEMU, Parallels, …

• とりあえず思いつく「その他の仮想マシン」– 言語VM

• Java, .NET Framework, YARV(Yet Another Ruby VM), …– おもちゃのエミュレータ、古いコンピュータのエミュレータ

• MAME, NES, ANEX86/T98, PC98E, …– 特定OSが提供するシステムコールのエミュレーション

• WINE (WINdows Emulator)

Page 9: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

9

仮想化技術から見たx86の歴史

Intel 80861978

vSphere 4.1, RHEV 2.2~2010

vSphere 4.0, Hyper-V 2.0, EL5(KVM)/RHEVオーバーヘッド削減の努力2009

Intel 803861985

|

Xen 2.02004

Hyper-V 1.0メモリ仮想化支援(EPT/NPT)2008

VMware設立1998

RHEL5 (Xen)IOMMU仮想化支援(VT-d)2007

VMware Server, Xen 3.0, KVM開発開始2006

Microsoft Virtual Server R2Intel VT(VT-x, VT-i)2005

x86ハードウェアの仮想化対応

仮想マシンの幕開けRobert P. Goldberg - Survey of Virtual Machine Research

1975

Xen 1.0, XenSource設立2003

x86仮想化ソフトウェア年

SRA創立(1967)

SRA, VAX-11導入(1980)

Page 10: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

10

活性化してきたx86仮想化

• Xen Hypervisorがもたらしたもの 「Windowsが動く」オープンソースのハイパーバイザ

Intel VTを使った代表的な仮想マシン実装

専用カーネルを使う「準仮想化」による高いパフォーマンス

• ハードウェアによる仮想化支援機能の充実 VT-x, VT-I, AMD-V … CPUの仮想化

• さらなる仮想化支援機能の強化 VT-x, VT-I, AMD-V … さらなるパフォーマンス向上

VT-d, AMD IOMMU… 仮想マシンからのPCIデバイスアクセス

EPT/NPT … 仮想マシンのメモリアクセス高速化

「カーネルはX86用OSを使用し、I/O部分のみを準仮想化」する方向へ

Page 11: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

11

準仮想化 vs 完全仮想化

ハードウェアハードウェア

ハイパーバイザ

(ハードウェア支援なし)

ハイパーバイザ

(ハードウェア支援なし)

仮想化専用

kernel

仮想化専用

kernel x86 H/W用

kernel

x86 H/W用

kernel

ハイパーバイザ

(ハードウェア支援あり)

ハイパーバイザ

(ハードウェア支援あり)

x86 H/W用

kernel

x86 H/W用

kernel

ハードウェアレベル 仮想化支援機能ハードウェアレベル 仮想化支援機能

KVM, VMware, …Xen

Page 12: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

12

クラウドに求められる仮想マシンの特性

• クラウドコンピュータ – “規模”が実現するシステム運用ファシリティ →ラック、データセンタ、コンテナ単位での導入

インシデント駆けつけ型保守 → 計画的保守へ

システム全体としての耐障害性、各ノードの柔軟な構成・運用が必要

• 物理マシンと比べ魅力的な“仮想マシン”の特性 導入後からの構成変更、レプリカの作成が容易

手元でなくとも“完全な管理”

サービス提供用OSの起動・停止が容易

(ソフトウェアで実現でき、専用ハードウェアなどが不要)

仮想化によるパフォーマンス低下

• 運用と性能のどちらを取るか?

Page 13: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

13

On-going なトピック

• “ゲストOS”としての各OSの仮想化サポート– 仮想環境むけデバイスドライバの標準装備化– 仮想環境における時間管理(Dynamic Tick、PV Timer)

• よりシームレスな統合管理– ノード管理ツールの強化

– クラウドとしてのリソース管理ツールVMwareを買うエンドユーザ、内製するサービスベンダ

• 性能が求められる環境に対応するハードウェア– Device Passthrough– SR-IOV

• より安価・高速・高信頼なストレージシステム– 実は仮想マシンにとって一番大事

Page 14: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

いまさら聞けない「仮想マシン」のしくみ

Page 15: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

15

qemu-kvmとQEMU

• QEMU … オープンソースのPCエミュレータ– ソフトウェアによるCPUおよび関連チップを再現

• ソフトウェアCPU: x86 32bit/64bit, IA64, ARM, SPARC, PowerPC, MIPS

– Bochs由来のBIOSを搭載

– ユーザモードで動作するプログラム

• QEMUからforkした仮想マシンソフトウェア群– VIrtualBox (Sunによる仮想マシンソフトウェア)

– Xenに含まれるqemu-dm(Xen HVM用ハードウェアエミュレータ)

– kqemu (カーネルモードで動作する、より高速なQEMU)

– qemu-kvm (CPU仮想化にKVMを使用するQEMU)

Page 16: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

16

(参考) QEMUを使ったVMM

現Oracle VM(ブランド名)

Sun xVM (ブランド名)

Bochs (2 )

QEM U (2)

kQEMU

一部処理(CPU処理)

をkernel modeに持っ

ていって高速化した版

QEMU。KVM登場によ

りdiscon

各種CPUエミュレータ+デバイスエミュレー

タ。Bochsと比べ高速なのがウリ。デスク

トップ用、開発者用ともいえる

PC/AT互換機を再現できる、ほぼ最初の

CPUエミュレータ+デバイスエミュレータ。

KV M (1)

V irtualBox (2)

Sunが開発した

VMM+QEMUのハー

ドウェアエミュレータ

部分による仮想化ソ

フトウェア。とはいえ

H/Wエミュ部分に随

分Sunのコードが入っ

ているのが特徴的?

デスクトップ用

Xen 2.x (1)

PC/ATを再現するのではなく、OS側を

VMMにあわせる「準仮想化」を採用した

VM

Xen 3 .0 (1)

Xenの上でPC/ATを

再現できるように

なった最初のバー

ジョン

qemu-dm

Xen用にforkされ改造

されたもの

BIOSコード流用

fork→merge→

disconfork→merge

qemu-kvm

Linux上でIntel

VT(AMD-V)を利用

するためのカーネル

モジュール。CPU仮

想化、メモリ仮想化

の機能を提供。

QEMUのCPUエミュ

レータを使わずに

KVMを使う。KVMが

H/Wアクセスを検出

した際にqemu-kvm

がH/Wエミュレーショ

ンする仕組み

fork

Xen 4 .0 (1)

Oracle V MServer (1 )

H/W emuコード

大量流用

xV MHypervisor (1)

×

×コンフリクト

SunがOpenSolaris用

にパッケージした

オープンソース版

Xen。Oracle VM

Serverとコンフリクト

するためdiscon.

Oracleがオープン

ソース版Xenをベー

スに開発。

独自のWindows用ド

ライバ、管理ツール、

Oracle製品サポート

などの特徴を持つ

fork fork

Page 17: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

17

KVMが必要とするハードウェアスペック

• 最低要求事項– CPU

• x86_64 or IA64 (64bit ほぼ必須)• 仮想化支援技術必須 (Intel VT or AMD-V)

– マザーボード、チップセット• BIOSレベルで仮想化支援技術が有効であること

– メモリ• ホストOS使用分: 512MB以上

• ゲストOS使用分: 512MB以上

– その他Linuxカーネルの動作要件を満たすこと

• 推奨スペック– Intel EPT (Extended Page Tables)/AMD NPT(Nested Page Tables)

Page 18: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

18

Red HatのKVMによりサポートされるゲストOS

• virtioドライバが提供されておりパフォーマンスが期待できるもの– EL3.9 (32bit, 64bit), EL4.7(32bit, 64bit), EL5.3 (32bit, 64bit)– Windows Server 2003 (32bit, 64bit)– Windows Server 2008 (32bit, 64bit)– Windows XP (32bit) – Network driver only– 2000=NG Vista, 7=?

• RHEL5により公式サポートされるもの– EL3(32bit), EL4(32bit or 64bit), EL5(32bit or 64bit)– Windows Server 2003 (32bit, 64bit)– Windows Server 2008 (32bit, 64bit)– Windows XP (32bit)

※公式なサポート状況はRed Hatにご確認ください

Page 19: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

19

XenとKVMのざっくりした比較

• ハイパーバイザー(VMM)の機能– Xen: Hypervisorと管理OSの独立性が高い

• 管理OSへの攻撃が難しい?

• XSM (Xen Security Modules) – LSM (Linux Security Module) のXenバージョン

– Linux: Hypervisorと管理OSが融合している

• 比較的コンテキストスイッチが少なく高速

• SELinuxを利用したMAC

• ゲストのサポート状況、サポート方法– Xen: Linux, NetBSD/FreeBSD, OpenSolaris, Windows

• Xen用カーネルを作成するアプローチ、PVドライバのみ移植するアプローチ

– KVM: Linux, Windows• virtioドライバを移植するアプローチ

Page 20: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

CPUの仮想化

Page 21: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

21

x86のプロテクトモード基礎知識

• IAのリングプロテクション基礎知識– リアルモード(16bit)

• 16ビットまでのデータ操作・メモリ操作

– プロテクトモード(32/64bit)• 32/64ビットの操作、ページ単位のメモリ管理

• プロテクション リング

– X86 CPUに実装された権限機能

– Ring 0: 特権モード

– Ring 1~2: 使わないのが通例

– Ring 3: ユーザモード

Applications – Ring 3

Operating System Services – Ring 1, 2

Operating System – Ring 0

x86 Protection Rings

NTOSKRNL

linux-kernel

Apache

calc.exe

Page 22: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

22

QEMUによるVMの動作原理

• QEMU の基本動作– VM上のコードを実行する前に、コードを確認する

• CPU上で直接実行できない命令(例:仮想メモリの設定、権限管理)

対応するルーチンを実行

• 通常の命令(例:仮想メモリに対する操作、演算など)

直接実行

– VM上のコードが実行された時にCPUで例外を捕捉する• VMの権限で直接実行できない命令(例:I/Oポート操作)

デバイスエミュレータで原因を解析、エミュレーションしVM実行を継続

• ゲストに未割り当てのページアクセスメモリを割り当て、VM実行を継続

Page 23: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

23

Intel VT, AMD-Vの基礎知識

• 仮想マシン実行用モードの追加メモリ上の仮想マシン情報を基に、VMを実行する

必要に応じて制御をゲストから奪い、VMM(仮想マシンモニタ)へ戻す

linux-kernel

kvmGuest kernel

VMX Root VMX nonroot

仮想マシンへの突入VMLAUNCH/VMRESUME (Intel)

VMRUN (AMD)

仮想マシンからの復帰特権命令、I/O操作等→VMEXIT

VMCS VMCB(AMD)

VMCS VMCB(AMD)

VMCS VMCB(AMD)

Apache

calc.exe

qemu-kvm

Page 24: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

24

qemu-kvmによるVMの動作原理

• qemu-kvm (KVM使用時)KVMを使用してVMを実行 (VMRESUME/VMRUN)

VM内で特殊命令にあたると制御が戻る(VMEXIT)

通常の命令であれば直接実行される

qemu-kvm内のハンドラが必要な処理を行う

– I/Oポートの読み書き、MMIOなどハードウェアアクセス

– 一定時間オーバー

– VM内からのVMM呼び出し

– VMの実行失敗、ほかエラーなど

Page 25: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

25

qemu-kvmにおける制限事項

• 仮想化支援技術が必須– Intel VT(VT-x) もしくは AMD-V

従来x86 CPUの特権モードに加え「VMX root」「VMX nonroot」を提供

VM専用空間(VMX nonroot)でVM上の命令を実行

非互換命令などにあたったら、VMM側(VMX root)に制御を戻す

• 仮想化支援技術にともなうゲストの制限– CPU

• qemu-kvmは、基本的に実CPU上でVMを直接実行する

• 実CPUが実行可能なコード(OS, アプリケーション)のみ実行可能

• 実際に搭載したCPUができない事はVM内でも「できない」

(エラーをトラップしエミュレーションすることは技術的には可能)

Page 26: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

26

KVM kernel moduleが提供する

インターフェイス

• /dev/kvm … 特殊なデバイス– ioctl()で操作する

– 主な機能• 新しいVMの作成

• VMへのメモリ割り当てリクエスト

• vCPUのレジスタの読み書き

• vCPUへの割り込み挿入

• vCPUの実行開始

• I/Oハンドラの登録

• qemu-kvmが/dev/kvmを通してVMを制御する

Page 27: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

27

qemu-kvmからのKVMモジュール操作

599 int kvm_run(CPUState *env) 600 { 601 int r; 602 kvm_context_t kvm = &env->kvm_state->kvm_context; 603 struct kvm_run *run = env->kvm_run; 604 int fd = env->kvm_fd; 605 606 again: ……… 610 } 626 r = ioctl(fd, KVM_RUN, 0); 645 if (1) { 646 switch (run->exit_reason) { 647 case KVM_EXIT_UNKNOWN: 650 case KVM_EXIT_FAIL_ENTRY: 653 case KVM_EXIT_EXCEPTION: 660 case KVM_EXIT_IO: 661 r = kvm_handle_io(run->io.port, 662 (uint8_t *)run + run->io.data_offset, 663 run->io.direction, 664 run->io.size, 665 run->io.count); 666 r = 0; 667 break; 668 case KVM_EXIT_DEBUG: ……… 694 default: 701 } 702 }

kvm-main.c1370 static long kvm_vcpu_ioctl(struct file *filp,1371 unsigned int ioctl, unsigned long arg)1372 {1373 struct kvm_vcpu *vcpu = filp->private_data;1374 void __user *argp = (void __user *)arg;1375 int r;1376 struct kvm_fpu *fpu = NULL;1377 struct kvm_sregs *kvm_sregs = NULL;13781379 if (vcpu->kvm->mm != current->mm)1380 return -EIO;1381 switch (ioctl) {1382 case KVM_RUN:1383 r = -EINVAL;1384 if (arg)1385 goto out;1386 r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);1387 break;1388 case KVM_GET_REGS: { ….1404 break;1405 }

VMを実行後何がおきたかを確認し、対処

仮想化支援機能を使用してVMを実行する

Page 28: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

28

CPU仮想化のまとめ

CPUの仮想化支援機能 Intel VT-x/VT-I AMD-V x86のリングプロテクションに加え、さらにVMMをサポートするための

命令セットが追加されている

KVMカーネルモジュール CPUの仮想化支援機能を使用して、おもに以下の処理を行う

• VM起動

• VM停止

• ハードウェアI/Oが発生したときのディスパッチ

• メモリの管理

制御はioctl()を使って行う

Page 29: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

仮想マシンのメモリ管理

Page 30: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

30

メモリ管理

• 実機環境(ベアメタル + OS)では– OSが物理メモリすべてを認識し、管理する

– OSは、物理メモリの一部をカーネル用とし、各プロセスの要求に応じてメモリを割り当てる

• 仮想化環境では– VMMがVM物理メモリすべてを認識し、管理する

– VMMがVMに対して指定容量のメモリを割り当てる

– VMは割り当てられたメモリが物理メモリ全体と信じて動作する

– ゲストOSは、VMに割り当てられたメモリからカーネル用、各プロセス用のメモリ空間を確保する

Page 31: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

31

メモリ管理、ちょっと寄り道(1/2)

モダンなシステムにおける、物理メモリ空間と仮想メモリ空間

0GiB -

OS Kernel

Process 2

Process2 から見える

メモリ空間物理メモリ

OS Kernel

Process 1

Process 2

Process 3

Process 4

64GiB -

OS Kernel

Process 1

Process1 から見える

メモリ空間

Page 32: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

32

メモリ管理、ちょっと寄り道(2/2)

procedure CR3Read(var p : Pointer);asm

mov p, cr3end;

// エディットボックスEdit1の内容が変更されたら、その内容を// 文字列バッファbuffにコピーする。procedure TForm1.Edit1Change(Sender: TObject);begin

StrPCopy(@buff, Edit1.Text);end;

// Button1がクリックされたら、文字列バッファがどこにあるか// アドレスを表示し、また、バッファ上の文字列を表示する。procedure TForm1.Button1Click(Sender: TObject);var

s: String;begin

s := format('バッファは0x%pにあります。', [ @buff ]);memo1.lines.add(s);

s := format('このアドレスには文字列 %s が記録されています。',[ PChar(@buff) ] );

memo1.lines.add(s);end;

// Button2がクリックされたら CR3 を読み取り、表示する。// ※特権命令があるため、実際には成功しないprocedure TForm1.Button2Click(Sender: TObject);var

p: Pointer;s: String;

beginCR3Read(p);

s := format('このプロセスのCR3は %p を指しています。',[ p ] );

memo1.lines.add(s);end;

サンプル ダウンロード先http://bit.ly/aPn3zm

Page 33: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

33

x86におけるメモリ管理の基本 #1

メモリアクセス要求 CR3

Page DirectoryPage Directory

Page TablePage Table

Page TablePage Table

Page TablePage Table

10bits(2^10=1024)分のテーブル

PDE(32bits) × 1024 = 4KB (1page)

10bits(2^10=1024)分のテーブル

PTE(32bites) = 4KB (1page)

Page

プロセスが実際にアクセスすべきメモリ空間(12bits) 2^12=4KB

10+10+12=32bitのメモリ空間を2段のぺージテーブルで表現(64bit環境では4段のページテーブルで48bitアドレス空間を表現) Linux (or other OS) Kernel

process

PTPD PTPD PT PT

Page Page Page Page

process

PTPD PTPD PT PT

Page Page Page Page

process

PTPD PT PT PT

Page Page Page Page

qemu-kvm

PTPD PTPD PT PT

Page Page Page Page

CR3 IP …CR3 IP …CR3 IP …CR3 IP …process 4

プロセステーブルprocess 1process 2process 3

そのプロセスの仮想メモリ空間と物理メモリ空間の対応を定義する

Page Directoryのポインタ、他

Page 34: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

34

x86におけるメモリ管理の基本 #2

出典: Intel® 64and IA-32 Architectures Software Developer’s Manual Volume 3A

Page 35: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

35

仮想化におけるメモリ利用のイメージ

ベアメタル環境の場合

0GiB -

OS Kernel

Process 2

ユーザプロセスから見えるメモリ空間物理メモリ

Hypervisor

Guest OS 1

Guest OS 2

Guest OS 3

Guest OS 4

OS Kernel

Process 1

Process 2

Process 3

Process 4

ゲストOSの

メモリ空間

OS Kernel

Process 1

Process 2

Process 3

Process 4

64GiB -

仮想化環境の場合

物理メモリ

Page 36: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

36

KVM, QEMUにおけるVMへの仮想物理メモリ割当 #1

• VMのメモリ空間はqemu-kvm(or QEMU)のデータ領域として確保される– 他の一般なプロセスと同じ扱い

• Linuxカーネルから見ればただのユーザスペースのデータ領域に過ぎない

Linux Kernel

qemu-kvm (or QEMU)

VM Image

process

process

process

物理メモリ

Page 37: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

37

KVM, QEMUにおけるVMへの仮想物理メモリ割当 #2

514 void *kvm_create_phys_mem(kvm_context_t kvm, unsigned long phys_start, 515 unsigned long len, int log, int writable) 516 { 517 int r; 518 int prot = PROT_READ; 519 void *ptr; 520 struct kvm_userspace_memory_region memory = { 521 .memory_size = len, 522 .guest_phys_addr = phys_start, 523 .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0, 524 }; 525 526 if (writable) 527 prot |= PROT_WRITE; 528 530 ptr = mmap(NULL, len, prot, MAP_ANONYMOUS | MAP_SHARED, -1, 0); 535 if (ptr == MAP_FAILED) { 536 fprintf(stderr, "%s: %s", __func__, strerror(errno)); 537 return 0; 538 } 539 540 memset(ptr, 0, len); 541 542 memory.userspace_addr = (unsigned long)ptr; 543 memory.slot = get_free_slot(kvm); 549 r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory); 550 if (r == -1) { 551 fprintf(stderr, "%s: %s", __func__, strerror(errno)); 552 return 0; 553 } 554 register_slot(memory.slot, memory.guest_phys_addr, memory.memory_size, 555 memory.userspace_addr, memory.flags); 556 557 return ptr; 558 }

プロセス内に仮想マシン用のメモリ領域を確保

VMのメモリ空間に、確保し

たメモリ領域を割り当て

Page 38: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

38

VM上のページング① - ソフトウェア処理Shadow Page Table (SPT) #1

OS Kernel

Process 1

Process 2

Process 3

Process 4

ゲストOSの

メモリ空間

物理メモリ

PTPD PTPD PT PT

PTPD PTPD PT PT

VM上の は、ゲストOSが管理するページテーブル

である。ゲストOSはVMに割り当てられたメモリ空間を物理メモリ空間全体と

信じてページテーブルを作成する。

PTPD PTPD PT PT

VM上のコードを実行する際、CPUはVMのメモリ空間で動作しなけれ

ばいけない。この際に参照すべきページテーブルは何か?

VM上のゲストOSが管理する をCPUが参照すると、物理メモリ空間が見えてしまい、本来ゲストOSが意図したページへ

アクセスされない。

PTPD PTPD PT PT

この問題を解決するため、仮想化ソフトウェアはシャドウページテーブル を作成する。これは、VM上の仮想メモリ空間を物理ページにマッピングする内容となるため、CR3レジスタにを設定することでCPUがVMのアドレス空間を解決可能となる。

PDVMへの割当ページ情報

PTPD PTPD PT PT

また、VM上のコード実行時、ページ読み書きの際にのAccess bit, Dirty bitがアップデートされる。これらは

へ、逆に同期する必要がある。

PTPD PTPD PT PT PTPD PTPD PT PTVMへの割当ページ情報= +

PTPD PTPD PT PT

PTPD PTPD PT PT

PD

sync

sync

Page 39: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

39

VM上のページング① - ソフトウェア処理Shadow Page Table (SPT) #2

• VVMが、VM内で使われるページテーブルを基に Guest Virtual →Machine-Physicalのページ追跡に使用するページテーブルを作成

1. VM上からハイパーコールが実行される

2. VMMがvCR3を読み取りVMに制御を戻す

1. VMが管理するvCR3を読み取ろうとする

2. VMX non-rootからVMEXITする

3. VMMがVMEXITの原因を確認し、vCR3を読み取りを再現して再度VMENTERする

CR3参照

Intel VT / AMD-Vなしの場合Intel VT / AMD-V ありの場合

1. VM上からハイパーコールが実行される

2. VMMがvCR3を書き込んだことにする

3. Shadow Page Table を更新する

4. VMMがVMに制御を戻す

1. VMMが命令をスキャンし、CR3読み書き等の命令を洗い出す

2. 見つかった命令群をハイパーコールに書き換え

1. VMがメモリにアクセスする(この際、実CR3=SPT)

2. CPUがSPTを使用してゲストの仮想アドレスをホストの物理アドレス空間に解決通常ページへの読み書き

1. VMがメモリにアクセスする(この際、実CR3=SPT)

2. VMからSPT(VMMのメモリ空間)に書き込めないためページフォルトを引き起こす

3. VMMがVM中のページテーブルを更新

4. VMMがvCR3の示すページテーブルにあわせてSPTを更新

ページテーブル書込

1. VMがメモリにアクセスする(この際、実CR3=SPT)

2. VMからSPT(VMMのメモリ空間)を読めずページフォルトを引き起こす

3. VMMが、必要に応じてSPT上のAccess bit, Dirty bitをVM上のページテーブルへ転記

4. VMMが、VMのvCR3が示すページテーブルを返す

ページテーブル参照

1. VMがvCR3を書き込もうとする

2. VMX non-rootからVMEXITする

3. VMMがVMEXITの原因を確認し、vCR3を書き込みを再現する

4. VMMがShadow Page Table を更新する

5. VMMが再度VMENTERし、VMに制御を戻す

CR3書込

(前処理不要)(命令実行前)

実際の操作VM内の操作

Page 40: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

40

Linux + KVM Linux + KVM qemu-kvmqemu-kvm

VM’s Page Table Shadow Page Table

VM上のページング① - ソフトウェア処理Shadow Page Table (SPT) #3

VM内の4段ページテーブル(64bitの場合、32bitの場合は2段)

CR3

Page

Page

Page

PML4

PDPT

PD

PT

CR3

例外による操作検出内容の同期

PML4

PDPT

PD

PT

VM内で見えるCR3

VM内で実際にCPUが使っている

CR3

TLB参照

TLB更新

メモリアクセス

要求

Page 41: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

41

VM上のページング① - ソフトウェア処理Shadow Page Table (SPT) #4

SPTの問題点

• 必要メモリ量 (VM上のPT, VMM上の割当テーブル、さらにSPT)

• VMMコードのプロファイリングを行うと、約75%がSPT関連処理

It is estimated that for certain workloads shadow paging can account for up to 75% of overall hypervisor overhead.

- AMD-V™ Nested Paging, ©2008 Advanced Micro Devices, Inc.

KVMはShadow Page Tableのパフォーマンスが高くない

• 新CPUのVM用ページング支援機能を利用するのが前提

• SPTのサポートはあくまで互換性目的

• SPTの性能はXen > KVM

Page 42: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

42

VM上のページング② - ハードウェア処理Extended Page Tables(EPT)/AMD Nested Page Tables(NPT) #1

• 物理(ベアメタル)環境– Memory Management Unit (MMU) – ハードウェア実装– CR3レジスタで指定されたページテーブルに従ってCPUが仮想メモリ機能を提供

• これまでの仮想化環境– VMMが、VM向けのページテーブルをソフトウェア的に再現– VMMが、ゲストOSのページテーブルをベースに

VM内仮想アドレス→物理アドレレスのテーブルを作成、管理(Shadow Page Table)

• EPT/NPT有効時の仮想化環境– VMの物理アドレス(Guest-Physical)を実際の物理アドレス(Machine-Physical)に

変換する機能を提供– VMMは必要なページテーブル情報をメモリ上に作成、CPUに設定する– ゲスト実行時のページテーブル参照をCPUが自動処理– パフォーマンスの大幅向上。KVMの場合約30%

Page 43: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

43

Linux + KVM Linux + KVM qemu-kvmqemu-kvm

VM’s Page Table Shadow Page Table

VM内の4段ページテーブル(64bitの場合、32bitの場合は2段)

メモリアクセス

要求CR3

Page

Page

Page

PML4

PDPT

PD

PT

CR3

例外による操作検出内容の同期

Extended Page TablePML4

PDPT

PD

PT

PML4

PDPT

PD

PT

VM上のページング② - ハードウェア処理Extended Page Tables(EPT)/AMD Nested Page Tables(NPT) #2

VM実行時実際にCPUが使っている

CR3

VMMが作成した、VMへのメモリ割当を

示すテーブル

VM内で見えるCR3

Page 44: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

44

メモリ管理のまとめ

物理アドレスと仮想アドレス仮想アドレスを用いたアクセスにはページテーブルが必要Shadow Page Table

• VM内仮想アドレスをマシン物理アドレスに変換するテーブル

Extend Page Tables, Nested Page Tables• Shadow Page Tableを使用せず、CPUがVM内仮想アドレスを

マシン物理アドレスに変換

CPUアークテクチャに応じた仮想化技術の選択Core i7, Xeon 5500(Nehalem) 未満 …. KVM < XenCore i7, Xeon 5500(Nehalem) 以後 …. KVM ≒ Xen

Page 45: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

デバイスのエミュレーション

Page 46: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

46

• I/Oポート– プロセッサから外部に接続するためのデジタルインターフェイス– ON(1) もしくは OFF(0) を通信する– 1アドレス 8ビット×64K、アクセス単位が基本8ビットなので非常に低速

【使途】キーボードの押下状況確認、ディスクコントローラの状態設定、通知など

• ダイレクトメモリアクセス(Direct Memory Access)– DMAコントローラがデバイス上のメモリ-メインメモリ間のデータ転送を行う【使途】VGA, Sound, Disk Controller, Ethernet Controller など大量コピー

• メモリマップドI/O (Memory Mapped I/O)– プロセッサの物理メモリ空間に、デバイス上のメモリ空間をマッピングする– ソフトウェアからデバイス上のメモリ空間に直接アクセスできる【使途】VGA, Sound, Disk Controller, Ethernet Controller など大量コピー

• 割り込み(Interrupt)– デバイスからCPUへイベントを通知するための信号【使途】タイマーの通知、キーボードの状態変化通知、データ転送完了通知(DMA, MMIO)など

x86で使用される主なデバイスI/O方式

Page 47: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

47

SerialPort

SerialPort

ParallelPort

ParallelPort

PIIX3 PCI IDEPIIX3 PCI IDE

PIIX3 PCI USBPIIX3 PCI USB

PCI SlotPCI SlotPCI SlotPCI Slot

LSI LogicLSI53c895a

LSI LogicLSI53c895a

System MemorySystem Memory

BochsFlash BIOS

BochsFlash BIOS

Real TimeClock

Real TimeClock

Cirrus LogicCL-GD5446

Cirrus LogicCL-GD5446

RealtekRTL8029

RealtekRTL8029

EnsoniqES1370

EnsoniqES1370

ISA

Bus

ISA

BusISA

I/O Interface

ISAI/O Interface

FloppyFloppy

PC SpeakerPC Speaker

PCI

Bus

PCI

Bus

Intel 82371 PIIX3(South-bridge)

Intel 82371 PIIX3(South-bridge)

CPUCPU

VGAVGA

EthernetEthernet

SpeakerSpeaker

SCSI HDDSCSI HDD

IDE HDDIDE HDD

CD-ROMCD-ROM

USBUSB

KeyboardKeyboard

MouseMousePS/2PS/2

QEMUによるx86ハードウェアエミュレーション

出典: KVM徹底入門 (2010年 翔泳社)

Intel 82441FX(North-bridge)

Intel 82441FX(North-bridge)

Page 48: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

48

KVMによるx86ハードウェアエミュレーション

• QEMU由来のデバイスエミュレータを使用– Xen, VirtualBox等オープンソースの仮想

マシンはほとんどQEMU由来のエミュレータを使用している

• 仮想デバイスの処理の流れ– VM内でハードウェアアクセスが発生!

– CPUがゲストOSからホストOSへ制御を返す

– KVMが例外をトラップし、QEMUのイベントハンドラに制御を移す(返す)

– QEMUのイベントハンドラがトラップの原因を確認し、適宜必要な処理を行う仮想デバイスに対するI/O なら

デバイスエミュレータを実行

– QEMUがKVMに、KVMがVMに制御を戻す

– VMはハードウェアアクセスが成功したと信じて実行を続ける

LinuxカーネルLinuxカーネル

KVMカーネルモジュール

KVMカーネルモジュール

qemu-kvmqemu-kvm

VM Image

Event Handler,

Device Emulator

ハードウェアハードウェア

デバイスドライバデバイスドライバ

③’

Page 49: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

49

733 static int kvm_handle_io(uint16_t port, void *data, int direction, int size, 734 uint32_t count) 735 { 736 int i; 737 uint8_t *ptr = data;738 739 for (i = 0; i < count; i++) { 740 if (direction == KVM_EXIT_IO_IN) { 741 switch (size) { 742 case 1: 743 stb_p(ptr, cpu_inb(port)); 744 break; 745 case 2: 746 stw_p(ptr, cpu_inw(port)); 747 break; 748 case 4: 749 stl_p(ptr, cpu_inl(port)); 750 break; 751 } 752 } else { 753 switch (size) { 754 case 1: 755 cpu_outb(port, ldub_p(ptr)); 756 break; 757 case 2: 758 cpu_outw(port, lduw_p(ptr)); 759 break; 760 case 4: 761 cpu_outl(port, ldl_p(ptr)); 762 break; 763 } 764 } 765 766 ptr += size; 767 } 768 769 return 1; 770 }

KVMによるx86 H/Wエミュレーション (ソース追跡編 #1)

599 int kvm_run(CPUState *env) 600 { 601 int r; 602 kvm_context_t kvm = &env->kvm_state->kvm_context; 603 struct kvm_run *run = env->kvm_run; 604 int fd = env->kvm_fd; 605 606 again: ……… 610 } 626 r = ioctl(fd, KVM_RUN, 0); 645 if (1) { 646 switch (run->exit_reason) { 647 case KVM_EXIT_UNKNOWN: 650 case KVM_EXIT_FAIL_ENTRY: 653 case KVM_EXIT_EXCEPTION: 660 case KVM_EXIT_IO: 661 r = kvm_handle_io(run->io.port, 662 (uint8_t *)run + run->io.data_offset, 663 run->io.direction, 664 run->io.size, 665 run->io.count); 666 r = 0; 667 break; 668 case KVM_EXIT_DEBUG: ……… 694 default: 701 } 702 } 703 more: 704 if (!r) { 705 goto again; 706 } 707 return r; 708 }

qemu-kvm.ckvm_run関数 (VM実行部分)

VM実行

kvm-all.ckvm_handle_io関数 (I/Oイベントハンドラ)

読み取り????

I/Oポートへの

書き込み

ioport.c201 void cpu_outw(pio_addr_t addr, uint16_t val)202 {203 LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);204 ioport_write(1, addr, val);205 }

ioport.c

70 static void ioport_write(int index, uint32_t address, uint32_t data) 71 { 72 static IOPortWriteFunc * const default_func[3] = { 73 default_ioport_writeb, 74 default_ioport_writew, 75 default_ioport_writel 76 }; 77 IOPortWriteFunc *func = ioport_write_table[index][address]; 78 if (!func) 79 func = default_func[index]; 80 func(ioport_opaque[address], address, data); 81 }

I/O発生 → QEMUの

イベントハンドラへ

I/Oポートに対応する

イベントハンドラへ

Page 50: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

50

フロッピーディスクコントローラをQEMUに登録1955 static int isabus_fdc_init1(ISADevice *dev)1956 {1957 fdctrl_isabus_t *isa = DO_UPCAST(fdctrl_isabus_t, busdev, dev);1958 fdctrl_t *fdctrl = &isa->state;1959 int iobase = 0x3f0;1960 int isairq = 6;1961 int dma_chann = 2;1962 int ret;19631964 register_ioport_read(iobase + 0x01, 5, 1,1965 &fdctrl_read_port, fdctrl);1966 register_ioport_read(iobase + 0x07, 1, 1,1967 &fdctrl_read_port, fdctrl);1968 register_ioport_write(iobase + 0x01, 5, 1,1969 &fdctrl_write_port, fdctrl);1970 register_ioport_write(iobase + 0x07, 1, 1,1971 &fdctrl_write_port, fdctrl);1972 isa_init_irq(&isa->busdev, &fdctrl->irq, isairq);1973 fdctrl->dma_chann = dma_chann;19741975 ret = fdctrl_init_common(fdctrl, iobase);19761977 return ret;1978 }

QEMUからの通知を受け取るイベントハンドラ 589 static uint32_t fdctrl_read_port (void *opaque, uint32_t reg) 590 { 591 return fdctrl_read(opaque, reg & 7); 592 } 593 594 static void fdctrl_write_port (void *opaque, uint32_t reg, uint32_t value) 595 { 596 fdctrl_write(opaque, reg & 7, value); 597 } 598 599 static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg) 600 { 601 return fdctrl_read(opaque, (uint32_t)reg); 602 } 603 604 static void fdctrl_write_mem (void *opaque, 605 target_phys_addr_t reg, uint32_t value) 606 { 607 fdctrl_write(opaque, (uint32_t)reg, value); 608 }

KVMによるx86 H/Wエミュレーション (ソース追跡編 #2)

529 static uint32_t fdctrl_read (void *opaque, uint32_t reg) 530 { 531 fdctrl_t *fdctrl = opaque; 532 uint32_t retval; 533 534 switch (reg) { 535 case FD_REG_SRA: 536 retval = fdctrl_read_statusA(fdctrl); 537 break; 538 case FD_REG_SRB: 539 retval = fdctrl_read_statusB(fdctrl); 540 break; 541 case FD_REG_DOR: 542 retval = fdctrl_read_dor(fdctrl); 543 break; … 556 default: 557 retval = (uint32_t)(-1); 558 break; 559 } 561 562 return retval; 563 }

レジスタの読み取りエミュレーション 847 /* Status B register : 0x01 (read-only) */ 848 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) 849 { 850 uint32_t retval = fdctrl->srb; 854 return retval; 855 }

I/Oポートアクセス

qemu-0.12.5/hw/fdc.c (仮想フロッピーディスクコントローラ)

QEMU I/Oポートテーブル

Page 51: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

51

QEMUの仮想デバイスを選択する(1/3)

• QEMUには同種のデバイスエミュレータが複数実装されている

• いちばん気になる「仮想NIC」– rtl8139 (Realtek 8139)

– e1000 (Intel PRO/1000)

• 何が違うのか

– ゲストが認識するデバイス

– デバイスドライバ

エミュレーションの効率→ “全ゲストでシェアするCPU”の利用効率

Page 52: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

52

QEMUの仮想デバイスを選択する(2/3)

• どれぐらい効率が違うものか?

58.3Mbps 対 394Mbps (6.75倍)

C:¥>iperf -c 192.168.44.25 -w 4M

------------------------------------------------------------

Client connecting to 192.168.44.25, TCP port 5001

TCP window size: 4.00 MByte

------------------------------------------------------------

[1912] local 192.168.44.77 port 3334 connected with 192.168.44.25 port 5001

[ ID] Interval Transfer Bandwidth

[1912] 0.0-10.1 sec 474 MBytes 394 Mbits/sec

C:¥>iperf -c 192.168.44.25 -w 4M

------------------------------------------------------------

Client connecting to 192.168.44.25, TCP port 5001

TCP window size: 4.00 MByte

------------------------------------------------------------

[1912] local 192.168.44.77 port 3334 connected with 192.168.44.25 port 5001

[ ID] Interval Transfer Bandwidth

[1912] 0.0-10.1 sec 474 MBytes 394 Mbits/sec

e1000C:¥>iperf -c 192.168.44.75 -w 4M------------------------------------------------------------Client connecting to 192.168.44.75, TCP port 5001TCP window size: 4.00 MByte------------------------------------------------------------[1912] local 192.168.44.77 port 3318 connected with 192.168.44.75 port 5001[ ID] Interval Transfer Bandwidth[1912] 0.0-10.5 sec 73.1 MBytes 58.3 Mbits/sec

C:¥>iperf -c 192.168.44.75 -w 4M------------------------------------------------------------Client connecting to 192.168.44.75, TCP port 5001TCP window size: 4.00 MByte------------------------------------------------------------[1912] local 192.168.44.77 port 3318 connected with 192.168.44.75 port 5001[ ID] Interval Transfer Bandwidth[1912] 0.0-10.5 sec 73.1 MBytes 58.3 Mbits/sec

rtl8193

評価環境Machine: Intel DQ45CB + Core2 Quad Q8400 (2.6GHz)Host: Debian GNU/Linux (Lenny) + xen-unstable (Aug. 2010)Guest: Windows xp SP3, 1 vCPU

Page 53: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

53

QEMUの仮想デバイスを選択する(3/3)

• rtl8193とe1000の差はどこに?– 「熱に消えた?」一概には言えないが

• rtl8193を使うということCPU能力の無駄遣い

スループット制限はホストOSの機能を使うこと(tcコマンド)

• e1000ドライバを使うということQEMU由来VM用仮想NICの中では“かなりの高効率”

Windows XP SP3標準ドライバでは認識できない

Intel純正ドライバを使えば利用できる(が…)

Page 54: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

54

デバイスのエミュレーションのまとめ

オープンソース系のVMMは、デバイスエミュレーションにQEMUを使用している– x86で使用される周辺チップがソフトウェアとして実装されて

いる

– 仮想マシン内でI/Oが発生したらエミュレータが処理し

結果を返す

エミュレーションするデバイスの選び方にも注意

– パフォーマンスが高い仮想デバイス、低い仮想デバイス

Page 55: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

virtio 仮想デバイス

Page 56: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

56

virtioの概要

• virtioとは– PCIデバイスを模倣した仮想的

なデバイスを提供する– virtioは「インターフェイス」を定

義する。H/Wエミュレータ、ゲストOSに非依存

– 各デバイスは1つ1つが独立し動作

• virtio Block x2→ PCIデバイス x2• 例外あり(ドライバ実装に依存)

– 非常に高速• 仮想PCIデバイスの格好をして

いるが、実際は準仮想化的な動作をするため非常に高速

H/WエミュレータH/Wエミュレータ

仮想マシン仮想マシン

ハードウェアハードウェア

PCI BusPCI Bus

virtioBallon

virtioBallon

virtioBlock

virtioBlock

virtioBlock

virtioBlock

virtioNet

virtioNet

virtioBallon

virtioBallon

virtioBlock

virtioBlock

virtioBlock

virtioBlock

virtioNet

virtioNet

Page 57: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

57

virtioの既知デバイスタイプ

ゲストが“不要”とマークしたメモリを物理的に開放

メモリバルーンvirtio balloon5仮想コンソールvirtio console3

仮想ネットワークインターフェイスvirtio net1仮想ディスク、SCSIパススル-仮想ブロックデバイスvirtio block2

参考デバイス機能Device TypeID

ERRATA: 説明が違うと指摘がありました。ありがとうございます(2010/10/31)

いやbaloonはmalloc()しまくってみて、溢れた分をOSが従

来のキャッシュ破棄の枠組みで適切にメモリ解放してくれると祈るドライバ。必要なものも落ちるよ

http://twitter.com/kosaki55tea/status/29077390107

Page 58: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

58

virtioのリングバッファ構造

• リングバッファ– ホスト-ゲスト間のデータ交換

を行う– デバイスあたり1つ以上使用

– リングの構成(数・長さ)はバックエンドドライバが指定

• virtio共通の初期化処理(フロントエンド視点)– バックエンドドライバをプローブ

– ゲストのメモリ空間にバッファを確保

– ホスト側にバッファ位置を通知

H/WエミュレータH/Wエミュレータ

仮想マシン仮想マシン

ハードウェアハードウェア

PCI BusPCI Bus

virtioBallon

virtioBallon

virtioBlock

virtioBlock

virtioBlock

virtioBlock

virtioNet

virtioNet

virtioBalloon

virtioBalloon

virtioBlock

virtioBlock

virtioBlock

virtioBlock

virtioNet

virtioNet

Page 59: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

59

virtioのリングバッファ利用例(virtio net)

• キュー 0– 受信パケット用キュー

• キュー 1– 送信パケット用キュー

• キュー 2– ドライバ制御情報

H/WエミュレータH/Wエミュレータ

仮想マシン仮想マシン

ハードウェアハードウェア

PCI BusPCI Bus

virtio-net デバイスドライバvirtio-net デバイスドライバ

virtio-net PCIデバイスvirtio-net PCIデバイス

Queue 0 Queue 1 Queue 2

受信パケット

送信パケット

ドライバ制御情報

Page 60: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

60

ゲスト側ゲスト側

virtioのリングバッファ構造(1/2)

• キューの位置を示す2つのポインタ– ホストが最後に読み取った位置

(vring.used.idx)– データが入っている終端位置

(vring.avail.idx)– 互いに絶対追い抜いてはいけない– Lock-Free

• Guestがキューにデータを追加する– キューにデータを書き込む;– vring.avail.idx += num_bufs;

• Hostがキューからデータを読む– while (vring.used.idx <

vring.avail.idx) {キュー上のデータを処理;vring.used.idx++;

}

vring.avail.idx

vring.used.idx

データ受信側データ受信側

• Guestがキューからデータを読む

– while (last_used_idx < vring.used.idx) {

キュー上のデータを処理;

last_used_idx ++;

}

• リングの仕組みは共有コード上に実装

– 各ドライバごとの実装は不要

Page 61: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

61

virtioのリングバッファ構造(2/2)

• 従来モード– リング上にバッファのアドレス情報をおく– 1メモリ断片/1エントリ

• indirectモード– リング上にindirectテーブルのアドレス

情報をおき、実際のバッファを間接参照– 1以上のメモリ断片/1エントリ

• virtio-netの例– RX/TXのデータ構造の例

• TX(RX)パケット情報の構造体 × 1• Ethernetフレーム × 1

– リングの構造: 256エントリ/ring• 従来モード: 256 ÷ 2 = 128• indirectモード: 256 ÷ 1 = 256

indirectモードのほうが多数パケットをキューできる

従来モード(過去バージョンのvirtio互換)

indirectモード(現行virtioでサポートされる)

干し柿の写真

Page 62: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

62

virtioのリングバッファ更新通知

• Guest → Host– 通知用I/Oポートにデータを書き込

む– H/WエミュレータのI/Oポートハンド

ラをキックする

• Host → Guest– 仮想ハードウェアがIRQ割り込みを

起こす– ゲストの割り込みハンドラをキック

する

• キックの抑制– リング ディスクプリタ上にフラグを設

定した場合、相手に通知されない– VRING_USED_F_NO_NOTIFY

(G→H I/Oポートキックの抑制)– VRING_AVAIL_NO_INTERRUPT

(H→G IRQ割り込みの抑制)

H/Wエミュレータ (Host) H/Wエミュレータ (Host)

仮想マシン ( Guest) 仮想マシン ( Guest)

ハードウェアハードウェア

PCI BusPCI Bus

virtio フロントエンド デバイスドライバvirtio フロントエンド デバイスドライバ

virtio バックエンド PCIデバイスvirtio バックエンド PCIデバイス

IRQ割り込み

でキック

I/Oポートを

通してキック

Page 63: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

63

virtio-blkが遅い? - 原因を考えてみる

現状のvirtio-blkの実装は…– リングはひとつだけ使用– I/O要求、I/O結果の繰り返し

SCSI, SATAのNCQ相当が効かない?– リングは“順番に処理”が原則– Host OS, Driver, Driveのレベルで

I/O要求の並べ替えが行われない

virtio-blkはI/Oの乱発が苦手?– マルチスレッドI/Oもきっと苦手

性能より実装容易化を重視した? 今後、マルチキューサポートで改善? H/WエミュレータH/Wエミュレータ

仮想マシン仮想マシン

PCI BusPCI Bus

virtio-blk デバイスドライバvirtio-blk デバイスドライバ

virtio-blk PCIデバイスvirtio-blk PCIデバイス

Queue 0

I/O要求

I/O結果

Page 64: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

64

virtio関連ソースコードとライセンス形態

• ホスト側(バックエンド側)– QEMUソースコードを参照

– Git

• ゲスト側(フロントエンド側)– Linuxソースコードを参照

– ファンクションドライバdrivers/net/virtio-net.c

drivers/block/virtio-blk.c ほか

– 共有ソースコード

drivers/virtio/virtio_pci.c (仮想PCIデバイス)

virtio_ring.c (リングバッファ)

コードのライセンス形態

アルゴリズム(関数定義、マクロ)

アルゴリズム(関数定義、マクロ)

データ構造、定数(構造体など)

データ構造、定数(構造体など)

BSDL

GPL

Page 65: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

65

FreeBSD用virtioドライバ

$ ifconfig vn0

vn0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500

ether 52:54:00:1f:61:0e

inet 192.168.90.1 netmask 0xffffff00 broadcast 255.255.255.0

$

[root@proliant2 ~]# ifconfig vnet2

vnet2 Link encap:Ethernet HWaddr FE:54:00:1F:61:0E

inet6 addr: fe80::fc54:ff:fe1f:610e/64 Scope:Link

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:2828598448 errors:0 dropped:0 overruns:0 frame:0

TX packets:1424299907 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:500

RX bytes:4267254392920 (3.8 TiB) TX bytes:93999838700 (87.5 GiB)

Guset OS (FreeBSD) から見ると

Host OS (Linux, Fedora 14) から見ると

Page 66: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

66

FreeBSD用virtioドライバ

モチベーション

• virtioを理解するために開発中

Why on FreeBSD?

• FreeBSDなら実用価値もある?– さくらのVPS

• BSDL

現段階の実装状況

• リングバッファ(主要機能のみ)

• virtio-net

virtio-net for FreeBSD

テスト状況

• 2TiB TX, 1TiB RX以上の負荷試験

• 32bit OS未確認(AMD64にて開発)

パフォーマンス

• 1vCPU VM: TX 110Mbps

• 2vCPUs VM: TX 40Mbps

• 1vCPU VM+HW Emulation

TX 100MBps

Page 67: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

67

virtioのまとめ

PCIデバイスのふりをする仮想デバイスのフレームワーク

– メジャーなフロントエンドドライバ• ネットワーク、ディスク、シリアルコンソール

• メモリバルーン(不要メモリの解放)

– リングバッファを利用しホストOSと通信

virtioドライバを書けばLinux KVMで高効率I/Oができる– リファレンスドライバは GPL

– FreeBSD用ドライバを鋭意開発中

Page 68: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

Copyright(C) Software Research Associates, Inc. All Rights Reserved.

付録

Page 69: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

69

外部リソース集 (1/2)

• KVM - Kernel Based Virtual Machinehttp://www.linux-kvm.org/page/

• QEMUhttp://wiki.qemu.org/

• virtiohttp://www.linux-kvm.org/page/virtio

• AMD-V™ Nested Paginghttp://developer.amd.com/assets/NPT-WP-1%201-final-TM.pdf

• Intel® 64 and IA-32 Architectures Software Developer’s ManualVolume 3A, 3B

Page 70: エンジニアなら知っておきたい「仮想マシン」のしくみ (BPStudy38)

70

外部リソース集 (2/2)

– 書籍『KVM徹底入門』(翔泳社)http://www.seshop.com/product/detail/12214/

– はじめて読む486 (アスキー出版局)http://www.amazon.co.jp/dp/4756102131

– すべてわかる仮想化大全 – VMware/Virtual Server (日経BPムック)

http://www.amazon.co.jp/dp/482223410X

– 30日でできる! OS自作入門 (MYCOM)http://www.amazon.co.jp/dp/4839919844