Bhyve code reading

  • 907 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
907
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
9
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. BHyVe code reading @syuu1228 1
  • 2. お手元にソースコードをご 用意下さいhttps://github.com/lattera/b hyve 2
  • 3. 1, BHyVe 概要 3
  • 4. BHyVe とは● FreeBSD 版の Linux KVM のようなもの● Intel VT を用いたハイパーバイザ● 開発の初期段階でごく限定的な機能が実装されている             ↓ 最低限のハイパーバイザ実装のよいサンプルになりそう 4
  • 5. Web Sitehttp://www.bhyve.org/ 5
  • 6. 実装状況● Intel VT-x, EPT 必須 (= Nehalem 以降必須 )● BIOS 非対応 (disk ブート出来ない )● 対応デバイス : – PCI ● virtio-net, virtio-blk ● pci passthrough(VT-d) ● pci UART – paravirtual console/debug port 6●
  • 7. 割り込み● MSI 割り込みのみ対応● 割り込みコントローラは Local APIC のみ実装 7
  • 8. 2,動作の流れ 8
  • 9. おさらい: Linux KVM 9
  • 10. Intel VT 向け VMM の動作の流れ1.VMCS にゲスト環境の設定をロード2.CPU に VMCS をセット3.VMLAUNCH でゲストモードに切り替え4.ゲスト環境実行 trap 要因が発生、 VMExit する5.何らかのエミュレー タが欲 しいなら、 QEMU を使 えばいいじゃない 10
  • 11. Linux KVM 動作イメージ QEMU User program IOCTL VMExitLinux kernel KVM Guest kernel VMLAUNCH 11
  • 12. Intel VT 向け VMM の動作の流れ1.VMCS にゲスト環境の設定をロード2.CPU に VMCS をセット3.VMLAUNCH でゲストモードに切り替え4.ゲスト環境実行 白 いところを 要因が発生、 VMExit する5.何らかの trap KVM がやる。黄色 いところを QEMU がやる。 12
  • 13. BHyVe は? 13
  • 14. BHyVe 動作イメージ/usr/sbin/bhyve User program IOCTL(VM_RUN) VMExitBSD kernel vmm.ko Guest kernel VMLAUNCH 14
  • 15. Intel VT 向け VMM の動作の流れ1.VMCS にゲスト環境の設定をロード2.CPU に VMCS をセット3.VMLAUNCH でゲストモードに切り替え4.ゲスト環境実行 白 いところを 要因が発生、 VMExit する5.何らかの trap vmm.ko がやる。黄色 いところを /usr/sbin/bhyve が やる。 15
  • 16. /usr/sbin/bhyve の動作(1)● src/usr.sbin/bhyve/fbsdrun.c:669 fbsdrun_addcpu() で CPU0 のスレッドを作成 – src/usr.sbin/bhyve/fbsdrun.c:209 pthread_create(fbsdrun_start_thread) ● src/usr.sbin/bhyve/fbsdrun.c:195 vm_loop() – src/usr.sbin/bhyve/fbsdrun.c:476 while(1) {vm_run();} 16
  • 17. /usr/sbin/bhyve の動作(2)● src/usr.sbin/bhyve/fbsdrun.c:476 while(1) { vm_run(); – src/lib/libvmmapi/vmmapi.c:265 ioctl(VM_RUN) vmm.ko に VMX non root mode への切り替 えを依頼● src/usr.sbin/bhyve/fbsdrun.c:494 handler[exitcode]() EXIT_REASON に対応するエミュレー ション処理を呼び出し 17
  • 18. 3,ゲスト OS ローダ 18
  • 19. 何故ゲスト OS ローダが必要か● BHyVe には BIOS がない● HDD のブートセクタから起動されるブートローダは BIOS に依存 している為、例え /usr/sbin/bhyve が起動時にブートセクタをロー ドして実行しても動作しない● BIOS のエミュレーションを実装する代わりにゲストの FreeBSD カーネルをゲストメモリ空間にロードして、いきなりカーネルを 実行している 19
  • 20. bhyveload の動作 - vm_create● src/usr.sbin/bhyveload/bhyveload.c:557 vm_create(vmname) で /dev/vmm/%s に device file を作成 – src/lib/libvmmapi/vmmapi.c:85 sysctl 経由で device file 作成を vmm.ko に依頼 20
  • 21. bhyveload の動作 - vm_setup_memory● src/usr.sbin/bhyveload/bhyveload.c:570 vm_setup_memory() で membase へゲスト空間を mmap – src/lib/libvmmapi/vmmapi.c:139 vmm.ko へ ioctl(VM_MAP_MEMORY) でゲスト空間をアロケート vmm.ko への mmap でゲスト空間を membase へマップ 21
  • 22. bhyveload の動作 - vm_open● usr.sbin/bhyveload/bhyveload.c:564 vm_open(vmname) で /dev/vmm/%s を open() – src/lib/libvmmapi/vmmapi.c:92 vm_open() ● src/lib/libvmmapi/vmmapi.c:67 vm_device_open() 22
  • 23. bhyveload の動作 – userboot.so● usr.sbin/bhyveload/bhyveload.c:589 – FreeBSD のブートローダをユーザ空間で動くように移植したも の – メモリやレジスタへの読み書きを wrap 、ゲストのメモリ空間 /レジスタへアクセス – (メモリ空間は mmap 、レジスタの読み書きは ioctl 経由で VMM が管理するゲストのデスクリプタへ) 23
  • 24. bhyveload の動作 – userboot.so● usr.sbin/bhyveload/bhyveload.c:589 dlopen で userboot.so を開く● usr.sbin/bhyveload/bhyveload.c:594 dlsym で loader_main 関数のアドレスを取得● usr.sbin/bhyveload/bhyveload.c:603 loader_main 関数を実行 24
  • 25. bhyveload の動作 – userboot.so● loader_main 関数は boot2 とほぼ同じ動作を行うが、引数で渡 しているコールバック関数で以下のような処理を仮想化して いる – コンソールの読み書き cb_putc, cb_getc, cb_poll – ファイルの操作 cb_open, cb_close, cb_isdir, cb_read, cb_readdir, cb_seek, cb_stat – ディスクの読み書き cb_diskread – メモリの読み書き cb_copyin, cb_copyout, cb_getmem – レジスタの読み書き cb_setreg, cb_setmsr, cb_setcr, cb_setgdt, cb_exec 25
  • 26. bhyveload の動作 – cb_copyin, cb_copyout● src/usr.sbin/bhyveload/bhyveload.c:297 membase へ memcpy● src/usr.sbin/bhyveload/bhyveload.c:313 membase から memcpy 26
  • 27. bhyveload の動作 – cb_setreg, cb_exec● src/usr.sbin/bhyveload/bhyveload.c:327 vm_set_register でレジスタセット● src/usr.sbin/bhyveload/bhyveload.c:434 vm_setup_freebsd_registers でレジスタなどの初期化 – src/lib/libvmmapi/vmmapi_freebsd.c:63 vm_set_register, vm_set_desc で各種レジスタを初期化 27
  • 28. bhyveload の動作 – vm_setup_freebsd_registers● src/lib/libvmmapi/vmmapi_freebsd.c:63 – CR0 = PE | PG | NE # ページング、プロテクトモード – CR4 = PAE | VMXE # PAE 、 VMX 有効 – EFER = LME | LMA # long mode 有効 – GDT 初期化&セグメントレジスタ初期化 – タスクレジスタ初期化 – ページテーブル& CR3 初期化 – RSP 初期化 28
  • 29. 4, IO デバイスエミュレーション 29
  • 30. ゲストカーネルのコンフィグレーションdevice pcidevice bvmconsoledevice bvmdebugdevice mptableACPI や多くのデバイスは無効virtio.ko, if_vtnet.ko, virtio_pci.ko, virtio_blk.ko はモジュールとしてビルド 30
  • 31. IO エミュレーションio emulation 実行 console net blk PCI /usr/sbin/bhyve IOCTL return IO 命令 VMExit BSD kernel vmm.ko Guest kernel 31
  • 32. /usr/sbin/bhyve の動作 – IO emulation● src/usr.sbin/bhyve/fbsdrun.c:494 handler[exitcode]() EXIT_REASON に対応するエミュレー ション処理を呼び出し – src/usr.sbin/bhyve/fbsdrun.c:465 IO の場合は VM_EXITCODE_INOUT なので vmexit_inout ● src/usr.sbin/bhyve/fbsdrun.c:281 EAX の値を取得して emulate_inout() 32
  • 33. /usr/sbin/bhyve の動作 – IO emulation● src/usr.sbin/bhyve/inout.c:72 inout_handers[port].handler(in, port, bytes, eax) port = 0x220 なら console ( src/usr.sbin/bhyve/consport.c:127 で定義) – src/usr.sbin/bhyve/consport.c:101 in = 1 ならキーボードから一文字を読んで eax に書く in = 0 なら eax から一文字読んで画面に書く 33
  • 34. 3, vmm.ko の提供するイ ンタフェース 34
  • 35. sysctl● src/sys/amd64/vmm/vmm_dev.c:387 – hw.vmm.create(name) /dev/vmm/${name} に新しい VM インスタンスを指す デバイスファイルを作成 – hw.vmm.destroy(name) /dev/vmm/${name} の VM インスタンスを削除 35
  • 36. /dev/vmm/${name} へのファイル API● read/write –src/sys/amd64/vmm/vmm_dev.c:184 ゲスト空間の読み書き( offset = ゲストの物理アドレス)● mmap – src/sys/amd64/vmm/vmm_dev.c:347 ゲスト空間のマップ (先頭ポインタがゲストの物理アドレス0番地) 36
  • 37. /dev/vmm/${name} への ioctl (1)● src/sys/amd64/vmm/vmm_dev.c:144● VM_RUN: VMLAUNCH させる● VM_SET_PINNING/VM_GET_PINNING: CPU の固定割当● VM_MAP_MEMORY: ゲストのメモリ空間割当● VM_GET_MEMORY_SEG: 未調査● VM_SET_REGISTER/VM_GET_REGISTER: ゲストレジス 37
  • 38. /dev/vmm/${name} への ioctl(2)● VM_SET_SEGMENT_DESCRIPTOR/VM_GET_SEGMENT_D ESCRIPTOR: セグメントレジスタの読み書き● VM_INJECT_EVENT: 未調査● VM_LAPIC_IRQ: 未調査● VM_SET_CAPABILITY/VM_GET_CAPABILITY: VT-x のどの 機能を使うか(調査中) 38
  • 39. /dev/vmm/${name} への ioctl (3)● VM_PPTDEV_MSI: PCI passthorugh● VM_INJECT_NMI: 未調査● VM_STATS: 未調査● VM_STAT_DESC: 未調査 39