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

Post on 10-May-2015

6417 Views

Category:

Technology

6 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

Transcript

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

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

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

12009年8月13日木曜日

本日のメニュー

22009年8月13日木曜日

1. VMMって何やってるの

2. Intel-VT

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

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

32009年8月13日木曜日

VMMって何やってるの

42009年8月13日木曜日

VMM

52009年8月13日木曜日

Virtual Machine Monitor

62009年8月13日木曜日

Virtual Machine Monitor

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

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

72009年8月13日木曜日

VMMにも

色々ある

82009年8月13日木曜日

ハードウェアを

全て物真似する方式

92009年8月13日木曜日

エミュレーション方式

102009年8月13日木曜日

代表例 Qemu

112009年8月13日木曜日

ユーザ空間で動作

122009年8月13日木曜日

ユーザモード

特権モード

132009年8月13日木曜日

特権モード

Qemu

142009年8月13日木曜日

ところで

152009年8月13日木曜日

一般的なCPUの挙動

162009年8月13日木曜日

ALU...

movl %eax %ebx...

Main Memory

172009年8月13日木曜日

ALU...

movl %eax %ebx...

Main Memory

fetch

182009年8月13日木曜日

Qemuだと...

192009年8月13日木曜日

特権モード

Qemu

ALU...

movl %eax %ebx...

Main Memory

fetch

202009年8月13日木曜日

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

擬似コード

212009年8月13日木曜日

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

擬似コードmov命令

jmp命令

222009年8月13日木曜日

欠点

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

232009年8月13日木曜日

対策

動的バイナリ変換

242009年8月13日木曜日

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

execute(mid_ops);

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

252009年8月13日木曜日

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

execute(mid_ops);

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

262009年8月13日木曜日

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

execute(mid_ops);

擬似コード一気に実行

272009年8月13日木曜日

対策

フェッチ処理が軽くなる

282009年8月13日木曜日

でも遅い

292009年8月13日木曜日

エミュレーション方式

• ユーザ空間だけで動作

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

• 工夫しても遅い

302009年8月13日木曜日

命令の実行

全部

エミュレーション

ではなくて

312009年8月13日木曜日

命令の実行

ほとんど

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

322009年8月13日木曜日

ほとんど実機で動く

方式のVMM

332009年8月13日木曜日

KVMはこちらの方式

342009年8月13日木曜日

ほとんど実機で実行

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

352009年8月13日木曜日

サンプルプログラム.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日木曜日

このプログラムは?

./a.out

hello,gas!

372009年8月13日木曜日

このプログラムは?

いわゆるHello world

382009年8月13日木曜日

このプログラムは?

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

392009年8月13日木曜日

このプログラムは?

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

402009年8月13日木曜日

このプログラムは?

標準出力に書き込み

412009年8月13日木曜日

このプログラムは?

仮想端末に書き込み

422009年8月13日木曜日

このプログラムは?

仮想端末に対して

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

432009年8月13日木曜日

write システムコール

仮想端末に対して

out 命令を発行する

442009年8月13日木曜日

実行.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日木曜日

実行

...

outb %ax

...

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

462009年8月13日木曜日

Program

CPU

実機の挙動

Display

outb472009年8月13日木曜日

実行結果

hello,gas!

482009年8月13日木曜日

命令の実行

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

492009年8月13日木曜日

命令の実行

•VM上で

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

502009年8月13日木曜日

実行.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日木曜日

実行

...

outb $hogehoge

...

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

522009年8月13日木曜日

実行

hello,gas!

532009年8月13日木曜日

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

542009年8月13日木曜日

Program

VirtualCPU

VMの挙動

outb

VirtualDisplay

552009年8月13日木曜日

Program

VirtualCPU

VMの挙動

RealDisplay

outb562009年8月13日木曜日

実行

hello,gas!on host system?!

572009年8月13日木曜日

それはまずい

582009年8月13日木曜日

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

592009年8月13日木曜日

センシティブ命令

602009年8月13日木曜日

センシティブ命令は

どうあつかうのか

612009年8月13日木曜日

Program

仮想CPU

VM上のout 命令

VirtualDisplay

622009年8月13日木曜日

Program

仮想CPU

VM上のout 命令

outb

VirtualDisplay

632009年8月13日木曜日

VM上のout 命令

ここでトラップ発生

642009年8月13日木曜日

ホスト側の処理

trap

EmuCode

CPU

652009年8月13日木曜日

ホスト側の処理

handle

EmuCode

CPU

662009年8月13日木曜日

VM上のout 命令retEmu

Code

CPU

672009年8月13日木曜日

Program

仮想CPU

VM上のout 命令

VirtualDisplay

ack

682009年8月13日木曜日

VM上のout 命令

あたかも

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

692009年8月13日木曜日

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

702009年8月13日木曜日

ところが

712009年8月13日木曜日

x86はそんなに甘くない

722009年8月13日木曜日

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

センシティブ命令

特権命令

すべての命令

732009年8月13日木曜日

という包含関係が

成立

742009年8月13日木曜日

なぜ?

752009年8月13日木曜日

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

センシティブ命令

特権命令

すべての命令

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

762009年8月13日木曜日

ところがどっこい

772009年8月13日木曜日

x86は仮想化可能?

センシティブ命令

特権命令

すべての命令

782009年8月13日木曜日

あれ...不可能?

792009年8月13日木曜日

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

802009年8月13日木曜日

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

812009年8月13日木曜日

x86の仮想化

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

• Hypervisor Call

• Xenのアプローチ

822009年8月13日木曜日

x86の仮想化

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

• LilyVMのアプローチ

832009年8月13日木曜日

x86の仮想化

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

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

• VMWareのアプローチ

842009年8月13日木曜日

でも大変

852009年8月13日木曜日

Intel、なんとかして

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

862009年8月13日木曜日

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

ところで

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

882009年8月13日木曜日

ホスト側

User

Privilege

892009年8月13日木曜日

ゲスト側

User

Privilege

902009年8月13日木曜日

自由に行き来できる

912009年8月13日木曜日

User

Privilege

User

Privilegewarp

922009年8月13日木曜日

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

932009年8月13日木曜日

User

Privilege

User

Privilege

942009年8月13日木曜日

User

Privilege

User

Privilege

センシティブ命令

952009年8月13日木曜日

User

Privilege

User

Privilegetrap

962009年8月13日木曜日

User

Privilege

User

Privilege

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

User

Privilege

こちら側

982009年8月13日木曜日

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

992009年8月13日木曜日

User

Privilege

こちら側

1002009年8月13日木曜日

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

1012009年8月13日木曜日

VMX non Root Modeに

なるための命令

1022009年8月13日木曜日

User

Privilege

User

Privilege

コレ

1032009年8月13日木曜日

vmlaunchvmresume

1042009年8月13日木曜日

ここからようやくKVMの話

1052009年8月13日木曜日

KVMとは

1062009年8月13日木曜日

Kernel-basedVirtul Machine

1072009年8月13日木曜日

略してKVM

1082009年8月13日木曜日

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

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

1092009年8月13日木曜日

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

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

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

KVMが行っていること

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

1112009年8月13日木曜日

やること意外と多い

1122009年8月13日木曜日

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

1132009年8月13日木曜日

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

1142009年8月13日木曜日

KVMの概要

1152009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1162009年8月13日木曜日

見方

1172009年8月13日木曜日

VMXRoot Mode

VMXnon Root

Mode

1182009年8月13日木曜日

ユーザモード

特権モード

1192009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1202009年8月13日木曜日

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

1212009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1222009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

生じる

1232009年8月13日木曜日

./qemu -hda disk1.img

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

1242009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

$ ./qemu -hda disk1

1252009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

Qemuの初期化を行う

1262009年8月13日木曜日

Qemuの初期化が終わったら

1272009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1282009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1292009年8月13日木曜日

特権モードに切り替え

1302009年8月13日木曜日

なぜか

1312009年8月13日木曜日

vmlaunchvmresumeは

特権命令

1322009年8月13日木曜日

次に、VMX non Root

Modeになる準備をする

1332009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel VTを使って

モード遷移をする準備

1342009年8月13日木曜日

準備ができたら

1352009年8月13日木曜日

vmlaunchvmresumeを発行

1362009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

1372009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1382009年8月13日木曜日

無事にVMX non root Mode に

なりました

1392009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1402009年8月13日木曜日

1412009年8月13日木曜日

VMX non Root Modeから

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

1422009年8月13日木曜日

そうこうしているうちに

1432009年8月13日木曜日

outb %ax が発生したと仮定

1442009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1452009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax1462009年8月13日木曜日

処理がVMX Root Modeに

移る

1472009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1482009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

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

1492009年8月13日木曜日

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

1502009年8月13日木曜日

Qemuの助けが必要

1512009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

1522009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1532009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

1542009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

1552009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

1562009年8月13日木曜日

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

1572009年8月13日木曜日

再度IOCTLを発行して

CPUをゲストに渡す

1582009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1592009年8月13日木曜日

以下略

1602009年8月13日木曜日

まとめると...

1612009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

vmlaunch vmresume

センシティブ命令

1622009年8月13日木曜日

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

1632009年8月13日木曜日

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

1642009年8月13日木曜日

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

kvm-85

1652009年8月13日木曜日

まずは

1662009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1672009年8月13日木曜日

Qemu起動するところ

1682009年8月13日木曜日

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

1692009年8月13日木曜日

qemu/vl.cのmain.c

に処理がとぶ

1702009年8月13日木曜日

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日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1722009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

Qemuの初期化を行う

1732009年8月13日木曜日

起動 - 初期化

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

1742009年8月13日木曜日

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

1752009年8月13日木曜日

初期化のコールグラフ

1762009年8月13日木曜日

pc_init1pc_new_cpu

cpu_init = cpu_x86_initkvm_init_cpu

pthread_createap_main_loop

kvm_main_loop_cpu1772009年8月13日木曜日

初期化が終わったら

1782009年8月13日木曜日

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

1792009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1802009年8月13日木曜日

橋渡しはIOCTL

システムコール

1812009年8月13日木曜日

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

qemu/kvm-all.ckvm_cpu_exec

1822009年8月13日木曜日

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日木曜日

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日木曜日

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日木曜日

あった!

1862009年8月13日木曜日

IOCTLを発行すると

1872009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

1882009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

1892009年8月13日木曜日

特権モードに切り替わる

1902009年8月13日木曜日

行き先はどこか

1912009年8月13日木曜日

IOCTLのハンドラ

1922009年8月13日木曜日

IOCTLのハンドラは

いつ登録するの?

1932009年8月13日木曜日

初期化時に登録する

1942009年8月13日木曜日

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日木曜日

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

file->f_op = kvm_vcpu_fops;

1962009年8月13日木曜日

kvm_vcpu_ioctl に

処理が移る

1972009年8月13日木曜日

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日木曜日

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

1992009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel VTを使って

モード遷移をする準備

2002009年8月13日木曜日

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

2012009年8月13日木曜日

kvm_arch_vcpu_ioctl_run

__vcpu_run

vcpu_enter_guest

vmx_vcpu_run

コールグラフ

2022009年8月13日木曜日

vmx_vcpu_runkernel/x86/vmx.c

2032009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

2042009年8月13日木曜日

を発行するところ

2052009年8月13日木曜日

コード読んでみましょう

2062009年8月13日木曜日

include/asm-x86/vmx.h

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

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

2072009年8月13日木曜日

命令を

バイナリ直打ち

2082009年8月13日木曜日

vmlaunch/vmresumeを発行すると

2092009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

vmlaunch / vmresume

2102009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2112009年8月13日木曜日

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

2122009年8月13日木曜日

さて折り返し

2132009年8月13日木曜日

VMX non Root Modeから

IOのハンドリングまで

2142009年8月13日木曜日

追います

2152009年8月13日木曜日

そうこうしているうちに

2162009年8月13日木曜日

outb %ax が発生したと仮定

2172009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2182009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

outb %ax2192009年8月13日木曜日

どこから再開するのか

2202009年8月13日木曜日

"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日木曜日

"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日木曜日

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

2232009年8月13日木曜日

これから何するの?

2242009年8月13日木曜日

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

2252009年8月13日木曜日

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

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

2262009年8月13日木曜日

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

2272009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel なぜ

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

2282009年8月13日木曜日

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

2292009年8月13日木曜日

Qemuの助けが必要

2302009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTLから一旦return

2312009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

2322009年8月13日木曜日

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日木曜日

outbを処理中なので

2342009年8月13日木曜日

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日木曜日

次にすることは

2362009年8月13日木曜日

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

IOなのかを判断する

2372009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

2382009年8月13日木曜日

どうするか

2392009年8月13日木曜日

out命令のオペランドで

判断

2402009年8月13日木曜日

outb %al

2412009年8月13日木曜日

outb %al

ポート番号が入っている

2422009年8月13日木曜日

ポート番号で

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

2432009年8月13日木曜日

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日木曜日

kvm_handle_iocpu_outb

ioport_write

2452009年8月13日木曜日

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日木曜日

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

2472009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

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

判断

2482009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

エミュレーションを行う

2492009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

結果がメモリ上の

仮想ハードウェアに反映

2502009年8月13日木曜日

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

2512009年8月13日木曜日

再度IOCTLを発行して

CPUをゲストに渡す

2522009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

2532009年8月13日木曜日

以下略

2542009年8月13日木曜日

まとめると...

2552009年8月13日木曜日

Qemu

KVM

UserProgram

GuestKernel

LinuxKernel

IOCTL

vmlaunch vmresume

センシティブ命令

2562009年8月13日木曜日

コードレベルだと

2572009年8月13日木曜日

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日木曜日

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

2592009年8月13日木曜日

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

Twitterでお願いします

2602009年8月13日木曜日

top related