linux kvm のコードを追いかけてみよう

260
Linux KVMのコードを 追いかけてみよう! カーネル/VM探検隊 1by Tsuyoshi Ozawa, softlab@univ. of Tsukuba. Twitter: oza_x86 1 2009813日木曜日

Upload: tsuyoshi-ozawa

Post on 10-May-2015

6.421 views

Category:

Technology


6 download

DESCRIPTION

第1回カーネル/VM探検隊 Linux KVM のコードを追いかけてみよう のスライドです。

TRANSCRIPT

Page 1: Linux KVM のコードを追いかけてみよう

Linux KVMのコードを追いかけてみよう!

カーネル/VM探検隊第1回

by Tsuyoshi Ozawa, softlab@univ. of Tsukuba.Twitter: oza_x86

12009年8月13日木曜日

Page 2: Linux KVM のコードを追いかけてみよう

本日のメニュー

22009年8月13日木曜日

Page 3: Linux KVM のコードを追いかけてみよう

1. VMMって何やってるの

2. Intel-VT

3. Linux KVMの挙動ここで発表する内容は

KVM勉強会のものと一部重複しています

32009年8月13日木曜日

Page 4: Linux KVM のコードを追いかけてみよう

VMMって何やってるの

42009年8月13日木曜日

Page 5: Linux KVM のコードを追いかけてみよう

VMM

52009年8月13日木曜日

Page 6: Linux KVM のコードを追いかけてみよう

Virtual Machine Monitor

62009年8月13日木曜日

Page 7: Linux KVM のコードを追いかけてみよう

Virtual Machine Monitor

1.実機に影響を与えないように監視

2.上で動作しているソフト(OS)に仮想的なハードウェアを提供

72009年8月13日木曜日

Page 8: Linux KVM のコードを追いかけてみよう

VMMにも

色々ある

82009年8月13日木曜日

Page 9: Linux KVM のコードを追いかけてみよう

ハードウェアを

全て物真似する方式

92009年8月13日木曜日

Page 10: Linux KVM のコードを追いかけてみよう

エミュレーション方式

102009年8月13日木曜日

Page 11: Linux KVM のコードを追いかけてみよう

代表例 Qemu

112009年8月13日木曜日

Page 12: Linux KVM のコードを追いかけてみよう

ユーザ空間で動作

122009年8月13日木曜日

Page 13: Linux KVM のコードを追いかけてみよう

ユーザモード

特権モード

132009年8月13日木曜日

Page 14: Linux KVM のコードを追いかけてみよう

特権モード

Qemu

142009年8月13日木曜日

Page 15: Linux KVM のコードを追いかけてみよう

ところで

152009年8月13日木曜日

Page 16: Linux KVM のコードを追いかけてみよう

一般的なCPUの挙動

162009年8月13日木曜日

Page 17: Linux KVM のコードを追いかけてみよう

ALU...

movl %eax %ebx...

Main Memory

172009年8月13日木曜日

Page 18: Linux KVM のコードを追いかけてみよう

ALU...

movl %eax %ebx...

Main Memory

fetch

182009年8月13日木曜日

Page 19: Linux KVM のコードを追いかけてみよう

Qemuだと...

192009年8月13日木曜日

Page 20: Linux KVM のコードを追いかけてみよう

特権モード

Qemu

ALU...

movl %eax %ebx...

Main Memory

fetch

202009年8月13日木曜日

Page 21: Linux KVM のコードを追いかけてみよう

opcode = mem[pc];execute(opcode);

擬似コード

212009年8月13日木曜日

Page 22: Linux KVM のコードを追いかけてみよう

opcode = mem[pc];execute(opcode);

擬似コードmov命令

jmp命令

222009年8月13日木曜日

Page 23: Linux KVM のコードを追いかけてみよう

欠点

•フェッチだけでコストが数倍かかる

232009年8月13日木曜日

Page 24: Linux KVM のコードを追いかけてみよう

対策

動的バイナリ変換

242009年8月13日木曜日

Page 25: Linux KVM のコードを追いかけてみよう

opcode[0..N] = mem[pc];mid_ops=compile(opcode);

execute(mid_ops);

擬似コードまとめてフェッチ

252009年8月13日木曜日

Page 26: Linux KVM のコードを追いかけてみよう

opcode[0..N] = mem[pc];mid_ops=compile(opcode);

execute(mid_ops);

擬似コードコンパイルして

262009年8月13日木曜日

Page 27: Linux KVM のコードを追いかけてみよう

opcode[0..N] = mem[pc];mid_ops=compile(opcode);

execute(mid_ops);

擬似コード一気に実行

272009年8月13日木曜日

Page 28: Linux KVM のコードを追いかけてみよう

対策

フェッチ処理が軽くなる

282009年8月13日木曜日

Page 29: Linux KVM のコードを追いかけてみよう

でも遅い

292009年8月13日木曜日

Page 30: Linux KVM のコードを追いかけてみよう

エミュレーション方式

• ユーザ空間だけで動作

• 実機の数倍のリソースを利用

• 工夫しても遅い

302009年8月13日木曜日

Page 31: Linux KVM のコードを追いかけてみよう

命令の実行

全部

エミュレーション

ではなくて

312009年8月13日木曜日

Page 32: Linux KVM のコードを追いかけてみよう

命令の実行

ほとんど

実機で実行すればいいじゃない

322009年8月13日木曜日

Page 33: Linux KVM のコードを追いかけてみよう

ほとんど実機で動く

方式のVMM

332009年8月13日木曜日

Page 34: Linux KVM のコードを追いかけてみよう

KVMはこちらの方式

342009年8月13日木曜日

Page 35: Linux KVM のコードを追いかけてみよう

ほとんど実機で実行

•実機上で命令を実行することを考えてみましょう!

352009年8月13日木曜日

Page 36: Linux KVM のコードを追いかけてみよう

サンプルプログラム.section .data message: .ascii "hello,gas!\n"

.section .text .global _start _start: movl $4,%eax movl $1,%ebx movl $message,%ecx movl $12,%edx int $0x80

362009年8月13日木曜日

Page 37: Linux KVM のコードを追いかけてみよう

このプログラムは?

./a.out

hello,gas!

372009年8月13日木曜日

Page 38: Linux KVM のコードを追いかけてみよう

このプログラムは?

いわゆるHello world

382009年8月13日木曜日

Page 39: Linux KVM のコードを追いかけてみよう

このプログラムは?

いわゆるprintf(“HelloWorld¥n”)と同等

392009年8月13日木曜日

Page 40: Linux KVM のコードを追いかけてみよう

このプログラムは?

printfは標準出力に書き込みをする

402009年8月13日木曜日

Page 41: Linux KVM のコードを追いかけてみよう

このプログラムは?

標準出力に書き込み

412009年8月13日木曜日

Page 42: Linux KVM のコードを追いかけてみよう

このプログラムは?

仮想端末に書き込み

422009年8月13日木曜日

Page 43: Linux KVM のコードを追いかけてみよう

このプログラムは?

仮想端末に対して

writeシステムコールを発行する

432009年8月13日木曜日

Page 44: Linux KVM のコードを追いかけてみよう

write システムコール

仮想端末に対して

out 命令を発行する

442009年8月13日木曜日

Page 45: Linux KVM のコードを追いかけてみよう

実行.section .data message: .ascii "hello,gas!\n"

.section .text .global _start _start: movl $4,%eax movl $1,%ebx movl $message,%ecx movl $12,%edx int $0x80

この中でout命令発効

452009年8月13日木曜日

Page 46: Linux KVM のコードを追いかけてみよう

実行

...

outb %ax

...

ここで標準出力に書き込み!

462009年8月13日木曜日

Page 47: Linux KVM のコードを追いかけてみよう

Program

CPU

実機の挙動

Display

outb472009年8月13日木曜日

Page 48: Linux KVM のコードを追いかけてみよう

実行結果

hello,gas!

482009年8月13日木曜日

Page 49: Linux KVM のコードを追いかけてみよう

命令の実行

•実機上で命令を実行することを考えてみましょう!

492009年8月13日木曜日

Page 50: Linux KVM のコードを追いかけてみよう

命令の実行

•VM上で

命令を実行することを考えてみましょう!

502009年8月13日木曜日

Page 51: Linux KVM のコードを追いかけてみよう

実行.section .data message: .ascii "hello,gas!\n"

.section .text .global _start _start: movl $4,%eax movl $1,%ebx movl $message,%ecx movl $12,%edx int $0x80

この中でout命令発効

512009年8月13日木曜日

Page 52: Linux KVM のコードを追いかけてみよう

実行

...

outb $hogehoge

...

ここで標準出力に書き込み!

522009年8月13日木曜日

Page 53: Linux KVM のコードを追いかけてみよう

実行

hello,gas!

532009年8月13日木曜日

Page 54: Linux KVM のコードを追いかけてみよう

いいえ、ここはホストOSの上です.

542009年8月13日木曜日

Page 55: Linux KVM のコードを追いかけてみよう

Program

VirtualCPU

VMの挙動

outb

VirtualDisplay

552009年8月13日木曜日

Page 56: Linux KVM のコードを追いかけてみよう

Program

VirtualCPU

VMの挙動

RealDisplay

outb562009年8月13日木曜日

Page 57: Linux KVM のコードを追いかけてみよう

実行

hello,gas!on host system?!

572009年8月13日木曜日

Page 58: Linux KVM のコードを追いかけてみよう

それはまずい

582009年8月13日木曜日

Page 59: Linux KVM のコードを追いかけてみよう

実機のステートに影響を与える命令

592009年8月13日木曜日

Page 60: Linux KVM のコードを追いかけてみよう

センシティブ命令

602009年8月13日木曜日

Page 61: Linux KVM のコードを追いかけてみよう

センシティブ命令は

どうあつかうのか

612009年8月13日木曜日

Page 62: Linux KVM のコードを追いかけてみよう

Program

仮想CPU

VM上のout 命令

VirtualDisplay

622009年8月13日木曜日

Page 63: Linux KVM のコードを追いかけてみよう

Program

仮想CPU

VM上のout 命令

outb

VirtualDisplay

632009年8月13日木曜日

Page 64: Linux KVM のコードを追いかけてみよう

VM上のout 命令

ここでトラップ発生

642009年8月13日木曜日

Page 65: Linux KVM のコードを追いかけてみよう

ホスト側の処理

trap

EmuCode

CPU

652009年8月13日木曜日

Page 66: Linux KVM のコードを追いかけてみよう

ホスト側の処理

handle

EmuCode

CPU

662009年8月13日木曜日

Page 67: Linux KVM のコードを追いかけてみよう

VM上のout 命令retEmu

Code

CPU

672009年8月13日木曜日

Page 68: Linux KVM のコードを追いかけてみよう

Program

仮想CPU

VM上のout 命令

VirtualDisplay

ack

682009年8月13日木曜日

Page 69: Linux KVM のコードを追いかけてみよう

VM上のout 命令

あたかも

out命令を行ったかのようにメモリを書き換える

692009年8月13日木曜日

Page 70: Linux KVM のコードを追いかけてみよう

必要な箇所だけエミュレーション方式

702009年8月13日木曜日

Page 71: Linux KVM のコードを追いかけてみよう

ところが

712009年8月13日木曜日

Page 72: Linux KVM のコードを追いかけてみよう

x86はそんなに甘くない

722009年8月13日木曜日

Page 73: Linux KVM のコードを追いかけてみよう

古典的な「仮想化可能」とは?

センシティブ命令

特権命令

すべての命令

732009年8月13日木曜日

Page 74: Linux KVM のコードを追いかけてみよう

という包含関係が

成立

742009年8月13日木曜日

Page 75: Linux KVM のコードを追いかけてみよう

なぜ?

752009年8月13日木曜日

Page 76: Linux KVM のコードを追いかけてみよう

古典的な「仮想化可能」とは?

センシティブ命令

特権命令

すべての命令

権限がない状態で起動すればセンシティブ命令をトラップできる!

762009年8月13日木曜日

Page 77: Linux KVM のコードを追いかけてみよう

ところがどっこい

772009年8月13日木曜日

Page 78: Linux KVM のコードを追いかけてみよう

x86は仮想化可能?

センシティブ命令

特権命令

すべての命令

782009年8月13日木曜日

Page 79: Linux KVM のコードを追いかけてみよう

あれ...不可能?

792009年8月13日木曜日

Page 80: Linux KVM のコードを追いかけてみよう

頑張れば不可能なんてない

802009年8月13日木曜日

Page 81: Linux KVM のコードを追いかけてみよう

センシティブ命令をなんとかする

812009年8月13日木曜日

Page 82: Linux KVM のコードを追いかけてみよう

x86の仮想化

•手で明記的に書き換える

• Hypervisor Call

• Xenのアプローチ

822009年8月13日木曜日

Page 83: Linux KVM のコードを追いかけてみよう

x86の仮想化

•コンパイル時に自動で書き換える

• LilyVMのアプローチ

832009年8月13日木曜日

Page 84: Linux KVM のコードを追いかけてみよう

x86の仮想化

•実行時に自動で書き換える

• 動的バイナリ変換 (JITみたいなもの)

• VMWareのアプローチ

842009年8月13日木曜日

Page 85: Linux KVM のコードを追いかけてみよう

でも大変

852009年8月13日木曜日

Page 86: Linux KVM のコードを追いかけてみよう

Intel、なんとかして

(ホントはAMD-Vの方が早く出てました)

862009年8月13日木曜日

Page 87: Linux KVM のコードを追いかけてみよう

Intel-VTの登場872009年8月13日木曜日

Page 88: Linux KVM のコードを追いかけてみよう

ところで

仮想化にとって理想のCPUとは?

882009年8月13日木曜日

Page 89: Linux KVM のコードを追いかけてみよう

ホスト側

User

Privilege

892009年8月13日木曜日

Page 90: Linux KVM のコードを追いかけてみよう

ゲスト側

User

Privilege

902009年8月13日木曜日

Page 91: Linux KVM のコードを追いかけてみよう

自由に行き来できる

912009年8月13日木曜日

Page 92: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilegewarp

922009年8月13日木曜日

Page 93: Linux KVM のコードを追いかけてみよう

センシティブ命令をトラップできる

932009年8月13日木曜日

Page 94: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilege

942009年8月13日木曜日

Page 95: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilege

センシティブ命令

952009年8月13日木曜日

Page 96: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilegetrap

962009年8月13日木曜日

Page 97: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilege

これがIntel-VT972009年8月13日木曜日

Page 98: Linux KVM のコードを追いかけてみよう

User

Privilege

こちら側

982009年8月13日木曜日

Page 99: Linux KVM のコードを追いかけてみよう

VMX-Root Mode(VM特権モード)

992009年8月13日木曜日

Page 100: Linux KVM のコードを追いかけてみよう

User

Privilege

こちら側

1002009年8月13日木曜日

Page 101: Linux KVM のコードを追いかけてみよう

VMX-non root Mode(ゲストモード)

1012009年8月13日木曜日

Page 102: Linux KVM のコードを追いかけてみよう

VMX non Root Modeに

なるための命令

1022009年8月13日木曜日

Page 103: Linux KVM のコードを追いかけてみよう

User

Privilege

User

Privilege

コレ

1032009年8月13日木曜日

Page 104: Linux KVM のコードを追いかけてみよう

vmlaunchvmresume

1042009年8月13日木曜日

Page 105: Linux KVM のコードを追いかけてみよう

ここからようやくKVMの話

1052009年8月13日木曜日

Page 106: Linux KVM のコードを追いかけてみよう

KVMとは

1062009年8月13日木曜日

Page 107: Linux KVM のコードを追いかけてみよう

Kernel-basedVirtul Machine

1072009年8月13日木曜日

Page 108: Linux KVM のコードを追いかけてみよう

略してKVM

1082009年8月13日木曜日

Page 109: Linux KVM のコードを追いかけてみよう

KVM•例外の発生•エミュレーション•ブート•デバイスドライバ

•Intel-VTにお任せ•Qemuにお任せ•Linuxにお任せ•Linuxにお任せ

1092009年8月13日木曜日

Page 110: Linux KVM のコードを追いかけてみよう

KVM•例外の発生•エミュレーション•ブート•デバイスドライバ

•Intel-VTにお任せ•Qemuにお任せ•Linuxにお任せ•Linuxにお任せ

KVMは何やってるの1102009年8月13日木曜日

Page 111: Linux KVM のコードを追いかけてみよう

KVMが行っていること

•初期化•VMインスタンスの立ち上げ•割り込み管理•エミュレーションのルーティング•ユーザ空間とカーネル空間のやりとり•ゲストOSのメモリ管理

1112009年8月13日木曜日

Page 112: Linux KVM のコードを追いかけてみよう

やること意外と多い

1122009年8月13日木曜日

Page 113: Linux KVM のコードを追いかけてみよう

やること全部追うのは厳しい

1132009年8月13日木曜日

Page 114: Linux KVM のコードを追いかけてみよう

Main loopを理解してわかった気になろう

1142009年8月13日木曜日

Page 115: Linux KVM のコードを追いかけてみよう

KVMの概要

1152009年8月13日木曜日

Page 116: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1162009年8月13日木曜日

Page 117: Linux KVM のコードを追いかけてみよう

見方

1172009年8月13日木曜日

Page 118: Linux KVM のコードを追いかけてみよう

VMXRoot Mode

VMXnon Root

Mode

1182009年8月13日木曜日

Page 119: Linux KVM のコードを追いかけてみよう

ユーザモード

特権モード

1192009年8月13日木曜日

Page 120: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1202009年8月13日木曜日

Page 121: Linux KVM のコードを追いかけてみよう

起動からVMX non Root Modeになるまで

1212009年8月13日木曜日

Page 122: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1222009年8月13日木曜日

Page 123: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

KVMのブートはQemuを起動することで

生じる

1232009年8月13日木曜日

Page 124: Linux KVM のコードを追いかけてみよう

./qemu -hda disk1.img

(-hda は起動ディスクを指定するオプション)

1242009年8月13日木曜日

Page 125: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

$ ./qemu -hda disk1

1252009年8月13日木曜日

Page 126: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

Qemuの初期化を行う

1262009年8月13日木曜日

Page 127: Linux KVM のコードを追いかけてみよう

Qemuの初期化が終わったら

1272009年8月13日木曜日

Page 128: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1282009年8月13日木曜日

Page 129: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1292009年8月13日木曜日

Page 130: Linux KVM のコードを追いかけてみよう

特権モードに切り替え

1302009年8月13日木曜日

Page 131: Linux KVM のコードを追いかけてみよう

なぜか

1312009年8月13日木曜日

Page 132: Linux KVM のコードを追いかけてみよう

vmlaunchvmresumeは

特権命令

1322009年8月13日木曜日

Page 133: Linux KVM のコードを追いかけてみよう

次に、VMX non Root

Modeになる準備をする

1332009年8月13日木曜日

Page 134: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel VTを使って

モード遷移をする準備

1342009年8月13日木曜日

Page 135: Linux KVM のコードを追いかけてみよう

準備ができたら

1352009年8月13日木曜日

Page 136: Linux KVM のコードを追いかけてみよう

vmlaunchvmresumeを発行

1362009年8月13日木曜日

Page 137: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

1372009年8月13日木曜日

Page 138: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1382009年8月13日木曜日

Page 139: Linux KVM のコードを追いかけてみよう

無事にVMX non root Mode に

なりました

1392009年8月13日木曜日

Page 140: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1402009年8月13日木曜日

Page 141: Linux KVM のコードを追いかけてみよう

1412009年8月13日木曜日

Page 142: Linux KVM のコードを追いかけてみよう

VMX non Root Modeから

IOのハンドリングまでを追ってみます

1422009年8月13日木曜日

Page 143: Linux KVM のコードを追いかけてみよう

そうこうしているうちに

1432009年8月13日木曜日

Page 144: Linux KVM のコードを追いかけてみよう

outb %ax が発生したと仮定

1442009年8月13日木曜日

Page 145: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1452009年8月13日木曜日

Page 146: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax1462009年8月13日木曜日

Page 147: Linux KVM のコードを追いかけてみよう

処理がVMX Root Modeに

移る

1472009年8月13日木曜日

Page 148: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1482009年8月13日木曜日

Page 149: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

ゲストから処理が渡されたのか特定

1492009年8月13日木曜日

Page 150: Linux KVM のコードを追いかけてみよう

エミュレーションの場合は

1502009年8月13日木曜日

Page 151: Linux KVM のコードを追いかけてみよう

Qemuの助けが必要

1512009年8月13日木曜日

Page 152: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

1522009年8月13日木曜日

Page 153: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1532009年8月13日木曜日

Page 154: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

どのハードウェアにio命令が来たか

判断

1542009年8月13日木曜日

Page 155: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

1552009年8月13日木曜日

Page 156: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

1562009年8月13日木曜日

Page 157: Linux KVM のコードを追いかけてみよう

エミュレーションが終了したら

1572009年8月13日木曜日

Page 158: Linux KVM のコードを追いかけてみよう

再度IOCTLを発行して

CPUをゲストに渡す

1582009年8月13日木曜日

Page 159: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1592009年8月13日木曜日

Page 160: Linux KVM のコードを追いかけてみよう

以下略

1602009年8月13日木曜日

Page 161: Linux KVM のコードを追いかけてみよう

まとめると...

1612009年8月13日木曜日

Page 162: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

vmlaunch vmresume

センシティブ命令

1622009年8月13日木曜日

Page 163: Linux KVM のコードを追いかけてみよう

これがおおざっぱなメインループ

1632009年8月13日木曜日

Page 164: Linux KVM のコードを追いかけてみよう

このフローをコードレベルで追ってみよう

1642009年8月13日木曜日

Page 165: Linux KVM のコードを追いかけてみよう

今回追いかけるKVMのバージョン

kvm-85

1652009年8月13日木曜日

Page 166: Linux KVM のコードを追いかけてみよう

まずは

1662009年8月13日木曜日

Page 167: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1672009年8月13日木曜日

Page 168: Linux KVM のコードを追いかけてみよう

Qemu起動するところ

1682009年8月13日木曜日

Page 169: Linux KVM のコードを追いかけてみよう

$./qemu -hda disk1とすると...

1692009年8月13日木曜日

Page 170: Linux KVM のコードを追いかけてみよう

qemu/vl.cのmain.c

に処理がとぶ

1702009年8月13日木曜日

Page 171: Linux KVM のコードを追いかけてみよう

4439 int main(int argc, char **argv, char **envp)

4440 { // 初期化. Shadow page table の作成.5425 kvm_qemu_create_context() // 構造体のメモリ確保など5493 kvm_init(smp_cpus); ...

// qemu/hw/pc.c 実はここが本体5554 machine->init(ram_size, vga_ram_size, boot_devices,5555 kernel_filename, kernel_cmdline,5556 initrd_filename, cpu_model); ...

...5742 main_loop(); ...5747 }

1712009年8月13日木曜日

Page 172: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1722009年8月13日木曜日

Page 173: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

Qemuの初期化を行う

1732009年8月13日木曜日

Page 174: Linux KVM のコードを追いかけてみよう

起動 - 初期化

•machine->init•各種仮想ハードウェアの初期化•本体はqemu/hw/pc.cのpc_init1という関数

1742009年8月13日木曜日

Page 175: Linux KVM のコードを追いかけてみよう

この辺り、追いかけると煩雑

1752009年8月13日木曜日

Page 176: Linux KVM のコードを追いかけてみよう

初期化のコールグラフ

1762009年8月13日木曜日

Page 177: Linux KVM のコードを追いかけてみよう

pc_init1pc_new_cpu

cpu_init = cpu_x86_initkvm_init_cpu

pthread_createap_main_loop

kvm_main_loop_cpu1772009年8月13日木曜日

Page 178: Linux KVM のコードを追いかけてみよう

初期化が終わったら

1782009年8月13日木曜日

Page 179: Linux KVM のコードを追いかけてみよう

カーネルに処理を渡すんでした

1792009年8月13日木曜日

Page 180: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1802009年8月13日木曜日

Page 181: Linux KVM のコードを追いかけてみよう

橋渡しはIOCTL

システムコール

1812009年8月13日木曜日

Page 182: Linux KVM のコードを追いかけてみよう

さきほどの続きを追うと...

qemu/kvm-all.ckvm_cpu_exec

1822009年8月13日木曜日

Page 183: Linux KVM のコードを追いかけてみよう

378 static int kvm_main_loop_cpu(CPUState *env)

379 {

394 while (1) { 395 while (!has_work(env)) 396 kvm_main_loop_wait(env, 1000); 397 if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) 398 env->halted = 0; // ここで割り込み処理を行う.

.... 404 } 405 if (!env->halted && !env->kvm_cpu_state.init) {

406 kvm_cpu_exec(env); // ここが本体

} } 413 }

1832009年8月13日木曜日

Page 184: Linux KVM のコードを追いかけてみよう

int kvm_cpu_exec(){ ...

461 ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);

478 switch (run->exit_reason) {479 case KVM_EXIT_IO:481 ret = kvm_handle_io(env, run->io.port,482 (uint8_t *)run + run>io.data_offset,483 run->io.direction,484 run->io.size,485 run->io.count);486 break; case KVM_EXIT_MMIO: .... 続く ...

1842009年8月13日木曜日

Page 185: Linux KVM のコードを追いかけてみよう

648 int kvm_vcpu_ioctl(CPUState *env, int type, ...)649 {

658 ret = ioctl(env->kvm_fd, type, arg);659 if (ret == -1)660 ret = -errno;661 662 return ret;663 }

1852009年8月13日木曜日

Page 186: Linux KVM のコードを追いかけてみよう

あった!

1862009年8月13日木曜日

Page 187: Linux KVM のコードを追いかけてみよう

IOCTLを発行すると

1872009年8月13日木曜日

Page 188: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1882009年8月13日木曜日

Page 189: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1892009年8月13日木曜日

Page 190: Linux KVM のコードを追いかけてみよう

特権モードに切り替わる

1902009年8月13日木曜日

Page 191: Linux KVM のコードを追いかけてみよう

行き先はどこか

1912009年8月13日木曜日

Page 192: Linux KVM のコードを追いかけてみよう

IOCTLのハンドラ

1922009年8月13日木曜日

Page 193: Linux KVM のコードを追いかけてみよう

IOCTLのハンドラは

いつ登録するの?

1932009年8月13日木曜日

Page 194: Linux KVM のコードを追いかけてみよう

初期化時に登録する

1942009年8月13日木曜日

Page 195: Linux KVM のコードを追いかけてみよう

static struct file_operations kvm_vcpu_fops = {

.release = kvm_vcpu_release,

.unlocked_ioctl = kvm_vcpu_ioctl,

.compat_ioctl = kvm_vcpu_ioctl,

.mmap = kvm_vcpu_mmap,

};

1952009年8月13日木曜日

Page 196: Linux KVM のコードを追いかけてみよう

// カーネルモジュール読み込み時

file->f_op = kvm_vcpu_fops;

1962009年8月13日木曜日

Page 197: Linux KVM のコードを追いかけてみよう

kvm_vcpu_ioctl に

処理が移る

1972009年8月13日木曜日

Page 198: Linux KVM のコードを追いかけてみよう

static long kvm_vcpu_ioctl(struct file *filp,

unsigned int ioctl, unsigned long arg)

{

switch (ioctl) {

case KVM_RUN:

r = kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run);

break;

....

}

1982009年8月13日木曜日

Page 199: Linux KVM のコードを追いかけてみよう

ここではVMX non Root Modeになる準備を行う

1992009年8月13日木曜日

Page 200: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel VTを使って

モード遷移をする準備

2002009年8月13日木曜日

Page 201: Linux KVM のコードを追いかけてみよう

色々準備しているところをまとめると...

2012009年8月13日木曜日

Page 202: Linux KVM のコードを追いかけてみよう

kvm_arch_vcpu_ioctl_run

__vcpu_run

vcpu_enter_guest

vmx_vcpu_run

コールグラフ

2022009年8月13日木曜日

Page 203: Linux KVM のコードを追いかけてみよう

vmx_vcpu_runkernel/x86/vmx.c

2032009年8月13日木曜日

Page 204: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

2042009年8月13日木曜日

Page 205: Linux KVM のコードを追いかけてみよう

を発行するところ

2052009年8月13日木曜日

Page 206: Linux KVM のコードを追いかけてみよう

コード読んでみましょう

2062009年8月13日木曜日

Page 207: Linux KVM のコードを追いかけてみよう

include/asm-x86/vmx.h

#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2"

#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3"

2072009年8月13日木曜日

Page 208: Linux KVM のコードを追いかけてみよう

命令を

バイナリ直打ち

2082009年8月13日木曜日

Page 209: Linux KVM のコードを追いかけてみよう

vmlaunch/vmresumeを発行すると

2092009年8月13日木曜日

Page 210: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

2102009年8月13日木曜日

Page 211: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2112009年8月13日木曜日

Page 212: Linux KVM のコードを追いかけてみよう

無事VMX non-root modeに突入しました

2122009年8月13日木曜日

Page 213: Linux KVM のコードを追いかけてみよう

さて折り返し

2132009年8月13日木曜日

Page 214: Linux KVM のコードを追いかけてみよう

VMX non Root Modeから

IOのハンドリングまで

2142009年8月13日木曜日

Page 215: Linux KVM のコードを追いかけてみよう

追います

2152009年8月13日木曜日

Page 216: Linux KVM のコードを追いかけてみよう

そうこうしているうちに

2162009年8月13日木曜日

Page 217: Linux KVM のコードを追いかけてみよう

outb %ax が発生したと仮定

2172009年8月13日木曜日

Page 218: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2182009年8月13日木曜日

Page 219: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax2192009年8月13日木曜日

Page 220: Linux KVM のコードを追いかけてみよう

どこから再開するのか

2202009年8月13日木曜日

Page 221: Linux KVM のコードを追いかけてみよう

"jne .Llaunched \n\t" __ex(ASM_VMX_VMLAUNCH) "\n\t" "jmp .Lkvm_vmx_return \n\t" ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"

".Lkvm_vmx_return: "

/* レジスタの復帰 */

...

vmlaunchvmresumeの...

2212009年8月13日木曜日

Page 222: Linux KVM のコードを追いかけてみよう

"jne .Llaunched \n\t" __ex(ASM_VMX_VMLAUNCH) "\n\t" "jmp .Lkvm_vmx_return \n\t" ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"

".Lkvm_vmx_return: "

/* レジスタの復帰 */

...

次の命令

2222009年8月13日木曜日

Page 223: Linux KVM のコードを追いかけてみよう

次の命令から再開はいいけど

2232009年8月13日木曜日

Page 224: Linux KVM のコードを追いかけてみよう

これから何するの?

2242009年8月13日木曜日

Page 225: Linux KVM のコードを追いかけてみよう

out命令のエミュレーション

2252009年8月13日木曜日

Page 226: Linux KVM のコードを追いかけてみよう

なぜ out 命令のエミュレーションと特定できるのか?

in 命令かもしれないじゃん.

2262009年8月13日木曜日

Page 227: Linux KVM のコードを追いかけてみよう

Intel-VTの機能でモード遷移の原因がわかる

2272009年8月13日木曜日

Page 228: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

ゲストから処理が渡されたのか特定

2282009年8月13日木曜日

Page 229: Linux KVM のコードを追いかけてみよう

エミュレーションの場合は

2292009年8月13日木曜日

Page 230: Linux KVM のコードを追いかけてみよう

Qemuの助けが必要

2302009年8月13日木曜日

Page 231: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

2312009年8月13日木曜日

Page 232: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2322009年8月13日木曜日

Page 233: Linux KVM のコードを追いかけてみよう

int kvm_cpu_exec(){ ...461 ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);

478 switch (run->exit_reason) { 479 case KVM_EXIT_IO:481 ret = kvm_handle_io(env, run->io.port,482 (uint8_t *)run + run>io.data_offset,483 run->io.direction,484 run->io.size,485 run->io.count);486 break; case KVM_EXIT_MMIO: .... 続く ...

ここにもどってくる

2332009年8月13日木曜日

Page 234: Linux KVM のコードを追いかけてみよう

outbを処理中なので

2342009年8月13日木曜日

Page 235: Linux KVM のコードを追いかけてみよう

int kvm_cpu_exec(){ ...

// ここに戻ってくる461 ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);

478 switch (run->exit_reason) { 479 case KVM_EXIT_IO:481 ret = kvm_handle_io(env, run->io.port,482 (uint8_t *)run + run>io.data_offset,483 run->io.direction,484 run->io.size,485 run->io.count);486 break; case KVM_EXIT_MMIO: .... 続く ...

outbが発生したのでここにくる

2352009年8月13日木曜日

Page 236: Linux KVM のコードを追いかけてみよう

次にすることは

2362009年8月13日木曜日

Page 237: Linux KVM のコードを追いかけてみよう

どの仮想ハードウェアに対する

IOなのかを判断する

2372009年8月13日木曜日

Page 238: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

どのハードウェアにio命令が来たか

判断

2382009年8月13日木曜日

Page 239: Linux KVM のコードを追いかけてみよう

どうするか

2392009年8月13日木曜日

Page 240: Linux KVM のコードを追いかけてみよう

out命令のオペランドで

判断

2402009年8月13日木曜日

Page 241: Linux KVM のコードを追いかけてみよう

outb %al

2412009年8月13日木曜日

Page 242: Linux KVM のコードを追いかけてみよう

outb %al

ポート番号が入っている

2422009年8月13日木曜日

Page 243: Linux KVM のコードを追いかけてみよう

ポート番号で

ルーティング(実機と同じ判断方法!)

2432009年8月13日木曜日

Page 244: Linux KVM のコードを追いかけてみよう

int kvm_cpu_exec(){ ...

// ここに戻ってくる461 ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);

478 switch (run->exit_reason) { 479 case KVM_EXIT_IO:481 ret = kvm_handle_io(env, run->io.port,482 (uint8_t *)run + run>io.data_offset,483 run->io.direction,484 run->io.size,485 run->io.count);486 break; case KVM_EXIT_MMIO: .... 続く ... 引数に注目

2442009年8月13日木曜日

Page 245: Linux KVM のコードを追いかけてみよう

kvm_handle_iocpu_outb

ioport_write

2452009年8月13日木曜日

Page 246: Linux KVM のコードを追いかけてみよう

static void ioport_write(int index, uint32_t address, uint32_t data){ static IOPortWriteFunc *default_func[3] = { default_ioport_writeb, default_ioport_writew, default_ioport_writel }; IOPortWriteFunc *func = ioport_write_table[index][address]; if (!func) func = default_func[index]; func(ioport_opaque[address], address, data);}

ioport_write_tableは関数ポインタのテーブル

2462009年8月13日木曜日

Page 247: Linux KVM のコードを追いかけてみよう

デバイスによって処理を分岐できる(実機と同じルーティング方法)

2472009年8月13日木曜日

Page 248: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

どのハードウェアにio命令が来たか

判断

2482009年8月13日木曜日

Page 249: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

2492009年8月13日木曜日

Page 250: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

2502009年8月13日木曜日

Page 251: Linux KVM のコードを追いかけてみよう

エミュレーションが終了したら

2512009年8月13日木曜日

Page 252: Linux KVM のコードを追いかけてみよう

再度IOCTLを発行して

CPUをゲストに渡す

2522009年8月13日木曜日

Page 253: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

2532009年8月13日木曜日

Page 254: Linux KVM のコードを追いかけてみよう

以下略

2542009年8月13日木曜日

Page 255: Linux KVM のコードを追いかけてみよう

まとめると...

2552009年8月13日木曜日

Page 256: Linux KVM のコードを追いかけてみよう

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

vmlaunch vmresume

センシティブ命令

2562009年8月13日木曜日

Page 257: Linux KVM のコードを追いかけてみよう

コードレベルだと

2572009年8月13日木曜日

Page 258: Linux KVM のコードを追いかけてみよう

378 static int kvm_main_loop_cpu(CPUState *env) 379 {

394 while (1) { 395 while (!has_work(env)) 396 kvm_main_loop_wait(env, 1000); 397 if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) 398 env->halted = 0; // ここで割り込み処理を行う.

.... 404 } 405 if (!env->halted && !env->kvm_cpu_state.init) {

406 kvm_cpu_exec(env); // ここが本体

} } 413 }

2582009年8月13日木曜日

Page 259: Linux KVM のコードを追いかけてみよう

これがおおざっぱなメインループをコードレベルで追った結果だよ!

2592009年8月13日木曜日

Page 260: Linux KVM のコードを追いかけてみよう

誤りのご指摘ご不明な点があれば

Twitterでお願いします

2602009年8月13日木曜日