linux kvm のコードを追いかけてみよう
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日木曜日