Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Bhyve Internals

3,939 views

Published on

Published in: Technology
  • Be the first to comment

Bhyve Internals

  1. 1. BHyVe internals @syuu1228 1
  2. 2. 1, BHyVe 概要 2
  3. 3. BHyVe とはFreeBSD 版の Linux KVM のようなものIntel VT を用いたハイパーバイザ開発の初期段階でごく限定的な機能が実装されている             ↓ 最低限のハイパーバイザ実装のよいサンプルになりそう 3
  4. 4. 新しい Web サイトと GSoC web site http://www.bhyve.org/GSoC 2012: BHyVe BIOS emulation to boot legacy systems http://bit.ly/bhyve_bios 4
  5. 5. 実装状況Intel VT-x, EPT 必須 (= Nehalem 以降必須 )BIOS 非対応 (disk ブート出来ない )対応デバイス : virtio-net, virtio-blk pci passthrough(VT-d) paravirtual console/debug port UART対応 OS: FreeBSD 8, 9, 10 5
  6. 6. 動作イメージ/usr/sbin/bhyve User program IOCTL(VM_RUN) VMExit vmm.k GuestBSD kernel o kernel VMLAUNCH 6
  7. 7. 使い方/boot/loader.confhw.physmem="0x100000000" (ホストのメモリ割り当てを減らしてゲスト用の領域を 用意)kldload vmm.ko/usr/sbin/bhyveload -m ${lowmem} -M {highmem} -h {bootdir} $ {vmname}/usr/sbin/bhyve -c ${cpus} -m ${lowmem} -M{highmem} -s 1,virtio-net,tap0 -s 2,virtio-blk,${diskdev} 7
  8. 8. 各コマンドの役割分担/usr/sbin/bhyveload VM インスタンスを作成し、 BSD カーネルを VM インスタンスのメモ リ領域にロードして起動可能な状態を作る/usr/sbin/bhyve bhyveload が初期化した VM インスタンスを実行し、ディス ク、 NIC 、コンソールなどのデバイスエミュレーション処理を行う VM インスタンスの状態は、プロセス内ではなく /dev/vmm/$ {vmname} というデバイス上、つまりカーネル内に保持される。 このファイルへ read(), write(), mmap() する事により VM 内のメモリ空 間にアクセス出来る。 8
  9. 9. bhyveload の動作sysctl(“hw.vmm.create”, vm_name)→ /dev/vmm/${vm_name} を作成open(/dev/vmm/${vm_name})seg.gpa = 0 seg.len = mem_size ioctl(fd, VM_MAP_MEMORY, seg) membase = mmap(NULL, mem_size, PROT_READ| PROT_WRITE, MAP_SHARED, fd, 0) 9
  10. 10. userboot.soFreeBSD のブートローダをユーザ空間で動くように移植し たものメモリやレジスタへの読み書きを wrap 、ゲストのメモリ空 間/レジスタへアクセス (メモリ空間は mmap 、レジスタの読み書きは ioctl 経由 で VMM が管理するゲストのデスクリプタへ)これを利用して kload が実装されている ( Linux における kexec と同じ) 10
  11. 11. bhyve の動作open(/dev/vmm/${vm_name})デバイス初期化pthread_create(fbsdrun_start_thread) fbsdrun_start_thread() { while(1) { ioctl(VM_RUN, &vmexit) handler[vmexit.exitcode](&vmexit, &vcpu); } }メイン関数はデバイスエミュレーションの処理要求イベントを kevent() で待つ 11
  12. 12. デモhttp://www.youtube.com/watch?v=N2TbKzE_puA 12
  13. 13. 2, CPU の初期化と OS のロード 13
  14. 14. vCPU の初期化bhyveload で以下の初期化を実施 CR0 = PE | PG | NE # ページング、プロテクトモード CR4 = PAE | VMXE # PAE 、 VMX 有効 EFER = LME | LMA # long mode 有効 GDT 初期化&セグメントレジスタ初期化 タスクレジスタ初期化 ページテーブル& CR3 初期化 RSP 初期化 14 エントリポイント設定
  15. 15. mptable の初期化/usr/sbin/bhyve から実行(引数の CPU 数を使用)(未実装な ACPI を使わずに)セカンダリ CPU の情報を OS に伝えるBIOS ROM 領域上にテーブルを用意PCI デバイスや割り込みの情報の伝達にも使ってる? 15
  16. 16. bhyveload の役割ホストのユーザ空間でブートローダを起動して、カーネル をロードする為のレジスタ/セグメント/ページテーブ ルの初期化を行うゲストはいきなり 64bit モードでカーネルを実行 16
  17. 17. 3, IO デバイスエミュレーション 17
  18. 18. ゲストカーネルのコンフィグレーションdevice pcidevice bvmconsoledevice bvmdebugdevice mptable ACPI や多くのデバイスは無効 virtio.ko, if_vtnet.ko, virtio_pci.ko, virtio_blk.ko はモジュール としてビルド 18
  19. 19. IO エミュレーションio emulation 実行 consol net blk e PCI /usr/sbin/bhyve IOCTL return VMExit IO 命令 vmm.k Guest BSD kernel o kernel 19
  20. 20. IO エミュレーションゲスト OS が in/out 命令を実行、 VMExitvmm.ko で EXIT_REASON_INOUT をハンドルVM_EXITCODE_INOUT で ioctl を return 、カーネルから /usr/ sbin/bhyve へ制御を移すhandler[VM_EXITCODE_INOUT]()       ↓ inout_handlers[port].handler() の順にハンドラがコールされ、 IO ポートに割り当てられ たハンドラが実行される 20
  21. 21. bvm_consoleIO 空間の 0x220 に inl / outl で読み書きゲストドライバ int getc(void) { return inl(0x220); } void putc(int c) { outl(0x220, c); } 割り込みなどない。VMM if (in) { read(fd, &c, 1); *eax = (c & 0xff); }else write(fd, *eax, 1); 21
  22. 22. PCI バスCONFIG_ADDRESS レジスタ: 0xcf8CONFIG_DATA レジスタ: 0xcfc – 0xcff各仮想 PCI デバイスは初期化時に自分のコンフィグレジス タの値を設定各仮想 PCI デバイスの IO レジスタはデバイス初期化時に動 的に確保 22
  23. 23. PCI デバイスの MSI 割り込みサポートPCI 割り込みとして MSI 割り込みのみサポートデバイス初期化時に configuration space 上の MSI capable フラグを 有効化/usr/sbin/bhyve からの割り込み要求は、 VM_LAPIC_IRQ ioctl とし て vmm.ko へ送られる 引数として cpuid と vector ナンバを指定vmm.ko で ioctl を受けて vlapic にレジスタ値をセットvmlaunch 前に vlapic の値をチェックして、割り込みがあったら VMCS にフラグをセット 23
  24. 24. MSR register のエミュレーションLocal APIC をエミュレートする為に、 wrmsr/rdmsr 命令で VMExit を発生させ、エミュレーションを行なっているほぼ vmm.ko でエミュレーションを行なっているが、初期 化周りの一部の処理で /usr/sbin/bhyve へエミュレーション を行わせている 24
  25. 25. タイマーLocal APIC Timer vmlaunch 前にタイマーの値を計算、 vlapic へ割り込みを設定 vmm.ko 内でエミュレーションTSC rdtsc を trap していないように見える (その場合どうなるんだろう??)PIT 8254 /usr/sbin/bhybe で IO ポートアクセスのエミュレーションをして いる 割り込むコードが見当たらないような…?? 25
  26. 26. virtio-net, blkPCI デバイス、 IO エミュレーションと MSI 割り込みを使用/usr/sbin/bhyve でエミュレーションMMIO は使っていない (そもそも MMIO に対応していないっぽい…) 26
  27. 27. pci passthrough(VT-d)デフォルトでは使わないIntel VT-d を使って PCI デバイスをゲストに割り当てる機能物理デバイス→ゲストへの割り込み転送は vmm.ko 内で行な っているが、 io は一度 /usr/sbin/bhyve へ戻しているよう に見えるMMIO 空間は EPT 経由でゲストにマップしている模様 27
  28. 28. UART( bvm_console がダサいので)最近実装されましたてっきり PC の COM ポートをエミュレーション出来るよう にしたのかと思ったら、なんと PCI デバイス…。Siig CyberSerial 1-port と自己申告IOAPIC 未実装だから割り込みも未実装\ (^o^) / 28
  29. 29. まとめたったこれだけのデバイスエミュレーションで、 (ちょっと苦しいけど)ゲスト OS が動く事が分かる 但し、準仮想化デバイスを幾つか使っているのでゲスト側ドライ バが必須現状では FreeBSD しか動かないが、 FreeBSD カーネルに 依存している訳ではない事がわかる bhyveload を fork して自分の起動したい OS に対応したものを書 けば、動きそう 29
  30. 30. おまけBHyVe Hackathon 参加者募集中 http://bit.ly/bhyve_hackathon 詳しくは @syuu1228 まで 30

×