Upload
tsuyoshi-ozawa
View
3.246
Download
0
Tags:
Embed Size (px)
DESCRIPTION
第二回KVM読書会のスライドです. Intel-VT と Linux KVM の概要についてまとめました.
Citation preview
KVM読書会第二回
Tsuyoshi Ozawa @ Univ. of TsukubaTwitter oza_x86
2009年8月30日日曜日
本日の内容1. Intel-VTの概要2. KVMの概要(その2)
2009年8月30日日曜日
Intel-VTの概要
2009年8月30日日曜日
プロテクションモデル
2009年8月30日日曜日
リングプロテクションでIntel-VT
1.仮想化の支援機構2.VMを簡単に実装するための CPUの機能
x86の保護モデルと密接な関係がある
2009年8月30日日曜日
x86の保護モデル(リングプロテクション)
数字が低いほど特権レベルが高い( 0 が最強 )
OSはRing 0 で動作
ユーザプログラムはRing3で動く
OSの機能を使いたいときは儀式を行う
Kernel Mode
Ring3 = User Mode
Ring2
Ring1
Ring0
2009年8月30日日曜日
リングプロテクションで保護されているもの
1.命令の発行2.メモリのアクセス
2009年8月30日日曜日
Ring3 から Ring0 へのアクセス
Kernel Mode
Ring3
Ring2
Ring1
Ring0
User Mode
2009年8月30日日曜日
Kernel Mode
Ring3
Ring2
Ring1
Ring0
ここで out 命令
User Mode
Ring3 から Ring0 へのアクセス
2009年8月30日日曜日
Kernel Mode
Ring3
Ring2
Ring1
Ring0
ここで out 命令
User Mode
Ring3 から Ring0 へのアクセス
ダメ!(例外を発生)
2009年8月30日日曜日
Kernel Mode
Ring3 = User Mode
Ring2
Ring1
Ring0
ここで out 命令
Ring3 から Ring0 へのアクセス
例外に対応した例外ハンドラが動作する
2009年8月30日日曜日
「VMが動作する」とは?
仮想的なCPU、メモリ、マザーボード etc...
がたくさんある
2009年8月30日日曜日
「VMが動作する」とは?
Kernel Mode
Kernel Mode
実機 仮想CPU
2009年8月30日日曜日
どうやって実装するの?
2009年8月30日日曜日
Xen や VMWare のモデル
HyperVisor
Ring3
Ring2
Ring1
Ring0
OSを書き換える
Ring1 = Guest Kerel
2009年8月30日日曜日
Xen や VMWare のモデル
Kernel Mode
Kernel Mode
Hypervirsor on 実機 Guest kernel on 仮想CPU
実は Ring 1Ring 1 とRing 2 は通常使われない
2009年8月30日日曜日
Intel-VT がやっていることも
同じ
2009年8月30日日曜日
Intel-VT の概要
Kernel Mode
Hypervirsor on 実機 Guest kernel on 仮想CPU
Kernel Mode
2009年8月30日日曜日
Intel-VT の概要
Kernel Mode
Hypervirsor on 実機 Guest kernel on 仮想CPU
実は Guest OS 専用モード
Kernel Mode
2009年8月30日日曜日
Intel-VT の概要
Kernel Mode
Hypervirsor on 実機 Guest kernel on 仮想CPU
あるCPUステートじゃないとダメ.
Kernel Mode
2009年8月30日日曜日
Intel-VTの用語
Hypervirsor on 実機 Guest kernel on 仮想CPU
VMX Root Mode
Kernel Mode
Kernel Mode
2009年8月30日日曜日
VMX Root Mode になるための命令
Hypervirsor on 実機
VMXON初期化命令.
A20信号線を無効にするVT用の命令が発効できるようになる
Kernel Mode
2009年8月30日日曜日
VMX Root Mode から戻る命令
Hypervirsor on 実機
VMXOFFVT終了命令.
VT周りの命令が使えなくなる
Kernel Mode
2009年8月30日日曜日
Intel-VTの用語
Hypervirsor on 実機 Guest kernel on 仮想CPU
VMX non Root Mode
Kernel Mode
Kernel Mode
2009年8月30日日曜日
Intel-VTの用語
Hypervirsor on 実機 Guest kernel on 仮想CPU
VMX non Root Mode
VMEntry
Kernel Mode
Kernel Mode
2009年8月30日日曜日
VMEntry を発生させる命令
VMLAUNCHVMRESUME
VMX non Root Modeに移行する
2009年8月30日日曜日
Intel-VTの用語
Hypervirsor on 実機 Guest kernel on 仮想CPU
VMExit
Kernel Mode
Kernel Mode
2009年8月30日日曜日
VMExit を発生させる命令
VMMCALL+その他例外
VMX non Root Modeに移行する
2009年8月30日日曜日
その他例外について
•設定に沿った例外を生じる.RDTSC (時間を読み取る)を発行しただけで例外を発生させるように設定することも可能
•「設定」を保存する場所
VMCS構造体
2009年8月30日日曜日
VMCSのイメージ
Hypervirsor on 実機
Memory
VMCS
Kernel Mode
2009年8月30日日曜日
VMCS構造体とは
Virtual Machine Control Structure
4KB の構造体命令でメモリアドレスをセットする
2009年8月30日日曜日
VMCS構造体とは
•Virtual Machine Control Structure
•4KB の構造体•保存するもの 例外の引き起こす命令の設定 プログラムカウンタの値 各種レジスタの値 VMのメモリ開始位置 etc...
2009年8月30日日曜日
VMCSを設定する命令
Current VMCSを設定
VMPTRST
2009年8月30日日曜日
Kernel Mode
VMPTRSTのイメージ
Hypervirsor on 実機
Memory
VMCSここがVMCSだよ!
2009年8月30日日曜日
Current VMCSをロードする命令
Current VMCSのアドレスを取得
VMPTRLD
2009年8月30日日曜日
Kernel Mode
VMPTRSTのイメージ
Hypervirsor on 実機
Memory
VMCSこの番地にCurrent VMCSあるよ
2009年8月30日日曜日
VMCLEAR
VMCSを初期化する
2009年8月30日日曜日
Kernel Mode
VMCLEARのイメージ
Hypervirsor on 実機
Memory
VMCS初期化して!
2009年8月30日日曜日
VMCSを読み書き
VMREAD/VMWRITE
2009年8月30日日曜日
Kernel Mode
VMWRITEのイメージ
Hypervirsor on 実機
Memory
VMCSココの値はこうして!
2009年8月30日日曜日
Kernel Mode
VMREADのイメージ
Hypervirsor on 実機
Memory
VMCSココの値はこうだよ!
2009年8月30日日曜日
詳細はIntelのマニュアル(英語版)参照
2009年8月30日日曜日
KVMの概要
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
見方
2009年8月30日日曜日
VMXRoot Mode
VMXNonRoot
Mode
2009年8月30日日曜日
ユーザモード
特権モード
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
起動からVMX non Root Modeになるまで
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
KVMのブートはQemuを起動することで
生じる
2009年8月30日日曜日
./qemu -hda disk1.img
(-hda は起動ディスクを指定するオプション)
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
$ ./qemu -hda disk1
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
Qemuの初期化を行う
2009年8月30日日曜日
Qemuの初期化が終わったら
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTL
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
特権モードに切り替え
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel VTを使って
モード遷移をする準備
2009年8月30日日曜日
VMX non Root Modeに
なるための命令
2009年8月30日日曜日
vmlaunchvmresume
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
vmlaunch / vmresume
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
無事にVMX non root Mode に
なりました
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
次
2009年8月30日日曜日
VMX non Root Modeから
IOのハンドリングまで
2009年8月30日日曜日
そうこうしているうちに
2009年8月30日日曜日
outb %ax が発生したと仮定
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
outb %ax2009年8月30日日曜日
処理がVMX Root Modeに
移る
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel なぜ
ゲストから処理が渡されたのか特定
2009年8月30日日曜日
エミュレーションの場合は
2009年8月30日日曜日
Qemuの助けが必要
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTLから一旦return
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
どのハードウェアにio命令が来たか
判断
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
エミュレーションを行う
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
結果がメモリ上の
仮想ハードウェアに反映
2009年8月30日日曜日
エミュレーションが終了したら
2009年8月30日日曜日
再度IOCTLを発行して
CPUをゲストに渡す
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTL
2009年8月30日日曜日
以下略
2009年8月30日日曜日
まとめると...
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTL センシティブ命令
vmlaunchvmresume
2009年8月30日日曜日
これがおおざっぱなメインループ
2009年8月30日日曜日
今回の説明箇所
2009年8月30日日曜日
outb %ax が発生したと仮定
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
outb %ax2009年8月30日日曜日
VMX non Root Modeから
IOのハンドリングまで
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
outb %ax2009年8月30日日曜日
どこから再開するのか
2009年8月30日日曜日
"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日日曜日
"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日日曜日
次の命令から再開はいいけど
2009年8月30日日曜日
これから何するの?
2009年8月30日日曜日
out命令のエミュレーション
2009年8月30日日曜日
なぜ out 命令のエミュレーションと特定できるのか?
in 命令かもしれないじゃん.
2009年8月30日日曜日
Intel-VTの機能でモード遷移の原因がわかる
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel なぜ
ゲストから処理が渡されたのか特定
2009年8月30日日曜日
エミュレーションの場合は
2009年8月30日日曜日
Qemuの助けが必要
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTLから一旦return
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
2009年8月30日日曜日
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日日曜日
outbを処理中なので
2009年8月30日日曜日
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日日曜日
次にすることは
2009年8月30日日曜日
どの仮想ハードウェアに対する
IOなのかを判断する
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
どのハードウェアにio命令が来たか
判断
2009年8月30日日曜日
どうするか
2009年8月30日日曜日
out命令のオペランドで
判断
2009年8月30日日曜日
outb %al
2009年8月30日日曜日
outb %al
ポート番号が入っている
2009年8月30日日曜日
ポート番号で
ルーティング(実機と同じ判断方法!)
2009年8月30日日曜日
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日日曜日
kvm_handle_iocpu_outb
ioport_write
2009年8月30日日曜日
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日日曜日
デバイスによって処理を分岐できる(実機と同じルーティング方法)
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
どのハードウェアにio命令が来たか
判断
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
エミュレーションを行う
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
結果がメモリ上の
仮想ハードウェアに反映
2009年8月30日日曜日
エミュレーションが終了したら
2009年8月30日日曜日
再度IOCTLを発行して
CPUをゲストに渡す
2009年8月30日日曜日
コードレベルだと
2009年8月30日日曜日
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日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTL
2009年8月30日日曜日
以下略
2009年8月30日日曜日
まとめると...
2009年8月30日日曜日
Qemu
KVM
UserProgram
GuestKernel
LinuxKernel
IOCTL
vmlaunch vmresume
センシティブ命令
2009年8月30日日曜日
以上がメインループの概要
2009年8月30日日曜日
質問?
2009年8月30日日曜日