136
KVM読書会 第二回 Tsuyoshi Ozawa @ Univ. of Tsukuba Twitter oza_x86 2009830日日曜日

第二回KVM読書会

Embed Size (px)

DESCRIPTION

第二回KVM読書会のスライドです. Intel-VT と Linux KVM の概要についてまとめました.

Citation preview

Page 1: 第二回KVM読書会

KVM読書会第二回

Tsuyoshi Ozawa @ Univ. of TsukubaTwitter oza_x86

2009年8月30日日曜日

Page 2: 第二回KVM読書会

本日の内容1. Intel-VTの概要2. KVMの概要(その2)

2009年8月30日日曜日

Page 3: 第二回KVM読書会

Intel-VTの概要

2009年8月30日日曜日

Page 4: 第二回KVM読書会

プロテクションモデル

2009年8月30日日曜日

Page 5: 第二回KVM読書会

リングプロテクションでIntel-VT

1.仮想化の支援機構2.VMを簡単に実装するための CPUの機能

x86の保護モデルと密接な関係がある

2009年8月30日日曜日

Page 6: 第二回KVM読書会

x86の保護モデル(リングプロテクション)

数字が低いほど特権レベルが高い( 0 が最強 )

OSはRing 0 で動作

ユーザプログラムはRing3で動く

OSの機能を使いたいときは儀式を行う

Kernel Mode

Ring3 = User Mode

Ring2

Ring1

Ring0

2009年8月30日日曜日

Page 7: 第二回KVM読書会

リングプロテクションで保護されているもの

1.命令の発行2.メモリのアクセス

2009年8月30日日曜日

Page 8: 第二回KVM読書会

Ring3 から Ring0 へのアクセス

Kernel Mode

Ring3

Ring2

Ring1

Ring0

User Mode

2009年8月30日日曜日

Page 9: 第二回KVM読書会

Kernel Mode

Ring3

Ring2

Ring1

Ring0

ここで out 命令

User Mode

Ring3 から Ring0 へのアクセス

2009年8月30日日曜日

Page 10: 第二回KVM読書会

Kernel Mode

Ring3

Ring2

Ring1

Ring0

ここで out 命令

User Mode

Ring3 から Ring0 へのアクセス

ダメ!(例外を発生)

2009年8月30日日曜日

Page 11: 第二回KVM読書会

Kernel Mode

Ring3 = User Mode

Ring2

Ring1

Ring0

ここで out 命令

Ring3 から Ring0 へのアクセス

例外に対応した例外ハンドラが動作する

2009年8月30日日曜日

Page 12: 第二回KVM読書会

「VMが動作する」とは?

仮想的なCPU、メモリ、マザーボード etc...

がたくさんある

2009年8月30日日曜日

Page 13: 第二回KVM読書会

「VMが動作する」とは?

Kernel Mode

Kernel Mode

実機 仮想CPU

2009年8月30日日曜日

Page 14: 第二回KVM読書会

どうやって実装するの?

2009年8月30日日曜日

Page 15: 第二回KVM読書会

Xen や VMWare のモデル

HyperVisor

Ring3

Ring2

Ring1

Ring0

OSを書き換える

Ring1 = Guest Kerel

2009年8月30日日曜日

Page 16: 第二回KVM読書会

Xen や VMWare のモデル

Kernel Mode

Kernel Mode

Hypervirsor on 実機 Guest kernel on 仮想CPU

実は Ring 1Ring 1 とRing 2 は通常使われない

2009年8月30日日曜日

Page 17: 第二回KVM読書会

Intel-VT がやっていることも

同じ

2009年8月30日日曜日

Page 18: 第二回KVM読書会

Intel-VT の概要

Kernel Mode

Hypervirsor on 実機 Guest kernel on 仮想CPU

Kernel Mode

2009年8月30日日曜日

Page 19: 第二回KVM読書会

Intel-VT の概要

Kernel Mode

Hypervirsor on 実機 Guest kernel on 仮想CPU

実は Guest OS 専用モード

Kernel Mode

2009年8月30日日曜日

Page 20: 第二回KVM読書会

Intel-VT の概要

Kernel Mode

Hypervirsor on 実機 Guest kernel on 仮想CPU

あるCPUステートじゃないとダメ.

Kernel Mode

2009年8月30日日曜日

Page 21: 第二回KVM読書会

Intel-VTの用語

Hypervirsor on 実機 Guest kernel on 仮想CPU

VMX Root Mode

Kernel Mode

Kernel Mode

2009年8月30日日曜日

Page 22: 第二回KVM読書会

VMX Root Mode になるための命令

Hypervirsor on 実機

VMXON初期化命令.

A20信号線を無効にするVT用の命令が発効できるようになる

Kernel Mode

2009年8月30日日曜日

Page 23: 第二回KVM読書会

VMX Root Mode から戻る命令

Hypervirsor on 実機

VMXOFFVT終了命令.

VT周りの命令が使えなくなる

Kernel Mode

2009年8月30日日曜日

Page 24: 第二回KVM読書会

Intel-VTの用語

Hypervirsor on 実機 Guest kernel on 仮想CPU

VMX non Root Mode

Kernel Mode

Kernel Mode

2009年8月30日日曜日

Page 25: 第二回KVM読書会

Intel-VTの用語

Hypervirsor on 実機 Guest kernel on 仮想CPU

VMX non Root Mode

VMEntry

Kernel Mode

Kernel Mode

2009年8月30日日曜日

Page 26: 第二回KVM読書会

VMEntry を発生させる命令

VMLAUNCHVMRESUME

VMX non Root Modeに移行する

2009年8月30日日曜日

Page 27: 第二回KVM読書会

Intel-VTの用語

Hypervirsor on 実機 Guest kernel on 仮想CPU

VMExit

Kernel Mode

Kernel Mode

2009年8月30日日曜日

Page 28: 第二回KVM読書会

VMExit を発生させる命令

VMMCALL+その他例外

VMX non Root Modeに移行する

2009年8月30日日曜日

Page 29: 第二回KVM読書会

その他例外について

•設定に沿った例外を生じる.RDTSC (時間を読み取る)を発行しただけで例外を発生させるように設定することも可能

•「設定」を保存する場所

VMCS構造体

2009年8月30日日曜日

Page 30: 第二回KVM読書会

VMCSのイメージ

Hypervirsor on 実機

Memory

VMCS

Kernel Mode

2009年8月30日日曜日

Page 31: 第二回KVM読書会

VMCS構造体とは

Virtual Machine Control Structure

4KB の構造体命令でメモリアドレスをセットする

2009年8月30日日曜日

Page 32: 第二回KVM読書会

VMCS構造体とは

•Virtual Machine Control Structure

•4KB の構造体•保存するもの 例外の引き起こす命令の設定 プログラムカウンタの値 各種レジスタの値 VMのメモリ開始位置 etc...

2009年8月30日日曜日

Page 33: 第二回KVM読書会

VMCSを設定する命令

Current VMCSを設定

VMPTRST

2009年8月30日日曜日

Page 34: 第二回KVM読書会

Kernel Mode

VMPTRSTのイメージ

Hypervirsor on 実機

Memory

VMCSここがVMCSだよ!

2009年8月30日日曜日

Page 35: 第二回KVM読書会

Current VMCSをロードする命令

Current VMCSのアドレスを取得

VMPTRLD

2009年8月30日日曜日

Page 36: 第二回KVM読書会

Kernel Mode

VMPTRSTのイメージ

Hypervirsor on 実機

Memory

VMCSこの番地にCurrent VMCSあるよ

2009年8月30日日曜日

Page 37: 第二回KVM読書会

VMCLEAR

VMCSを初期化する

2009年8月30日日曜日

Page 38: 第二回KVM読書会

Kernel Mode

VMCLEARのイメージ

Hypervirsor on 実機

Memory

VMCS初期化して!

2009年8月30日日曜日

Page 39: 第二回KVM読書会

VMCSを読み書き

VMREAD/VMWRITE

2009年8月30日日曜日

Page 40: 第二回KVM読書会

Kernel Mode

VMWRITEのイメージ

Hypervirsor on 実機

Memory

VMCSココの値はこうして!

2009年8月30日日曜日

Page 41: 第二回KVM読書会

Kernel Mode

VMREADのイメージ

Hypervirsor on 実機

Memory

VMCSココの値はこうだよ!

2009年8月30日日曜日

Page 42: 第二回KVM読書会

詳細はIntelのマニュアル(英語版)参照

2009年8月30日日曜日

Page 43: 第二回KVM読書会

KVMの概要

2009年8月30日日曜日

Page 44: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 45: 第二回KVM読書会

見方

2009年8月30日日曜日

Page 46: 第二回KVM読書会

VMXRoot Mode

VMXNonRoot

Mode

2009年8月30日日曜日

Page 47: 第二回KVM読書会

ユーザモード

特権モード

2009年8月30日日曜日

Page 48: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 49: 第二回KVM読書会

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

2009年8月30日日曜日

Page 50: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 51: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

生じる

2009年8月30日日曜日

Page 52: 第二回KVM読書会

./qemu -hda disk1.img

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

2009年8月30日日曜日

Page 53: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

$ ./qemu -hda disk1

2009年8月30日日曜日

Page 54: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

Qemuの初期化を行う

2009年8月30日日曜日

Page 55: 第二回KVM読書会

Qemuの初期化が終わったら

2009年8月30日日曜日

Page 56: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

2009年8月30日日曜日

Page 57: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 58: 第二回KVM読書会

特権モードに切り替え

2009年8月30日日曜日

Page 59: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel VTを使って

モード遷移をする準備

2009年8月30日日曜日

Page 60: 第二回KVM読書会

VMX non Root Modeに

なるための命令

2009年8月30日日曜日

Page 61: 第二回KVM読書会

vmlaunchvmresume

2009年8月30日日曜日

Page 62: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

2009年8月30日日曜日

Page 63: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 64: 第二回KVM読書会

無事にVMX non root Mode に

なりました

2009年8月30日日曜日

Page 65: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 66: 第二回KVM読書会

2009年8月30日日曜日

Page 67: 第二回KVM読書会

VMX non Root Modeから

IOのハンドリングまで

2009年8月30日日曜日

Page 68: 第二回KVM読書会

そうこうしているうちに

2009年8月30日日曜日

Page 69: 第二回KVM読書会

outb %ax が発生したと仮定

2009年8月30日日曜日

Page 70: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 71: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax2009年8月30日日曜日

Page 72: 第二回KVM読書会

処理がVMX Root Modeに

移る

2009年8月30日日曜日

Page 73: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 74: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

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

2009年8月30日日曜日

Page 75: 第二回KVM読書会

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

2009年8月30日日曜日

Page 76: 第二回KVM読書会

Qemuの助けが必要

2009年8月30日日曜日

Page 77: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

2009年8月30日日曜日

Page 78: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 79: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

2009年8月30日日曜日

Page 80: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

2009年8月30日日曜日

Page 81: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

2009年8月30日日曜日

Page 82: 第二回KVM読書会

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

2009年8月30日日曜日

Page 83: 第二回KVM読書会

再度IOCTLを発行して

CPUをゲストに渡す

2009年8月30日日曜日

Page 84: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

2009年8月30日日曜日

Page 85: 第二回KVM読書会

以下略

2009年8月30日日曜日

Page 86: 第二回KVM読書会

まとめると...

2009年8月30日日曜日

Page 87: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL センシティブ命令

vmlaunchvmresume

2009年8月30日日曜日

Page 88: 第二回KVM読書会

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

2009年8月30日日曜日

Page 89: 第二回KVM読書会

今回の説明箇所

2009年8月30日日曜日

Page 90: 第二回KVM読書会

outb %ax が発生したと仮定

2009年8月30日日曜日

Page 91: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 92: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax2009年8月30日日曜日

Page 93: 第二回KVM読書会

VMX non Root Modeから

IOのハンドリングまで

2009年8月30日日曜日

Page 94: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 95: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax2009年8月30日日曜日

Page 96: 第二回KVM読書会

どこから再開するのか

2009年8月30日日曜日

Page 97: 第二回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の...

2009年8月30日日曜日

Page 98: 第二回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: "

/* レジスタの復帰 */

...

次の命令

2009年8月30日日曜日

Page 99: 第二回KVM読書会

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

2009年8月30日日曜日

Page 100: 第二回KVM読書会

これから何するの?

2009年8月30日日曜日

Page 101: 第二回KVM読書会

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

2009年8月30日日曜日

Page 102: 第二回KVM読書会

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

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

2009年8月30日日曜日

Page 103: 第二回KVM読書会

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

2009年8月30日日曜日

Page 104: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

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

2009年8月30日日曜日

Page 105: 第二回KVM読書会

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

2009年8月30日日曜日

Page 106: 第二回KVM読書会

Qemuの助けが必要

2009年8月30日日曜日

Page 107: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

2009年8月30日日曜日

Page 108: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2009年8月30日日曜日

Page 109: 第二回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: .... 続く ...

ここにもどってくる

2009年8月30日日曜日

Page 110: 第二回KVM読書会

outbを処理中なので

2009年8月30日日曜日

Page 111: 第二回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が発生したのでここにくる

2009年8月30日日曜日

Page 112: 第二回KVM読書会

次にすることは

2009年8月30日日曜日

Page 113: 第二回KVM読書会

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

IOなのかを判断する

2009年8月30日日曜日

Page 114: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

2009年8月30日日曜日

Page 115: 第二回KVM読書会

どうするか

2009年8月30日日曜日

Page 116: 第二回KVM読書会

out命令のオペランドで

判断

2009年8月30日日曜日

Page 117: 第二回KVM読書会

outb %al

2009年8月30日日曜日

Page 118: 第二回KVM読書会

outb %al

ポート番号が入っている

2009年8月30日日曜日

Page 119: 第二回KVM読書会

ポート番号で

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

2009年8月30日日曜日

Page 120: 第二回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: .... 続く ... 引数に注目

2009年8月30日日曜日

Page 121: 第二回KVM読書会

kvm_handle_iocpu_outb

ioport_write

2009年8月30日日曜日

Page 122: 第二回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は関数ポインタのテーブル

2009年8月30日日曜日

Page 123: 第二回KVM読書会

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

2009年8月30日日曜日

Page 124: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

2009年8月30日日曜日

Page 125: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

2009年8月30日日曜日

Page 126: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

2009年8月30日日曜日

Page 127: 第二回KVM読書会

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

2009年8月30日日曜日

Page 128: 第二回KVM読書会

再度IOCTLを発行して

CPUをゲストに渡す

2009年8月30日日曜日

Page 129: 第二回KVM読書会

コードレベルだと

2009年8月30日日曜日

Page 130: 第二回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 }

2009年8月30日日曜日

Page 131: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

2009年8月30日日曜日

Page 132: 第二回KVM読書会

以下略

2009年8月30日日曜日

Page 133: 第二回KVM読書会

まとめると...

2009年8月30日日曜日

Page 134: 第二回KVM読書会

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

vmlaunch vmresume

センシティブ命令

2009年8月30日日曜日

Page 135: 第二回KVM読書会

以上がメインループの概要

2009年8月30日日曜日

Page 136: 第二回KVM読書会

質問?

2009年8月30日日曜日